1045 return "mul\t%0,%1,%2"; 1046 return "mult\t%0,%1,%2"; 1047} 1048 [(set_attr "type" "imul3,imul") 1049 (set_attr "mode" "SI")]) 1050 1051(define_insn "muldi3_mult3" 1052 [(set (match_operand:DI 0 "register_operand" "=d") 1053 (mult:DI (match_operand:DI 1 "register_operand" "d") 1054 (match_operand:DI 2 "register_operand" "d"))) 1055 (clobber (match_scratch:DI 3 "=h")) 1056 (clobber (match_scratch:DI 4 "=l"))] 1057 "TARGET_64BIT && GENERATE_MULT3_DI" 1058 "dmult\t%0,%1,%2" 1059 [(set_attr "type" "imul3") 1060 (set_attr "mode" "DI")]) 1061 1062;; If a register gets allocated to LO, and we spill to memory, the reload 1063;; will include a move from LO to a GPR. Merge it into the multiplication 1064;; if it can set the GPR directly. 1065;; 1066;; Operand 0: LO 1067;; Operand 1: GPR (1st multiplication operand) 1068;; Operand 2: GPR (2nd multiplication operand) 1069;; Operand 3: HI 1070;; Operand 4: GPR (destination) 1071(define_peephole2 1072 [(parallel 1073 [(set (match_operand:SI 0 "register_operand") 1074 (mult:SI (match_operand:SI 1 "register_operand") 1075 (match_operand:SI 2 "register_operand"))) 1076 (clobber (match_operand:SI 3 "register_operand")) 1077 (clobber (scratch:SI))]) 1078 (set (match_operand:SI 4 "register_operand") 1079 (unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] 1080 "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])" 1081 [(parallel 1082 [(set (match_dup 4) 1083 (mult:SI (match_dup 1) 1084 (match_dup 2))) 1085 (clobber (match_dup 3)) 1086 (clobber (match_dup 0))])]) 1087 1088(define_insn "mul<mode>3_internal" 1089 [(set (match_operand:GPR 0 "register_operand" "=l") 1090 (mult:GPR (match_operand:GPR 1 "register_operand" "d") 1091 (match_operand:GPR 2 "register_operand" "d"))) 1092 (clobber (match_scratch:GPR 3 "=h"))] 1093 "!TARGET_FIX_R4000" 1094 "<d>mult\t%1,%2" 1095 [(set_attr "type" "imul") 1096 (set_attr "mode" "<MODE>")]) 1097 1098(define_insn "mul<mode>3_r4000" 1099 [(set (match_operand:GPR 0 "register_operand" "=d") 1100 (mult:GPR (match_operand:GPR 1 "register_operand" "d") 1101 (match_operand:GPR 2 "register_operand" "d"))) 1102 (clobber (match_scratch:GPR 3 "=h")) 1103 (clobber (match_scratch:GPR 4 "=l"))] 1104 "TARGET_FIX_R4000" 1105 "<d>mult\t%1,%2\;mflo\t%0" 1106 [(set_attr "type" "imul") 1107 (set_attr "mode" "<MODE>") 1108 (set_attr "length" "8")]) 1109 1110;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead 1111;; of "mult; mflo". They have the same latency, but the first form gives 1112;; us an extra cycle to compute the operands. 1113 1114;; Operand 0: LO 1115;; Operand 1: GPR (1st multiplication operand) 1116;; Operand 2: GPR (2nd multiplication operand) 1117;; Operand 3: HI 1118;; Operand 4: GPR (destination) 1119(define_peephole2 1120 [(parallel 1121 [(set (match_operand:SI 0 "register_operand") 1122 (mult:SI (match_operand:SI 1 "register_operand") 1123 (match_operand:SI 2 "register_operand"))) 1124 (clobber (match_operand:SI 3 "register_operand"))]) 1125 (set (match_operand:SI 4 "register_operand") 1126 (unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] 1127 "ISA_HAS_MACC && !GENERATE_MULT3_SI" 1128 [(set (match_dup 0) 1129 (const_int 0)) 1130 (parallel 1131 [(set (match_dup 0) 1132 (plus:SI (mult:SI (match_dup 1) 1133 (match_dup 2)) 1134 (match_dup 0))) 1135 (set (match_dup 4) 1136 (plus:SI (mult:SI (match_dup 1) 1137 (match_dup 2)) 1138 (match_dup 0))) 1139 (clobber (match_dup 3))])]) 1140 1141;; Multiply-accumulate patterns 1142 1143;; For processors that can copy the output to a general register: 1144;; 1145;; The all-d alternative is needed because the combiner will find this 1146;; pattern and then register alloc/reload will move registers around to 1147;; make them fit, and we don't want to trigger unnecessary loads to LO. 1148;; 1149;; The last alternative should be made slightly less desirable, but adding 1150;; "?" to the constraint is too strong, and causes values to be loaded into 1151;; LO even when that's more costly. For now, using "*d" mostly does the 1152;; trick. 1153(define_insn "*mul_acc_si" 1154 [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") 1155 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") 1156 (match_operand:SI 2 "register_operand" "d,d,d")) 1157 (match_operand:SI 3 "register_operand" "0,l,*d"))) 1158 (clobber (match_scratch:SI 4 "=h,h,h")) 1159 (clobber (match_scratch:SI 5 "=X,3,l")) 1160 (clobber (match_scratch:SI 6 "=X,X,&d"))] 1161 "(TARGET_MIPS3900 1162 || ISA_HAS_MADD_MSUB) 1163 && !TARGET_MIPS16" 1164{ 1165 static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" }; 1166 if (which_alternative == 2) 1167 return "#"; 1168 if (ISA_HAS_MADD_MSUB && which_alternative != 0) 1169 return "#"; 1170 return madd[which_alternative]; 1171} 1172 [(set_attr "type" "imadd,imadd,multi") 1173 (set_attr "mode" "SI") 1174 (set_attr "length" "4,4,8")]) 1175 1176;; Split the above insn if we failed to get LO allocated. 1177(define_split 1178 [(set (match_operand:SI 0 "register_operand") 1179 (plus:SI (mult:SI (match_operand:SI 1 "register_operand") 1180 (match_operand:SI 2 "register_operand")) 1181 (match_operand:SI 3 "register_operand"))) 1182 (clobber (match_scratch:SI 4)) 1183 (clobber (match_scratch:SI 5)) 1184 (clobber (match_scratch:SI 6))] 1185 "reload_completed && !TARGET_DEBUG_D_MODE 1186 && GP_REG_P (true_regnum (operands[0])) 1187 && GP_REG_P (true_regnum (operands[3]))" 1188 [(parallel [(set (match_dup 6) 1189 (mult:SI (match_dup 1) (match_dup 2))) 1190 (clobber (match_dup 4)) 1191 (clobber (match_dup 5))]) 1192 (set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))] 1193 "") 1194 1195;; Splitter to copy result of MADD to a general register 1196(define_split 1197 [(set (match_operand:SI 0 "register_operand") 1198 (plus:SI (mult:SI (match_operand:SI 1 "register_operand") 1199 (match_operand:SI 2 "register_operand")) 1200 (match_operand:SI 3 "register_operand"))) 1201 (clobber (match_scratch:SI 4)) 1202 (clobber (match_scratch:SI 5)) 1203 (clobber (match_scratch:SI 6))] 1204 "reload_completed && !TARGET_DEBUG_D_MODE 1205 && GP_REG_P (true_regnum (operands[0])) 1206 && true_regnum (operands[3]) == LO_REGNUM" 1207 [(parallel [(set (match_dup 3) 1208 (plus:SI (mult:SI (match_dup 1) (match_dup 2)) 1209 (match_dup 3))) 1210 (clobber (match_dup 4)) 1211 (clobber (match_dup 5)) 1212 (clobber (match_dup 6))]) 1213 (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] 1214 "") 1215 1216(define_insn "*macc" 1217 [(set (match_operand:SI 0 "register_operand" "=l,d") 1218 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") 1219 (match_operand:SI 2 "register_operand" "d,d")) 1220 (match_operand:SI 3 "register_operand" "0,l"))) 1221 (clobber (match_scratch:SI 4 "=h,h")) 1222 (clobber (match_scratch:SI 5 "=X,3"))] 1223 "ISA_HAS_MACC" 1224{ 1225 if (which_alternative == 1) 1226 return "macc\t%0,%1,%2"; 1227 else if (TARGET_MIPS5500) 1228 return "madd\t%1,%2"; 1229 else 1230 /* The VR4130 assumes that there is a two-cycle latency between a macc 1231 that "writes" to $0 and an instruction that reads from it. We avoid 1232 this by assigning to $1 instead. */ 1233 return "%[macc\t%@,%1,%2%]"; 1234} 1235 [(set_attr "type" "imadd") 1236 (set_attr "mode" "SI")]) 1237 1238(define_insn "*msac" 1239 [(set (match_operand:SI 0 "register_operand" "=l,d") 1240 (minus:SI (match_operand:SI 1 "register_operand" "0,l") 1241 (mult:SI (match_operand:SI 2 "register_operand" "d,d") 1242 (match_operand:SI 3 "register_operand" "d,d")))) 1243 (clobber (match_scratch:SI 4 "=h,h")) 1244 (clobber (match_scratch:SI 5 "=X,1"))] 1245 "ISA_HAS_MSAC" 1246{ 1247 if (which_alternative == 1) 1248 return "msac\t%0,%2,%3"; 1249 else if (TARGET_MIPS5500) 1250 return "msub\t%2,%3"; 1251 else 1252 return "msac\t$0,%2,%3"; 1253} 1254 [(set_attr "type" "imadd") 1255 (set_attr "mode" "SI")]) 1256 1257;; An msac-like instruction implemented using negation and a macc. 1258(define_insn_and_split "*msac_using_macc" 1259 [(set (match_operand:SI 0 "register_operand" "=l,d") 1260 (minus:SI (match_operand:SI 1 "register_operand" "0,l") 1261 (mult:SI (match_operand:SI 2 "register_operand" "d,d") 1262 (match_operand:SI 3 "register_operand" "d,d")))) 1263 (clobber (match_scratch:SI 4 "=h,h")) 1264 (clobber (match_scratch:SI 5 "=X,1")) 1265 (clobber (match_scratch:SI 6 "=d,d"))] 1266 "ISA_HAS_MACC && !ISA_HAS_MSAC" 1267 "#" 1268 "&& reload_completed" 1269 [(set (match_dup 6) 1270 (neg:SI (match_dup 3))) 1271 (parallel 1272 [(set (match_dup 0) 1273 (plus:SI (mult:SI (match_dup 2) 1274 (match_dup 6)) 1275 (match_dup 1))) 1276 (clobber (match_dup 4)) 1277 (clobber (match_dup 5))])] 1278 "" 1279 [(set_attr "type" "imadd") 1280 (set_attr "length" "8")]) 1281 1282;; Patterns generated by the define_peephole2 below. 1283 1284(define_insn "*macc2" 1285 [(set (match_operand:SI 0 "register_operand" "=l") 1286 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") 1287 (match_operand:SI 2 "register_operand" "d")) 1288 (match_dup 0))) 1289 (set (match_operand:SI 3 "register_operand" "=d") 1290 (plus:SI (mult:SI (match_dup 1) 1291 (match_dup 2)) 1292 (match_dup 0))) 1293 (clobber (match_scratch:SI 4 "=h"))] 1294 "ISA_HAS_MACC && reload_completed" 1295 "macc\t%3,%1,%2" 1296 [(set_attr "type" "imadd") 1297 (set_attr "mode" "SI")]) 1298 1299(define_insn "*msac2" 1300 [(set (match_operand:SI 0 "register_operand" "=l") 1301 (minus:SI (match_dup 0) 1302 (mult:SI (match_operand:SI 1 "register_operand" "d") 1303 (match_operand:SI 2 "register_operand" "d")))) 1304 (set (match_operand:SI 3 "register_operand" "=d") 1305 (minus:SI (match_dup 0) 1306 (mult:SI (match_dup 1) 1307 (match_dup 2)))) 1308 (clobber (match_scratch:SI 4 "=h"))] 1309 "ISA_HAS_MSAC && reload_completed" 1310 "msac\t%3,%1,%2" 1311 [(set_attr "type" "imadd") 1312 (set_attr "mode" "SI")]) 1313 1314;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2> 1315;; Similarly msac. 1316;; 1317;; Operand 0: LO 1318;; Operand 1: macc/msac 1319;; Operand 2: HI 1320;; Operand 3: GPR (destination) 1321(define_peephole2 1322 [(parallel 1323 [(set (match_operand:SI 0 "register_operand") 1324 (match_operand:SI 1 "macc_msac_operand")) 1325 (clobber (match_operand:SI 2 "register_operand")) 1326 (clobber (scratch:SI))]) 1327 (set (match_operand:SI 3 "register_operand") 1328 (unspec:SI [(match_dup 0) (match_dup 2)] UNSPEC_MFHILO))] 1329 "" 1330 [(parallel [(set (match_dup 0) 1331 (match_dup 1)) 1332 (set (match_dup 3) 1333 (match_dup 1)) 1334 (clobber (match_dup 2))])] 1335 "") 1336 1337;; When we have a three-address multiplication instruction, it should 1338;; be faster to do a separate multiply and add, rather than moving 1339;; something into LO in order to use a macc instruction. 1340;; 1341;; This peephole needs a scratch register to cater for the case when one 1342;; of the multiplication operands is the same as the destination. 1343;; 1344;; Operand 0: GPR (scratch) 1345;; Operand 1: LO 1346;; Operand 2: GPR (addend) 1347;; Operand 3: GPR (destination) 1348;; Operand 4: macc/msac 1349;; Operand 5: HI 1350;; Operand 6: new multiplication 1351;; Operand 7: new addition/subtraction 1352(define_peephole2 1353 [(match_scratch:SI 0 "d") 1354 (set (match_operand:SI 1 "register_operand") 1355 (match_operand:SI 2 "register_operand")) 1356 (match_dup 0) 1357 (parallel 1358 [(set (match_operand:SI 3 "register_operand") 1359 (match_operand:SI 4 "macc_msac_operand")) 1360 (clobber (match_operand:SI 5 "register_operand")) 1361 (clobber (match_dup 1))])] 1362 "GENERATE_MULT3_SI 1363 && true_regnum (operands[1]) == LO_REGNUM 1364 && peep2_reg_dead_p (2, operands[1]) 1365 && GP_REG_P (true_regnum (operands[3]))" 1366 [(parallel [(set (match_dup 0) 1367 (match_dup 6)) 1368 (clobber (match_dup 5)) 1369 (clobber (match_dup 1))]) 1370 (set (match_dup 3) 1371 (match_dup 7))] 1372{ 1373 operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); 1374 operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, 1375 operands[2], operands[0]); 1376}) 1377 1378;; Same as above, except LO is the initial target of the macc. 1379;; 1380;; Operand 0: GPR (scratch) 1381;; Operand 1: LO 1382;; Operand 2: GPR (addend) 1383;; Operand 3: macc/msac 1384;; Operand 4: HI 1385;; Operand 5: GPR (destination) 1386;; Operand 6: new multiplication 1387;; Operand 7: new addition/subtraction 1388(define_peephole2 1389 [(match_scratch:SI 0 "d") 1390 (set (match_operand:SI 1 "register_operand") 1391 (match_operand:SI 2 "register_operand")) 1392 (match_dup 0) 1393 (parallel 1394 [(set (match_dup 1) 1395 (match_operand:SI 3 "macc_msac_operand")) 1396 (clobber (match_operand:SI 4 "register_operand")) 1397 (clobber (scratch:SI))]) 1398 (match_dup 0) 1399 (set (match_operand:SI 5 "register_operand") 1400 (unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))] 1401 "GENERATE_MULT3_SI && peep2_reg_dead_p (3, operands[1])" 1402 [(parallel [(set (match_dup 0) 1403 (match_dup 6)) 1404 (clobber (match_dup 4)) 1405 (clobber (match_dup 1))]) 1406 (set (match_dup 5) 1407 (match_dup 7))] 1408{ 1409 operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); 1410 operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, 1411 operands[2], operands[0]); 1412}) 1413 1414(define_insn "*mul_sub_si" 1415 [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") 1416 (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d") 1417 (mult:SI (match_operand:SI 2 "register_operand" "d,d,d") 1418 (match_operand:SI 3 "register_operand" "d,d,d")))) 1419 (clobber (match_scratch:SI 4 "=h,h,h")) 1420 (clobber (match_scratch:SI 5 "=X,1,l")) 1421 (clobber (match_scratch:SI 6 "=X,X,&d"))] 1422 "ISA_HAS_MADD_MSUB" 1423 "@ 1424 msub\t%2,%3 1425 # 1426 #" 1427 [(set_attr "type" "imadd,multi,multi") 1428 (set_attr "mode" "SI") 1429 (set_attr "length" "4,8,8")]) 1430 1431;; Split the above insn if we failed to get LO allocated. 1432(define_split 1433 [(set (match_operand:SI 0 "register_operand") 1434 (minus:SI (match_operand:SI 1 "register_operand") 1435 (mult:SI (match_operand:SI 2 "register_operand") 1436 (match_operand:SI 3 "register_operand")))) 1437 (clobber (match_scratch:SI 4)) 1438 (clobber (match_scratch:SI 5)) 1439 (clobber (match_scratch:SI 6))] 1440 "reload_completed && !TARGET_DEBUG_D_MODE 1441 && GP_REG_P (true_regnum (operands[0])) 1442 && GP_REG_P (true_regnum (operands[1]))" 1443 [(parallel [(set (match_dup 6) 1444 (mult:SI (match_dup 2) (match_dup 3))) 1445 (clobber (match_dup 4)) 1446 (clobber (match_dup 5))]) 1447 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 6)))] 1448 "") 1449 1450;; Splitter to copy result of MSUB to a general register 1451(define_split 1452 [(set (match_operand:SI 0 "register_operand") 1453 (minus:SI (match_operand:SI 1 "register_operand") 1454 (mult:SI (match_operand:SI 2 "register_operand") 1455 (match_operand:SI 3 "register_operand")))) 1456 (clobber (match_scratch:SI 4)) 1457 (clobber (match_scratch:SI 5)) 1458 (clobber (match_scratch:SI 6))] 1459 "reload_completed && !TARGET_DEBUG_D_MODE 1460 && GP_REG_P (true_regnum (operands[0])) 1461 && true_regnum (operands[1]) == LO_REGNUM" 1462 [(parallel [(set (match_dup 1) 1463 (minus:SI (match_dup 1) 1464 (mult:SI (match_dup 2) (match_dup 3)))) 1465 (clobber (match_dup 4)) 1466 (clobber (match_dup 5)) 1467 (clobber (match_dup 6))]) 1468 (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] 1469 "") 1470 1471(define_insn "*muls" 1472 [(set (match_operand:SI 0 "register_operand" "=l,d") 1473 (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") 1474 (match_operand:SI 2 "register_operand" "d,d")))) 1475 (clobber (match_scratch:SI 3 "=h,h")) 1476 (clobber (match_scratch:SI 4 "=X,l"))] 1477 "ISA_HAS_MULS" 1478 "@ 1479 muls\t$0,%1,%2 1480 muls\t%0,%1,%2" 1481 [(set_attr "type" "imul,imul3") 1482 (set_attr "mode" "SI")]) 1483 1484;; ??? We could define a mulditi3 pattern when TARGET_64BIT. 1485 1486(define_expand "<u>mulsidi3" 1487 [(parallel 1488 [(set (match_operand:DI 0 "register_operand") 1489 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) 1490 (any_extend:DI (match_operand:SI 2 "register_operand")))) 1491 (clobber (scratch:DI)) 1492 (clobber (scratch:DI)) 1493 (clobber (scratch:DI))])] 1494 "!TARGET_64BIT || !TARGET_FIX_R4000" 1495{ 1496 if (!TARGET_64BIT) 1497 { 1498 if (!TARGET_FIX_R4000) 1499 emit_insn (gen_<u>mulsidi3_32bit_internal (operands[0], operands[1], 1500 operands[2])); 1501 else 1502 emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1], 1503 operands[2])); 1504 DONE; 1505 } 1506}) 1507 1508(define_insn "<u>mulsidi3_32bit_internal" 1509 [(set (match_operand:DI 0 "register_operand" "=x") 1510 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1511 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 1512 "!TARGET_64BIT && !TARGET_FIX_R4000" 1513 "mult<u>\t%1,%2" 1514 [(set_attr "type" "imul") 1515 (set_attr "mode" "SI")]) 1516 1517(define_insn "<u>mulsidi3_32bit_r4000" 1518 [(set (match_operand:DI 0 "register_operand" "=d") 1519 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1520 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) 1521 (clobber (match_scratch:DI 3 "=x"))] 1522 "!TARGET_64BIT && TARGET_FIX_R4000" 1523 "mult<u>\t%1,%2\;mflo\t%L0;mfhi\t%M0" 1524 [(set_attr "type" "imul") 1525 (set_attr "mode" "SI") 1526 (set_attr "length" "12")]) 1527 1528(define_insn_and_split "*<u>mulsidi3_64bit" 1529 [(set (match_operand:DI 0 "register_operand" "=d") 1530 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1531 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) 1532 (clobber (match_scratch:DI 3 "=l")) 1533 (clobber (match_scratch:DI 4 "=h")) 1534 (clobber (match_scratch:DI 5 "=d"))] 1535 "TARGET_64BIT && !TARGET_FIX_R4000" 1536 "#" 1537 "&& reload_completed" 1538 [(parallel 1539 [(set (match_dup 3) 1540 (sign_extend:DI 1541 (mult:SI (match_dup 1) 1542 (match_dup 2)))) 1543 (set (match_dup 4) 1544 (ashiftrt:DI 1545 (mult:DI (any_extend:DI (match_dup 1)) 1546 (any_extend:DI (match_dup 2))) 1547 (const_int 32)))]) 1548 1549 ;; OP5 <- LO, OP0 <- HI 1550 (set (match_dup 5) (unspec:DI [(match_dup 3) (match_dup 4)] UNSPEC_MFHILO)) 1551 (set (match_dup 0) (unspec:DI [(match_dup 4) (match_dup 3)] UNSPEC_MFHILO)) 1552 1553 ;; Zero-extend OP5. 1554 (set (match_dup 5) 1555 (ashift:DI (match_dup 5) 1556 (const_int 32))) 1557 (set (match_dup 5) 1558 (lshiftrt:DI (match_dup 5) 1559 (const_int 32))) 1560 1561 ;; Shift OP0 into place. 1562 (set (match_dup 0) 1563 (ashift:DI (match_dup 0) 1564 (const_int 32))) 1565 1566 ;; OR the two halves together 1567 (set (match_dup 0) 1568 (ior:DI (match_dup 0) 1569 (match_dup 5)))] 1570 "" 1571 [(set_attr "type" "imul") 1572 (set_attr "mode" "SI") 1573 (set_attr "length" "24")]) 1574 1575(define_insn "*<u>mulsidi3_64bit_parts" 1576 [(set (match_operand:DI 0 "register_operand" "=l") 1577 (sign_extend:DI 1578 (mult:SI (match_operand:SI 2 "register_operand" "d") 1579 (match_operand:SI 3 "register_operand" "d")))) 1580 (set (match_operand:DI 1 "register_operand" "=h") 1581 (ashiftrt:DI 1582 (mult:DI (any_extend:DI (match_dup 2)) 1583 (any_extend:DI (match_dup 3))) 1584 (const_int 32)))] 1585 "TARGET_64BIT && !TARGET_FIX_R4000" 1586 "mult<u>\t%2,%3" 1587 [(set_attr "type" "imul") 1588 (set_attr "mode" "SI")]) 1589 1590;; Widening multiply with negation. 1591(define_insn "*muls<u>_di" 1592 [(set (match_operand:DI 0 "register_operand" "=x") 1593 (neg:DI 1594 (mult:DI 1595 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1596 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] 1597 "!TARGET_64BIT && ISA_HAS_MULS" 1598 "muls<u>\t$0,%1,%2" 1599 [(set_attr "type" "imul") 1600 (set_attr "mode" "SI")]) 1601 1602(define_insn "*msac<u>_di" 1603 [(set (match_operand:DI 0 "register_operand" "=x") 1604 (minus:DI 1605 (match_operand:DI 3 "register_operand" "0") 1606 (mult:DI 1607 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1608 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] 1609 "!TARGET_64BIT && ISA_HAS_MSAC" 1610{ 1611 if (TARGET_MIPS5500) 1612 return "msub<u>\t%1,%2"; 1613 else 1614 return "msac<u>\t$0,%1,%2"; 1615} 1616 [(set_attr "type" "imadd") 1617 (set_attr "mode" "SI")]) 1618 1619;; _highpart patterns 1620 1621(define_expand "<su>mulsi3_highpart" 1622 [(set (match_operand:SI 0 "register_operand") 1623 (truncate:SI 1624 (lshiftrt:DI 1625 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) 1626 (any_extend:DI (match_operand:SI 2 "register_operand"))) 1627 (const_int 32))))] 1628 "ISA_HAS_MULHI || !TARGET_FIX_R4000" 1629{ 1630 if (ISA_HAS_MULHI) 1631 emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0], 1632 operands[1], 1633 operands[2])); 1634 else 1635 emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1], 1636 operands[2])); 1637 DONE; 1638}) 1639 1640(define_insn "<su>mulsi3_highpart_internal" 1641 [(set (match_operand:SI 0 "register_operand" "=h") 1642 (truncate:SI 1643 (lshiftrt:DI 1644 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1645 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) 1646 (const_int 32)))) 1647 (clobber (match_scratch:SI 3 "=l"))] 1648 "!ISA_HAS_MULHI && !TARGET_FIX_R4000" 1649 "mult<u>\t%1,%2" 1650 [(set_attr "type" "imul") 1651 (set_attr "mode" "SI")]) 1652 1653(define_insn "<su>mulsi3_highpart_mulhi_internal" 1654 [(set (match_operand:SI 0 "register_operand" "=h,d") 1655 (truncate:SI 1656 (lshiftrt:DI 1657 (mult:DI 1658 (any_extend:DI (match_operand:SI 1 "register_operand" "d,d")) 1659 (any_extend:DI (match_operand:SI 2 "register_operand" "d,d"))) 1660 (const_int 32)))) 1661 (clobber (match_scratch:SI 3 "=l,l")) 1662 (clobber (match_scratch:SI 4 "=X,h"))] 1663 "ISA_HAS_MULHI" 1664 "@ 1665 mult<u>\t%1,%2 1666 mulhi<u>\t%0,%1,%2" 1667 [(set_attr "type" "imul,imul3") 1668 (set_attr "mode" "SI")]) 1669 1670(define_insn "*<su>mulsi3_highpart_neg_mulhi_internal" 1671 [(set (match_operand:SI 0 "register_operand" "=h,d") 1672 (truncate:SI 1673 (lshiftrt:DI 1674 (neg:DI 1675 (mult:DI 1676 (any_extend:DI (match_operand:SI 1 "register_operand" "d,d")) 1677 (any_extend:DI (match_operand:SI 2 "register_operand" "d,d")))) 1678 (const_int 32)))) 1679 (clobber (match_scratch:SI 3 "=l,l")) 1680 (clobber (match_scratch:SI 4 "=X,h"))] 1681 "ISA_HAS_MULHI" 1682 "@ 1683 mulshi<u>\t%.,%1,%2 1684 mulshi<u>\t%0,%1,%2" 1685 [(set_attr "type" "imul,imul3") 1686 (set_attr "mode" "SI")]) 1687 1688;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120 1689;; errata MD(0), which says that dmultu does not always produce the 1690;; correct result. 1691(define_insn "<su>muldi3_highpart" 1692 [(set (match_operand:DI 0 "register_operand" "=h") 1693 (truncate:DI 1694 (lshiftrt:TI 1695 (mult:TI 1696 (any_extend:TI (match_operand:DI 1 "register_operand" "d")) 1697 (any_extend:TI (match_operand:DI 2 "register_operand" "d"))) 1698 (const_int 64)))) 1699 (clobber (match_scratch:DI 3 "=l"))] 1700 "TARGET_64BIT && !TARGET_FIX_R4000 1701 && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" 1702 "dmult<u>\t%1,%2" 1703 [(set_attr "type" "imul") 1704 (set_attr "mode" "DI")]) 1705 1706;; The R4650 supports a 32 bit multiply/ 64 bit accumulate 1707;; instruction. The HI/LO registers are used as a 64 bit accumulator. 1708 1709(define_insn "madsi" 1710 [(set (match_operand:SI 0 "register_operand" "+l") 1711 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") 1712 (match_operand:SI 2 "register_operand" "d")) 1713 (match_dup 0))) 1714 (clobber (match_scratch:SI 3 "=h"))] 1715 "TARGET_MAD" 1716 "mad\t%1,%2" 1717 [(set_attr "type" "imadd") 1718 (set_attr "mode" "SI")]) 1719 1720(define_insn "*<su>mul_acc_di" 1721 [(set (match_operand:DI 0 "register_operand" "=x") 1722 (plus:DI 1723 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1724 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) 1725 (match_operand:DI 3 "register_operand" "0")))] 1726 "(TARGET_MAD || ISA_HAS_MACC) 1727 && !TARGET_64BIT" 1728{ 1729 if (TARGET_MAD) 1730 return "mad<u>\t%1,%2"; 1731 else if (TARGET_MIPS5500) 1732 return "madd<u>\t%1,%2"; 1733 else 1734 /* See comment in *macc. */ 1735 return "%[macc<u>\t%@,%1,%2%]"; 1736} 1737 [(set_attr "type" "imadd") 1738 (set_attr "mode" "SI")]) 1739 1740;; Floating point multiply accumulate instructions. 1741 1742(define_insn "*madd<mode>" 1743 [(set (match_operand:ANYF 0 "register_operand" "=f") 1744 (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 1745 (match_operand:ANYF 2 "register_operand" "f")) 1746 (match_operand:ANYF 3 "register_operand" "f")))] 1747 "ISA_HAS_FP4 && TARGET_FUSED_MADD" 1748 "madd.<fmt>\t%0,%3,%1,%2" 1749 [(set_attr "type" "fmadd") 1750 (set_attr "mode" "<UNITMODE>")]) 1751 1752(define_insn "*msub<mode>" 1753 [(set (match_operand:ANYF 0 "register_operand" "=f") 1754 (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 1755 (match_operand:ANYF 2 "register_operand" "f")) 1756 (match_operand:ANYF 3 "register_operand" "f")))] 1757 "ISA_HAS_FP4 && TARGET_FUSED_MADD" 1758 "msub.<fmt>\t%0,%3,%1,%2" 1759 [(set_attr "type" "fmadd") 1760 (set_attr "mode" "<UNITMODE>")]) 1761 1762(define_insn "*nmadd<mode>" 1763 [(set (match_operand:ANYF 0 "register_operand" "=f") 1764 (neg:ANYF (plus:ANYF 1765 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 1766 (match_operand:ANYF 2 "register_operand" "f")) 1767 (match_operand:ANYF 3 "register_operand" "f"))))] 1768 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1769 && HONOR_SIGNED_ZEROS (<MODE>mode) 1770 && !HONOR_NANS (<MODE>mode)" 1771 "nmadd.<fmt>\t%0,%3,%1,%2" 1772 [(set_attr "type" "fmadd") 1773 (set_attr "mode" "<UNITMODE>")]) 1774 1775(define_insn "*nmadd<mode>_fastmath" 1776 [(set (match_operand:ANYF 0 "register_operand" "=f") 1777 (minus:ANYF 1778 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 1779 (match_operand:ANYF 2 "register_operand" "f")) 1780 (match_operand:ANYF 3 "register_operand" "f")))] 1781 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1782 && !HONOR_SIGNED_ZEROS (<MODE>mode) 1783 && !HONOR_NANS (<MODE>mode)" 1784 "nmadd.<fmt>\t%0,%3,%1,%2" 1785 [(set_attr "type" "fmadd") 1786 (set_attr "mode" "<UNITMODE>")]) 1787 1788(define_insn "*nmsub<mode>" 1789 [(set (match_operand:ANYF 0 "register_operand" "=f") 1790 (neg:ANYF (minus:ANYF 1791 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") 1792 (match_operand:ANYF 3 "register_operand" "f")) 1793 (match_operand:ANYF 1 "register_operand" "f"))))] 1794 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1795 && HONOR_SIGNED_ZEROS (<MODE>mode) 1796 && !HONOR_NANS (<MODE>mode)" 1797 "nmsub.<fmt>\t%0,%1,%2,%3" 1798 [(set_attr "type" "fmadd") 1799 (set_attr "mode" "<UNITMODE>")]) 1800 1801(define_insn "*nmsub<mode>_fastmath" 1802 [(set (match_operand:ANYF 0 "register_operand" "=f") 1803 (minus:ANYF 1804 (match_operand:ANYF 1 "register_operand" "f") 1805 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") 1806 (match_operand:ANYF 3 "register_operand" "f"))))] 1807 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1808 && !HONOR_SIGNED_ZEROS (<MODE>mode) 1809 && !HONOR_NANS (<MODE>mode)" 1810 "nmsub.<fmt>\t%0,%1,%2,%3" 1811 [(set_attr "type" "fmadd") 1812 (set_attr "mode" "<UNITMODE>")]) 1813 1814;; 1815;; .................... 1816;; 1817;; DIVISION and REMAINDER 1818;; 1819;; .................... 1820;; 1821 1822(define_expand "div<mode>3" 1823 [(set (match_operand:ANYF 0 "register_operand") 1824 (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand") 1825 (match_operand:ANYF 2 "register_operand")))] 1826 "<divide_condition>" 1827{ 1828 if (const_1_operand (operands[1], <MODE>mode)) 1829 if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations)) 1830 operands[1] = force_reg (<MODE>mode, operands[1]); 1831}) 1832 1833;; These patterns work around the early SB-1 rev2 core "F1" erratum: 1834;; 1835;; If an mfc1 or dmfc1 happens to access the floating point register 1836;; file at the same time a long latency operation (div, sqrt, recip, 1837;; sqrt) iterates an intermediate result back through the floating 1838;; point register file bypass, then instead returning the correct 1839;; register value the mfc1 or dmfc1 operation returns the intermediate 1840;; result of the long latency operation. 1841;; 1842;; The workaround is to insert an unconditional 'mov' from/to the 1843;; long latency op destination register. 1844 1845(define_insn "*div<mode>3" 1846 [(set (match_operand:ANYF 0 "register_operand" "=f") 1847 (div:ANYF (match_operand:ANYF 1 "register_operand" "f") 1848 (match_operand:ANYF 2 "register_operand" "f")))] 1849 "<divide_condition>" 1850{ 1851 if (TARGET_FIX_SB1) 1852 return "div.<fmt>\t%0,%1,%2\;mov.<fmt>\t%0,%0"; 1853 else 1854 return "div.<fmt>\t%0,%1,%2"; 1855} 1856 [(set_attr "type" "fdiv") 1857 (set_attr "mode" "<UNITMODE>") 1858 (set (attr "length") 1859 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1860 (const_int 8) 1861 (const_int 4)))]) 1862 1863(define_insn "*recip<mode>3" 1864 [(set (match_operand:ANYF 0 "register_operand" "=f") 1865 (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") 1866 (match_operand:ANYF 2 "register_operand" "f")))] 1867 "<recip_condition> && flag_unsafe_math_optimizations" 1868{ 1869 if (TARGET_FIX_SB1) 1870 return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; 1871 else 1872 return "recip.<fmt>\t%0,%2"; 1873} 1874 [(set_attr "type" "frdiv") 1875 (set_attr "mode" "<UNITMODE>") 1876 (set (attr "length") 1877 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1878 (const_int 8) 1879 (const_int 4)))]) 1880 1881;; VR4120 errata MD(A1): signed division instructions do not work correctly 1882;; with negative operands. We use special libgcc functions instead. 1883(define_insn "divmod<mode>4" 1884 [(set (match_operand:GPR 0 "register_operand" "=l") 1885 (div:GPR (match_operand:GPR 1 "register_operand" "d") 1886 (match_operand:GPR 2 "register_operand" "d"))) 1887 (set (match_operand:GPR 3 "register_operand" "=h") 1888 (mod:GPR (match_dup 1) 1889 (match_dup 2)))] 1890 "!TARGET_FIX_VR4120" 1891 { return mips_output_division ("<d>div\t$0,%1,%2", operands); } 1892 [(set_attr "type" "idiv") 1893 (set_attr "mode" "<MODE>")]) 1894 1895(define_insn "udivmod<mode>4" 1896 [(set (match_operand:GPR 0 "register_operand" "=l") 1897 (udiv:GPR (match_operand:GPR 1 "register_operand" "d") 1898 (match_operand:GPR 2 "register_operand" "d"))) 1899 (set (match_operand:GPR 3 "register_operand" "=h") 1900 (umod:GPR (match_dup 1) 1901 (match_dup 2)))] 1902 "" 1903 { return mips_output_division ("<d>divu\t$0,%1,%2", operands); } 1904 [(set_attr "type" "idiv") 1905 (set_attr "mode" "<MODE>")]) 1906 1907;; 1908;; .................... 1909;; 1910;; SQUARE ROOT 1911;; 1912;; .................... 1913 1914;; These patterns work around the early SB-1 rev2 core "F1" erratum (see 1915;; "*div[sd]f3" comment for details). 1916 1917(define_insn "sqrt<mode>2" 1918 [(set (match_operand:ANYF 0 "register_operand" "=f") 1919 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 1920 "<sqrt_condition>" 1921{ 1922 if (TARGET_FIX_SB1) 1923 return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0"; 1924 else 1925 return "sqrt.<fmt>\t%0,%1"; 1926} 1927 [(set_attr "type" "fsqrt") 1928 (set_attr "mode" "<UNITMODE>") 1929 (set (attr "length") 1930 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1931 (const_int 8) 1932 (const_int 4)))]) 1933 1934(define_insn "*rsqrt<mode>a" 1935 [(set (match_operand:ANYF 0 "register_operand" "=f") 1936 (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") 1937 (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))] 1938 "<recip_condition> && flag_unsafe_math_optimizations" 1939{ 1940 if (TARGET_FIX_SB1) 1941 return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; 1942 else 1943 return "rsqrt.<fmt>\t%0,%2"; 1944} 1945 [(set_attr "type" "frsqrt") 1946 (set_attr "mode" "<UNITMODE>") 1947 (set (attr "length") 1948 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1949 (const_int 8) 1950 (const_int 4)))]) 1951 1952(define_insn "*rsqrt<mode>b" 1953 [(set (match_operand:ANYF 0 "register_operand" "=f") 1954 (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") 1955 (match_operand:ANYF 2 "register_operand" "f"))))] 1956 "<recip_condition> && flag_unsafe_math_optimizations" 1957{ 1958 if (TARGET_FIX_SB1) 1959 return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; 1960 else 1961 return "rsqrt.<fmt>\t%0,%2"; 1962} 1963 [(set_attr "type" "frsqrt") 1964 (set_attr "mode" "<UNITMODE>") 1965 (set (attr "length") 1966 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1967 (const_int 8) 1968 (const_int 4)))]) 1969 1970;; 1971;; .................... 1972;; 1973;; ABSOLUTE VALUE 1974;; 1975;; .................... 1976 1977;; Do not use the integer abs macro instruction, since that signals an 1978;; exception on -2147483648 (sigh). 1979 1980;; abs.fmt is an arithmetic instruction and treats all NaN inputs as 1981;; invalid; it does not clear their sign bits. We therefore can't use 1982;; abs.fmt if the signs of NaNs matter. 1983 1984(define_insn "abs<mode>2" 1985 [(set (match_operand:ANYF 0 "register_operand" "=f") 1986 (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 1987 "!HONOR_NANS (<MODE>mode)" 1988 "abs.<fmt>\t%0,%1" 1989 [(set_attr "type" "fabs") 1990 (set_attr "mode" "<UNITMODE>")]) 1991 1992;; 1993;; ................... 1994;; 1995;; Count leading zeroes. 1996;; 1997;; ................... 1998;; 1999 2000(define_insn "clz<mode>2" 2001 [(set (match_operand:GPR 0 "register_operand" "=d") 2002 (clz:GPR (match_operand:GPR 1 "register_operand" "d")))] 2003 "ISA_HAS_CLZ_CLO" 2004 "<d>clz\t%0,%1" 2005 [(set_attr "type" "clz") 2006 (set_attr "mode" "<MODE>")]) 2007 2008;; 2009;; .................... 2010;; 2011;; NEGATION and ONE'S COMPLEMENT 2012;; 2013;; .................... 2014 2015(define_insn "negsi2" 2016 [(set (match_operand:SI 0 "register_operand" "=d") 2017 (neg:SI (match_operand:SI 1 "register_operand" "d")))] 2018 "" 2019{ 2020 if (TARGET_MIPS16) 2021 return "neg\t%0,%1"; 2022 else 2023 return "subu\t%0,%.,%1"; 2024} 2025 [(set_attr "type" "arith") 2026 (set_attr "mode" "SI")]) 2027 2028(define_insn "negdi2" 2029 [(set (match_operand:DI 0 "register_operand" "=d") 2030 (neg:DI (match_operand:DI 1 "register_operand" "d")))] 2031 "TARGET_64BIT && !TARGET_MIPS16" 2032 "dsubu\t%0,%.,%1" 2033 [(set_attr "type" "arith") 2034 (set_attr "mode" "DI")]) 2035 2036;; neg.fmt is an arithmetic instruction and treats all NaN inputs as 2037;; invalid; it does not flip their sign bit. We therefore can't use 2038;; neg.fmt if the signs of NaNs matter. 2039 2040(define_insn "neg<mode>2" 2041 [(set (match_operand:ANYF 0 "register_operand" "=f") 2042 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 2043 "!HONOR_NANS (<MODE>mode)" 2044 "neg.<fmt>\t%0,%1" 2045 [(set_attr "type" "fneg") 2046 (set_attr "mode" "<UNITMODE>")]) 2047 2048(define_insn "one_cmpl<mode>2" 2049 [(set (match_operand:GPR 0 "register_operand" "=d") 2050 (not:GPR (match_operand:GPR 1 "register_operand" "d")))] 2051 "" 2052{ 2053 if (TARGET_MIPS16) 2054 return "not\t%0,%1"; 2055 else 2056 return "nor\t%0,%.,%1"; 2057} 2058 [(set_attr "type" "arith") 2059 (set_attr "mode" "<MODE>")]) 2060 2061;; 2062;; .................... 2063;; 2064;; LOGICAL 2065;; 2066;; .................... 2067;; 2068 2069;; Many of these instructions use trivial define_expands, because we 2070;; want to use a different set of constraints when TARGET_MIPS16. 2071 2072(define_expand "and<mode>3" 2073 [(set (match_operand:GPR 0 "register_operand") 2074 (and:GPR (match_operand:GPR 1 "register_operand") 2075 (match_operand:GPR 2 "uns_arith_operand")))] 2076 "" 2077{ 2078 if (TARGET_MIPS16) 2079 operands[2] = force_reg (<MODE>mode, operands[2]); 2080}) 2081 2082(define_insn "*and<mode>3" 2083 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2084 (and:GPR (match_operand:GPR 1 "register_operand" "%d,d") 2085 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] 2086 "!TARGET_MIPS16" 2087 "@ 2088 and\t%0,%1,%2 2089 andi\t%0,%1,%x2" 2090 [(set_attr "type" "arith") 2091 (set_attr "mode" "<MODE>")]) 2092 2093(define_insn "*and<mode>3_mips16" 2094 [(set (match_operand:GPR 0 "register_operand" "=d") 2095 (and:GPR (match_operand:GPR 1 "register_operand" "%0") 2096 (match_operand:GPR 2 "register_operand" "d")))] 2097 "TARGET_MIPS16" 2098 "and\t%0,%2" 2099 [(set_attr "type" "arith") 2100 (set_attr "mode" "<MODE>")]) 2101 2102(define_expand "ior<mode>3" 2103 [(set (match_operand:GPR 0 "register_operand") 2104 (ior:GPR (match_operand:GPR 1 "register_operand") 2105 (match_operand:GPR 2 "uns_arith_operand")))] 2106 "" 2107{ 2108 if (TARGET_MIPS16) 2109 operands[2] = force_reg (<MODE>mode, operands[2]); 2110}) 2111 2112(define_insn "*ior<mode>3" 2113 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2114 (ior:GPR (match_operand:GPR 1 "register_operand" "%d,d") 2115 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] 2116 "!TARGET_MIPS16" 2117 "@ 2118 or\t%0,%1,%2 2119 ori\t%0,%1,%x2" 2120 [(set_attr "type" "arith") 2121 (set_attr "mode" "<MODE>")]) 2122 2123(define_insn "*ior<mode>3_mips16" 2124 [(set (match_operand:GPR 0 "register_operand" "=d") 2125 (ior:GPR (match_operand:GPR 1 "register_operand" "%0") 2126 (match_operand:GPR 2 "register_operand" "d")))] 2127 "TARGET_MIPS16" 2128 "or\t%0,%2" 2129 [(set_attr "type" "arith") 2130 (set_attr "mode" "<MODE>")]) 2131 2132(define_expand "xor<mode>3" 2133 [(set (match_operand:GPR 0 "register_operand") 2134 (xor:GPR (match_operand:GPR 1 "register_operand") 2135 (match_operand:GPR 2 "uns_arith_operand")))] 2136 "" 2137 "") 2138 2139(define_insn "" 2140 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2141 (xor:GPR (match_operand:GPR 1 "register_operand" "%d,d") 2142 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] 2143 "!TARGET_MIPS16" 2144 "@ 2145 xor\t%0,%1,%2 2146 xori\t%0,%1,%x2" 2147 [(set_attr "type" "arith") 2148 (set_attr "mode" "<MODE>")]) 2149 2150(define_insn "" 2151 [(set (match_operand:GPR 0 "register_operand" "=d,t,t") 2152 (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d") 2153 (match_operand:GPR 2 "uns_arith_operand" "d,K,d")))] 2154 "TARGET_MIPS16" 2155 "@ 2156 xor\t%0,%2 2157 cmpi\t%1,%2 2158 cmp\t%1,%2" 2159 [(set_attr "type" "arith") 2160 (set_attr "mode" "<MODE>") 2161 (set_attr_alternative "length" 2162 [(const_int 4) 2163 (if_then_else (match_operand:VOID 2 "m16_uimm8_1") 2164 (const_int 4) 2165 (const_int 8)) 2166 (const_int 4)])]) 2167 2168(define_insn "*nor<mode>3" 2169 [(set (match_operand:GPR 0 "register_operand" "=d") 2170 (and:GPR (not:GPR (match_operand:GPR 1 "register_operand" "d")) 2171 (not:GPR (match_operand:GPR 2 "register_operand" "d"))))] 2172 "!TARGET_MIPS16" 2173 "nor\t%0,%1,%2" 2174 [(set_attr "type" "arith") 2175 (set_attr "mode" "<MODE>")]) 2176 2177;; 2178;; .................... 2179;; 2180;; TRUNCATION 2181;; 2182;; .................... 2183 2184 2185 2186(define_insn "truncdfsf2" 2187 [(set (match_operand:SF 0 "register_operand" "=f") 2188 (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] 2189 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2190 "cvt.s.d\t%0,%1" 2191 [(set_attr "type" "fcvt") 2192 (set_attr "cnv_mode" "D2S") 2193 (set_attr "mode" "SF")]) 2194 2195;; Integer truncation patterns. Truncating SImode values to smaller 2196;; modes is a no-op, as it is for most other GCC ports. Truncating 2197;; DImode values to SImode is not a no-op for TARGET_64BIT since we 2198;; need to make sure that the lower 32 bits are properly sign-extended 2199;; (see TRULY_NOOP_TRUNCATION). Truncating DImode values into modes 2200;; smaller than SImode is equivalent to two separate truncations: 2201;; 2202;; A B 2203;; DI ---> HI == DI ---> SI ---> HI 2204;; DI ---> QI == DI ---> SI ---> QI 2205;; 2206;; Step A needs a real instruction but step B does not. 2207 2208(define_insn "truncdisi2" 2209 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m") 2210 (truncate:SI (match_operand:DI 1 "register_operand" "d,d")))] 2211 "TARGET_64BIT" 2212 "@ 2213 sll\t%0,%1,0 2214 sw\t%1,%0" 2215 [(set_attr "type" "shift,store") 2216 (set_attr "mode" "SI") 2217 (set_attr "extended_mips16" "yes,*")]) 2218 2219(define_insn "truncdihi2" 2220 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") 2221 (truncate:HI (match_operand:DI 1 "register_operand" "d,d")))] 2222 "TARGET_64BIT" 2223 "@ 2224 sll\t%0,%1,0 2225 sh\t%1,%0" 2226 [(set_attr "type" "shift,store") 2227 (set_attr "mode" "SI") 2228 (set_attr "extended_mips16" "yes,*")]) 2229 2230(define_insn "truncdiqi2" 2231 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") 2232 (truncate:QI (match_operand:DI 1 "register_operand" "d,d")))] 2233 "TARGET_64BIT" 2234 "@ 2235 sll\t%0,%1,0 2236 sb\t%1,%0" 2237 [(set_attr "type" "shift,store") 2238 (set_attr "mode" "SI") 2239 (set_attr "extended_mips16" "yes,*")]) 2240 2241;; Combiner patterns to optimize shift/truncate combinations. 2242 2243(define_insn "" 2244 [(set (match_operand:SI 0 "register_operand" "=d") 2245 (truncate:SI 2246 (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") 2247 (match_operand:DI 2 "const_arith_operand" ""))))] 2248 "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32" 2249 "dsra\t%0,%1,%2" 2250 [(set_attr "type" "shift") 2251 (set_attr "mode" "SI")]) 2252 2253(define_insn "" 2254 [(set (match_operand:SI 0 "register_operand" "=d") 2255 (truncate:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") 2256 (const_int 32))))] 2257 "TARGET_64BIT && !TARGET_MIPS16" 2258 "dsra\t%0,%1,32" 2259 [(set_attr "type" "shift") 2260 (set_attr "mode" "SI")]) 2261 2262 2263;; Combiner patterns for truncate/sign_extend combinations. They use 2264;; the shift/truncate patterns above. 2265 2266(define_insn_and_split "" 2267 [(set (match_operand:SI 0 "register_operand" "=d") 2268 (sign_extend:SI 2269 (truncate:HI (match_operand:DI 1 "register_operand" "d"))))] 2270 "TARGET_64BIT && !TARGET_MIPS16" 2271 "#" 2272 "&& reload_completed" 2273 [(set (match_dup 2) 2274 (ashift:DI (match_dup 1) 2275 (const_int 48))) 2276 (set (match_dup 0) 2277 (truncate:SI (ashiftrt:DI (match_dup 2) 2278 (const_int 48))))] 2279 { operands[2] = gen_lowpart (DImode, operands[0]); }) 2280 2281(define_insn_and_split "" 2282 [(set (match_operand:SI 0 "register_operand" "=d") 2283 (sign_extend:SI 2284 (truncate:QI (match_operand:DI 1 "register_operand" "d"))))] 2285 "TARGET_64BIT && !TARGET_MIPS16" 2286 "#" 2287 "&& reload_completed" 2288 [(set (match_dup 2) 2289 (ashift:DI (match_dup 1) 2290 (const_int 56))) 2291 (set (match_dup 0) 2292 (truncate:SI (ashiftrt:DI (match_dup 2) 2293 (const_int 56))))] 2294 { operands[2] = gen_lowpart (DImode, operands[0]); }) 2295 2296 2297;; Combiner patterns to optimize truncate/zero_extend combinations. 2298 2299(define_insn "" 2300 [(set (match_operand:SI 0 "register_operand" "=d") 2301 (zero_extend:SI (truncate:HI 2302 (match_operand:DI 1 "register_operand" "d"))))] 2303 "TARGET_64BIT && !TARGET_MIPS16" 2304 "andi\t%0,%1,0xffff" 2305 [(set_attr "type" "arith") 2306 (set_attr "mode" "SI")]) 2307 2308(define_insn "" 2309 [(set (match_operand:SI 0 "register_operand" "=d") 2310 (zero_extend:SI (truncate:QI 2311 (match_operand:DI 1 "register_operand" "d"))))] 2312 "TARGET_64BIT && !TARGET_MIPS16" 2313 "andi\t%0,%1,0xff" 2314 [(set_attr "type" "arith") 2315 (set_attr "mode" "SI")]) 2316 2317(define_insn "" 2318 [(set (match_operand:HI 0 "register_operand" "=d") 2319 (zero_extend:HI (truncate:QI 2320 (match_operand:DI 1 "register_operand" "d"))))] 2321 "TARGET_64BIT && !TARGET_MIPS16" 2322 "andi\t%0,%1,0xff" 2323 [(set_attr "type" "arith") 2324 (set_attr "mode" "HI")]) 2325 2326;; 2327;; .................... 2328;; 2329;; ZERO EXTENSION 2330;; 2331;; .................... 2332 2333;; Extension insns. 2334 2335(define_insn_and_split "zero_extendsidi2" 2336 [(set (match_operand:DI 0 "register_operand" "=d,d") 2337 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))] 2338 "TARGET_64BIT" 2339 "@ 2340 # 2341 lwu\t%0,%1" 2342 "&& reload_completed && REG_P (operands[1])" 2343 [(set (match_dup 0) 2344 (ashift:DI (match_dup 1) (const_int 32))) 2345 (set (match_dup 0) 2346 (lshiftrt:DI (match_dup 0) (const_int 32)))] 2347 { operands[1] = gen_lowpart (DImode, operands[1]); } 2348 [(set_attr "type" "multi,load") 2349 (set_attr "mode" "DI") 2350 (set_attr "length" "8,*")]) 2351 2352;; Combine is not allowed to convert this insn into a zero_extendsidi2 2353;; because of TRULY_NOOP_TRUNCATION. 2354 2355(define_insn_and_split "*clear_upper32" 2356 [(set (match_operand:DI 0 "register_operand" "=d,d") 2357 (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o") 2358 (const_int 4294967295)))] 2359 "TARGET_64BIT" 2360{ 2361 if (which_alternative == 0) 2362 return "#"; 2363 2364 operands[1] = gen_lowpart (SImode, operands[1]); 2365 return "lwu\t%0,%1"; 2366} 2367 "&& reload_completed && REG_P (operands[1])" 2368 [(set (match_dup 0) 2369 (ashift:DI (match_dup 1) (const_int 32))) 2370 (set (match_dup 0) 2371 (lshiftrt:DI (match_dup 0) (const_int 32)))] 2372 "" 2373 [(set_attr "type" "multi,load") 2374 (set_attr "mode" "DI") 2375 (set_attr "length" "8,*")]) 2376 2377(define_expand "zero_extend<SHORT:mode><GPR:mode>2" 2378 [(set (match_operand:GPR 0 "register_operand") 2379 (zero_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))] 2380 "" 2381{ 2382 if (TARGET_MIPS16 && !GENERATE_MIPS16E 2383 && !memory_operand (operands[1], <SHORT:MODE>mode)) 2384 { 2385 emit_insn (gen_and<GPR:mode>3 (operands[0], 2386 gen_lowpart (<GPR:MODE>mode, operands[1]), 2387 force_reg (<GPR:MODE>mode, 2388 GEN_INT (<SHORT:mask>)))); 2389 DONE; 2390 } 2391}) 2392 2393(define_insn "*zero_extend<SHORT:mode><GPR:mode>2" 2394 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2395 (zero_extend:GPR 2396 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] 2397 "!TARGET_MIPS16" 2398 "@ 2399 andi\t%0,%1,<SHORT:mask> 2400 l<SHORT:size>u\t%0,%1" 2401 [(set_attr "type" "arith,load") 2402 (set_attr "mode" "<GPR:MODE>")]) 2403 2404(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16e" 2405 [(set (match_operand:GPR 0 "register_operand" "=d") 2406 (zero_extend:GPR (match_operand:SHORT 1 "register_operand" "0")))] 2407 "GENERATE_MIPS16E" 2408 "ze<SHORT:size>\t%0" 2409 [(set_attr "type" "arith") 2410 (set_attr "mode" "<GPR:MODE>")]) 2411 2412(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16" 2413 [(set (match_operand:GPR 0 "register_operand" "=d") 2414 (zero_extend:GPR (match_operand:SHORT 1 "memory_operand" "m")))] 2415 "TARGET_MIPS16" 2416 "l<SHORT:size>u\t%0,%1" 2417 [(set_attr "type" "load") 2418 (set_attr "mode" "<GPR:MODE>")]) 2419 2420(define_expand "zero_extendqihi2" 2421 [(set (match_operand:HI 0 "register_operand") 2422 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))] 2423 "" 2424{ 2425 if (TARGET_MIPS16 && !memory_operand (operands[1], QImode)) 2426 { 2427 emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]), 2428 operands[1])); 2429 DONE; 2430 } 2431}) 2432 2433(define_insn "*zero_extendqihi2" 2434 [(set (match_operand:HI 0 "register_operand" "=d,d") 2435 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] 2436 "!TARGET_MIPS16" 2437 "@ 2438 andi\t%0,%1,0x00ff 2439 lbu\t%0,%1" 2440 [(set_attr "type" "arith,load") 2441 (set_attr "mode" "HI")]) 2442 2443(define_insn "*zero_extendqihi2_mips16" 2444 [(set (match_operand:HI 0 "register_operand" "=d") 2445 (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 2446 "TARGET_MIPS16" 2447 "lbu\t%0,%1" 2448 [(set_attr "type" "load") 2449 (set_attr "mode" "HI")]) 2450 2451;; 2452;; .................... 2453;; 2454;; SIGN EXTENSION 2455;; 2456;; .................... 2457 2458;; Extension insns. 2459;; Those for integer source operand are ordered widest source type first. 2460 2461;; When TARGET_64BIT, all SImode integer registers should already be in 2462;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2). We can 2463;; therefore get rid of register->register instructions if we constrain 2464;; the source to be in the same register as the destination. 2465;; 2466;; The register alternative has type "arith" so that the pre-reload 2467;; scheduler will treat it as a move. This reflects what happens if 2468;; the register alternative needs a reload. 2469(define_insn_and_split "extendsidi2" 2470 [(set (match_operand:DI 0 "register_operand" "=d,d") 2471 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))] 2472 "TARGET_64BIT" 2473 "@ 2474 # 2475 lw\t%0,%1" 2476 "&& reload_completed && register_operand (operands[1], VOIDmode)" 2477 [(const_int 0)] 2478{ 2479 emit_note (NOTE_INSN_DELETED); 2480 DONE; 2481} 2482 [(set_attr "type" "arith,load") 2483 (set_attr "mode" "DI")]) 2484 2485(define_expand "extend<SHORT:mode><GPR:mode>2" 2486 [(set (match_operand:GPR 0 "register_operand") 2487 (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))] 2488 "") 2489 2490(define_insn "*extend<SHORT:mode><GPR:mode>2_mips16e" 2491 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2492 (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand" "0,m")))] 2493 "GENERATE_MIPS16E" 2494 "@ 2495 se<SHORT:size>\t%0 2496 l<SHORT:size>\t%0,%1" 2497 [(set_attr "type" "arith,load") 2498 (set_attr "mode" "<GPR:MODE>")]) 2499 2500(define_insn_and_split "*extend<SHORT:mode><GPR:mode>2" 2501 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2502 (sign_extend:GPR 2503 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] 2504 "!ISA_HAS_SEB_SEH && !GENERATE_MIPS16E" 2505 "@ 2506 # 2507 l<SHORT:size>\t%0,%1" 2508 "&& reload_completed && REG_P (operands[1])" 2509 [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2))) 2510 (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))] 2511{ 2512 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]); 2513 operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode) 2514 - GET_MODE_BITSIZE (<SHORT:MODE>mode)); 2515} 2516 [(set_attr "type" "arith,load") 2517 (set_attr "mode" "<GPR:MODE>") 2518 (set_attr "length" "8,*")]) 2519 2520(define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>" 2521 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2522 (sign_extend:GPR 2523 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] 2524 "ISA_HAS_SEB_SEH" 2525 "@ 2526 se<SHORT:size>\t%0,%1 2527 l<SHORT:size>\t%0,%1" 2528 [(set_attr "type" "arith,load") 2529 (set_attr "mode" "<GPR:MODE>")]) 2530 2531;; This pattern generates the same code as extendqisi2; split it into 2532;; that form after reload. 2533(define_insn_and_split "extendqihi2" 2534 [(set (match_operand:HI 0 "register_operand" "=d,d") 2535 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] 2536 "" 2537 "#" 2538 "reload_completed" 2539 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] 2540 { operands[0] = gen_lowpart (SImode, operands[0]); } 2541 [(set_attr "type" "arith,load") 2542 (set_attr "mode" "SI") 2543 (set_attr "length" "8,*")]) 2544 2545(define_insn "extendsfdf2" 2546 [(set (match_operand:DF 0 "register_operand" "=f") 2547 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] 2548 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2549 "cvt.d.s\t%0,%1" 2550 [(set_attr "type" "fcvt") 2551 (set_attr "cnv_mode" "S2D") 2552 (set_attr "mode" "DF")]) 2553 2554;; 2555;; .................... 2556;; 2557;; CONVERSIONS 2558;; 2559;; .................... 2560 2561(define_expand "fix_truncdfsi2" 2562 [(set (match_operand:SI 0 "register_operand") 2563 (fix:SI (match_operand:DF 1 "register_operand")))] 2564 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2565{ 2566 if (!ISA_HAS_TRUNC_W) 2567 { 2568 emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1])); 2569 DONE; 2570 } 2571}) 2572 2573(define_insn "fix_truncdfsi2_insn" 2574 [(set (match_operand:SI 0 "register_operand" "=f") 2575 (fix:SI (match_operand:DF 1 "register_operand" "f")))] 2576 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && ISA_HAS_TRUNC_W" 2577 "trunc.w.d %0,%1" 2578 [(set_attr "type" "fcvt") 2579 (set_attr "mode" "DF") 2580 (set_attr "cnv_mode" "D2I") 2581 (set_attr "length" "4")]) 2582 2583(define_insn "fix_truncdfsi2_macro" 2584 [(set (match_operand:SI 0 "register_operand" "=f") 2585 (fix:SI (match_operand:DF 1 "register_operand" "f"))) 2586 (clobber (match_scratch:DF 2 "=d"))] 2587 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W" 2588{ 2589 if (set_nomacro) 2590 return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro"; 2591 else 2592 return "trunc.w.d %0,%1,%2"; 2593} 2594 [(set_attr "type" "fcvt") 2595 (set_attr "mode" "DF") 2596 (set_attr "cnv_mode" "D2I") 2597 (set_attr "length" "36")]) 2598 2599(define_expand "fix_truncsfsi2" 2600 [(set (match_operand:SI 0 "register_operand") 2601 (fix:SI (match_operand:SF 1 "register_operand")))] 2602 "TARGET_HARD_FLOAT" 2603{ 2604 if (!ISA_HAS_TRUNC_W) 2605 { 2606 emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1])); 2607 DONE; 2608 } 2609}) 2610 2611(define_insn "fix_truncsfsi2_insn" 2612 [(set (match_operand:SI 0 "register_operand" "=f") 2613 (fix:SI (match_operand:SF 1 "register_operand" "f")))] 2614 "TARGET_HARD_FLOAT && ISA_HAS_TRUNC_W" 2615 "trunc.w.s %0,%1" 2616 [(set_attr "type" "fcvt") 2617 (set_attr "mode" "SF") 2618 (set_attr "cnv_mode" "S2I") 2619 (set_attr "length" "4")]) 2620 2621(define_insn "fix_truncsfsi2_macro" 2622 [(set (match_operand:SI 0 "register_operand" "=f") 2623 (fix:SI (match_operand:SF 1 "register_operand" "f"))) 2624 (clobber (match_scratch:SF 2 "=d"))] 2625 "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W" 2626{ 2627 if (set_nomacro) 2628 return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro"; 2629 else 2630 return "trunc.w.s %0,%1,%2"; 2631} 2632 [(set_attr "type" "fcvt") 2633 (set_attr "mode" "SF") 2634 (set_attr "cnv_mode" "S2I") 2635 (set_attr "length" "36")]) 2636 2637 2638(define_insn "fix_truncdfdi2" 2639 [(set (match_operand:DI 0 "register_operand" "=f") 2640 (fix:DI (match_operand:DF 1 "register_operand" "f")))] 2641 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2642 "trunc.l.d %0,%1" 2643 [(set_attr "type" "fcvt") 2644 (set_attr "mode" "DF") 2645 (set_attr "cnv_mode" "D2I") 2646 (set_attr "length" "4")]) 2647 2648 2649(define_insn "fix_truncsfdi2" 2650 [(set (match_operand:DI 0 "register_operand" "=f") 2651 (fix:DI (match_operand:SF 1 "register_operand" "f")))] 2652 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2653 "trunc.l.s %0,%1" 2654 [(set_attr "type" "fcvt") 2655 (set_attr "mode" "SF") 2656 (set_attr "cnv_mode" "S2I") 2657 (set_attr "length" "4")]) 2658 2659 2660(define_insn "floatsidf2" 2661 [(set (match_operand:DF 0 "register_operand" "=f") 2662 (float:DF (match_operand:SI 1 "register_operand" "f")))] 2663 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2664 "cvt.d.w\t%0,%1" 2665 [(set_attr "type" "fcvt") 2666 (set_attr "mode" "DF") 2667 (set_attr "cnv_mode" "I2D") 2668 (set_attr "length" "4")]) 2669 2670 2671(define_insn "floatdidf2" 2672 [(set (match_operand:DF 0 "register_operand" "=f") 2673 (float:DF (match_operand:DI 1 "register_operand" "f")))] 2674 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2675 "cvt.d.l\t%0,%1" 2676 [(set_attr "type" "fcvt") 2677 (set_attr "mode" "DF") 2678 (set_attr "cnv_mode" "I2D") 2679 (set_attr "length" "4")]) 2680 2681 2682(define_insn "floatsisf2" 2683 [(set (match_operand:SF 0 "register_operand" "=f") 2684 (float:SF (match_operand:SI 1 "register_operand" "f")))] 2685 "TARGET_HARD_FLOAT" 2686 "cvt.s.w\t%0,%1" 2687 [(set_attr "type" "fcvt") 2688 (set_attr "mode" "SF") 2689 (set_attr "cnv_mode" "I2S") 2690 (set_attr "length" "4")]) 2691 2692 2693(define_insn "floatdisf2" 2694 [(set (match_operand:SF 0 "register_operand" "=f") 2695 (float:SF (match_operand:DI 1 "register_operand" "f")))] 2696 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2697 "cvt.s.l\t%0,%1" 2698 [(set_attr "type" "fcvt") 2699 (set_attr "mode" "SF") 2700 (set_attr "cnv_mode" "I2S") 2701 (set_attr "length" "4")]) 2702 2703 2704(define_expand "fixuns_truncdfsi2" 2705 [(set (match_operand:SI 0 "register_operand") 2706 (unsigned_fix:SI (match_operand:DF 1 "register_operand")))] 2707 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2708{ 2709 rtx reg1 = gen_reg_rtx (DFmode); 2710 rtx reg2 = gen_reg_rtx (DFmode); 2711 rtx reg3 = gen_reg_rtx (SImode); 2712 rtx label1 = gen_label_rtx (); 2713 rtx label2 = gen_label_rtx (); 2714 REAL_VALUE_TYPE offset; 2715 2716 real_2expN (&offset, 31); 2717 2718 if (reg1) /* Turn off complaints about unreached code. */ 2719 { 2720 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); 2721 do_pending_stack_adjust (); 2722 2723 emit_insn (gen_cmpdf (operands[1], reg1)); 2724 emit_jump_insn (gen_bge (label1)); 2725 2726 emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); 2727 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2728 gen_rtx_LABEL_REF (VOIDmode, label2))); 2729 emit_barrier (); 2730 2731 emit_label (label1); 2732 emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); 2733 emit_move_insn (reg3, GEN_INT (trunc_int_for_mode 2734 (BITMASK_HIGH, SImode))); 2735 2736 emit_insn (gen_fix_truncdfsi2 (operands[0], reg2)); 2737 emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); 2738 2739 emit_label (label2); 2740 2741 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2742 fields, and can't be used for REG_NOTES anyway). */ 2743 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2744 DONE; 2745 } 2746}) 2747 2748 2749(define_expand "fixuns_truncdfdi2" 2750 [(set (match_operand:DI 0 "register_operand") 2751 (unsigned_fix:DI (match_operand:DF 1 "register_operand")))] 2752 "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" 2753{ 2754 rtx reg1 = gen_reg_rtx (DFmode); 2755 rtx reg2 = gen_reg_rtx (DFmode); 2756 rtx reg3 = gen_reg_rtx (DImode); 2757 rtx label1 = gen_label_rtx (); 2758 rtx label2 = gen_label_rtx (); 2759 REAL_VALUE_TYPE offset; 2760 2761 real_2expN (&offset, 63); 2762 2763 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); 2764 do_pending_stack_adjust (); 2765 2766 emit_insn (gen_cmpdf (operands[1], reg1)); 2767 emit_jump_insn (gen_bge (label1)); 2768 2769 emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); 2770 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2771 gen_rtx_LABEL_REF (VOIDmode, label2))); 2772 emit_barrier (); 2773 2774 emit_label (label1); 2775 emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); 2776 emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); 2777 emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); 2778 2779 emit_insn (gen_fix_truncdfdi2 (operands[0], reg2)); 2780 emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); 2781 2782 emit_label (label2); 2783 2784 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2785 fields, and can't be used for REG_NOTES anyway). */ 2786 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2787 DONE; 2788}) 2789 2790 2791(define_expand "fixuns_truncsfsi2" 2792 [(set (match_operand:SI 0 "register_operand") 2793 (unsigned_fix:SI (match_operand:SF 1 "register_operand")))] 2794 "TARGET_HARD_FLOAT" 2795{ 2796 rtx reg1 = gen_reg_rtx (SFmode); 2797 rtx reg2 = gen_reg_rtx (SFmode); 2798 rtx reg3 = gen_reg_rtx (SImode); 2799 rtx label1 = gen_label_rtx (); 2800 rtx label2 = gen_label_rtx (); 2801 REAL_VALUE_TYPE offset; 2802 2803 real_2expN (&offset, 31); 2804 2805 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); 2806 do_pending_stack_adjust (); 2807 2808 emit_insn (gen_cmpsf (operands[1], reg1)); 2809 emit_jump_insn (gen_bge (label1)); 2810 2811 emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); 2812 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2813 gen_rtx_LABEL_REF (VOIDmode, label2))); 2814 emit_barrier (); 2815 2816 emit_label (label1); 2817 emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); 2818 emit_move_insn (reg3, GEN_INT (trunc_int_for_mode 2819 (BITMASK_HIGH, SImode))); 2820 2821 emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); 2822 emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); 2823 2824 emit_label (label2); 2825 2826 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2827 fields, and can't be used for REG_NOTES anyway). */ 2828 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2829 DONE; 2830}) 2831 2832 2833(define_expand "fixuns_truncsfdi2" 2834 [(set (match_operand:DI 0 "register_operand") 2835 (unsigned_fix:DI (match_operand:SF 1 "register_operand")))] 2836 "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" 2837{ 2838 rtx reg1 = gen_reg_rtx (SFmode); 2839 rtx reg2 = gen_reg_rtx (SFmode); 2840 rtx reg3 = gen_reg_rtx (DImode); 2841 rtx label1 = gen_label_rtx (); 2842 rtx label2 = gen_label_rtx (); 2843 REAL_VALUE_TYPE offset; 2844 2845 real_2expN (&offset, 63); 2846 2847 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); 2848 do_pending_stack_adjust (); 2849 2850 emit_insn (gen_cmpsf (operands[1], reg1)); 2851 emit_jump_insn (gen_bge (label1)); 2852 2853 emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); 2854 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2855 gen_rtx_LABEL_REF (VOIDmode, label2))); 2856 emit_barrier (); 2857 2858 emit_label (label1); 2859 emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); 2860 emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); 2861 emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); 2862 2863 emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); 2864 emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); 2865 2866 emit_label (label2); 2867 2868 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2869 fields, and can't be used for REG_NOTES anyway). */ 2870 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2871 DONE; 2872}) 2873 2874;; 2875;; .................... 2876;; 2877;; DATA MOVEMENT 2878;; 2879;; .................... 2880 2881;; Bit field extract patterns which use lwl/lwr or ldl/ldr. 2882 2883(define_expand "extv" 2884 [(set (match_operand 0 "register_operand") 2885 (sign_extract (match_operand:QI 1 "memory_operand") 2886 (match_operand 2 "immediate_operand") 2887 (match_operand 3 "immediate_operand")))] 2888 "!TARGET_MIPS16" 2889{ 2890 if (mips_expand_unaligned_load (operands[0], operands[1], 2891 INTVAL (operands[2]), 2892 INTVAL (operands[3]))) 2893 DONE; 2894 else 2895 FAIL; 2896}) 2897 2898(define_expand "extzv" 2899 [(set (match_operand 0 "register_operand") 2900 (zero_extract (match_operand 1 "nonimmediate_operand") 2901 (match_operand 2 "immediate_operand") 2902 (match_operand 3 "immediate_operand")))] 2903 "!TARGET_MIPS16" 2904{ 2905 if (mips_expand_unaligned_load (operands[0], operands[1], 2906 INTVAL (operands[2]), 2907 INTVAL (operands[3]))) 2908 DONE; 2909 else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3])) 2910 { 2911 if (GET_MODE (operands[0]) == DImode) 2912 emit_insn (gen_extzvdi (operands[0], operands[1], operands[2], 2913 operands[3])); 2914 else 2915 emit_insn (gen_extzvsi (operands[0], operands[1], operands[2], 2916 operands[3])); 2917 DONE; 2918 } 2919 else 2920 FAIL; 2921}) 2922 2923(define_insn "extzv<mode>" 2924 [(set (match_operand:GPR 0 "register_operand" "=d") 2925 (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d") 2926 (match_operand:SI 2 "immediate_operand" "I") 2927 (match_operand:SI 3 "immediate_operand" "I")))] 2928 "mips_use_ins_ext_p (operands[1], operands[2], operands[3])" 2929 "<d>ext\t%0,%1,%3,%2" 2930 [(set_attr "type" "arith") 2931 (set_attr "mode" "<MODE>")]) 2932 2933 2934(define_expand "insv" 2935 [(set (zero_extract (match_operand 0 "nonimmediate_operand") 2936 (match_operand 1 "immediate_operand") 2937 (match_operand 2 "immediate_operand")) 2938 (match_operand 3 "reg_or_0_operand"))] 2939 "!TARGET_MIPS16" 2940{ 2941 if (mips_expand_unaligned_store (operands[0], operands[3], 2942 INTVAL (operands[1]), 2943 INTVAL (operands[2]))) 2944 DONE; 2945 else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2])) 2946 { 2947 if (GET_MODE (operands[0]) == DImode) 2948 emit_insn (gen_insvdi (operands[0], operands[1], operands[2], 2949 operands[3])); 2950 else 2951 emit_insn (gen_insvsi (operands[0], operands[1], operands[2], 2952 operands[3])); 2953 DONE; 2954 } 2955 else 2956 FAIL; 2957}) 2958 2959(define_insn "insv<mode>" 2960 [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d") 2961 (match_operand:SI 1 "immediate_operand" "I") 2962 (match_operand:SI 2 "immediate_operand" "I")) 2963 (match_operand:GPR 3 "reg_or_0_operand" "dJ"))] 2964 "mips_use_ins_ext_p (operands[0], operands[1], operands[2])" 2965 "<d>ins\t%0,%z3,%2,%1" 2966 [(set_attr "type" "arith") 2967 (set_attr "mode" "<MODE>")]) 2968 2969;; Unaligned word moves generated by the bit field patterns. 2970;; 2971;; As far as the rtl is concerned, both the left-part and right-part 2972;; instructions can access the whole field. However, the real operand 2973;; refers to just the first or the last byte (depending on endianness). 2974;; We therefore use two memory operands to each instruction, one to 2975;; describe the rtl effect and one to use in the assembly output. 2976;; 2977;; Operands 0 and 1 are the rtl-level target and source respectively. 2978;; This allows us to use the standard length calculations for the "load" 2979;; and "store" type attributes. 2980 2981(define_insn "mov_<load>l" 2982 [(set (match_operand:GPR 0 "register_operand" "=d") 2983 (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") 2984 (match_operand:QI 2 "memory_operand" "m")] 2985 UNSPEC_LOAD_LEFT))] 2986 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" 2987 "<load>l\t%0,%2" 2988 [(set_attr "type" "load") 2989 (set_attr "mode" "<MODE>")]) 2990 2991(define_insn "mov_<load>r" 2992 [(set (match_operand:GPR 0 "register_operand" "=d") 2993 (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") 2994 (match_operand:QI 2 "memory_operand" "m") 2995 (match_operand:GPR 3 "register_operand" "0")] 2996 UNSPEC_LOAD_RIGHT))] 2997 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" 2998 "<load>r\t%0,%2" 2999 [(set_attr "type" "load") 3000 (set_attr "mode" "<MODE>")]) 3001 3002(define_insn "mov_<store>l" 3003 [(set (match_operand:BLK 0 "memory_operand" "=m") 3004 (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") 3005 (match_operand:QI 2 "memory_operand" "m")] 3006 UNSPEC_STORE_LEFT))] 3007 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" 3008 "<store>l\t%z1,%2" 3009 [(set_attr "type" "store") 3010 (set_attr "mode" "<MODE>")]) 3011 3012(define_insn "mov_<store>r" 3013 [(set (match_operand:BLK 0 "memory_operand" "+m") 3014 (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") 3015 (match_operand:QI 2 "memory_operand" "m") 3016 (match_dup 0)] 3017 UNSPEC_STORE_RIGHT))] 3018 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" 3019 "<store>r\t%z1,%2" 3020 [(set_attr "type" "store") 3021 (set_attr "mode" "<MODE>")]) 3022 3023;; An instruction to calculate the high part of a 64-bit SYMBOL_GENERAL. 3024;; The required value is: 3025;; 3026;; (%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16) 3027;; 3028;; which translates to: 3029;; 3030;; lui op0,%highest(op1) 3031;; daddiu op0,op0,%higher(op1) 3032;; dsll op0,op0,16 3033;; daddiu op0,op0,%hi(op1) 3034;; dsll op0,op0,16 3035;; 3036;; The split is deferred until after flow2 to allow the peephole2 below 3037;; to take effect. 3038(define_insn_and_split "*lea_high64" 3039 [(set (match_operand:DI 0 "register_operand" "=d") 3040 (high:DI (match_operand:DI 1 "general_symbolic_operand" "")))] 3041 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" 3042 "#" 3043 "&& flow2_completed" 3044 [(set (match_dup 0) (high:DI (match_dup 2))) 3045 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2))) 3046 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16))) 3047 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) 3048 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))] 3049{ 3050 operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); 3051 operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID); 3052} 3053 [(set_attr "length" "20")]) 3054 3055;; Use a scratch register to reduce the latency of the above pattern 3056;; on superscalar machines. The optimized sequence is: 3057;; 3058;; lui op1,%highest(op2) 3059;; lui op0,%hi(op2) 3060;; daddiu op1,op1,%higher(op2) 3061;; dsll32 op1,op1,0 3062;; daddu op1,op1,op0 3063(define_peephole2 3064 [(set (match_operand:DI 1 "register_operand") 3065 (high:DI (match_operand:DI 2 "general_symbolic_operand"))) 3066 (match_scratch:DI 0 "d")] 3067 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" 3068 [(set (match_dup 1) (high:DI (match_dup 3))) 3069 (set (match_dup 0) (high:DI (match_dup 4))) 3070 (set (match_dup 1) (lo_sum:DI (match_dup 1) (match_dup 3))) 3071 (set (match_dup 1) (ashift:DI (match_dup 1) (const_int 32))) 3072 (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 0)))] 3073{ 3074 operands[3] = mips_unspec_address (operands[2], SYMBOL_64_HIGH); 3075 operands[4] = mips_unspec_address (operands[2], SYMBOL_64_LOW); 3076}) 3077 3078;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit 3079;; SYMBOL_GENERAL X will take 6 cycles. This next pattern allows combine 3080;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only 3081;; used once. We can then use the sequence: 3082;; 3083;; lui op0,%highest(op1) 3084;; lui op2,%hi(op1) 3085;; daddiu op0,op0,%higher(op1) 3086;; daddiu op2,op2,%lo(op1) 3087;; dsll32 op0,op0,0 3088;; daddu op0,op0,op2 3089;; 3090;; which takes 4 cycles on most superscalar targets. 3091(define_insn_and_split "*lea64" 3092 [(set (match_operand:DI 0 "register_operand" "=d") 3093 (match_operand:DI 1 "general_symbolic_operand" "")) 3094 (clobber (match_scratch:DI 2 "=&d"))] 3095 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected" 3096 "#" 3097 "&& reload_completed" 3098 [(set (match_dup 0) (high:DI (match_dup 3))) 3099 (set (match_dup 2) (high:DI (match_dup 4))) 3100 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) 3101 (set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4))) 3102 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) 3103 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] 3104{ 3105 operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); 3106 operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW); 3107} 3108 [(set_attr "length" "24")]) 3109 3110;; Insns to fetch a global symbol from a big GOT. 3111 3112(define_insn_and_split "*xgot_hi<mode>" 3113 [(set (match_operand:P 0 "register_operand" "=d") 3114 (high:P (match_operand:P 1 "global_got_operand" "")))] 3115 "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" 3116 "#" 3117 "&& reload_completed" 3118 [(set (match_dup 0) (high:P (match_dup 2))) 3119 (set (match_dup 0) (plus:P (match_dup 0) (match_dup 3)))] 3120{ 3121 operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); 3122 operands[3] = pic_offset_table_rtx; 3123} 3124 [(set_attr "got" "xgot_high") 3125 (set_attr "mode" "<MODE>")]) 3126 3127(define_insn_and_split "*xgot_lo<mode>" 3128 [(set (match_operand:P 0 "register_operand" "=d") 3129 (lo_sum:P (match_operand:P 1 "register_operand" "d") 3130 (match_operand:P 2 "global_got_operand" "")))] 3131 "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" 3132 "#" 3133 "&& reload_completed" 3134 [(set (match_dup 0) 3135 (unspec:P [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))] 3136 { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); } 3137 [(set_attr "got" "load") 3138 (set_attr "mode" "<MODE>")]) 3139 3140;; Insns to fetch a global symbol from a normal GOT. 3141 3142(define_insn_and_split "*got_disp<mode>" 3143 [(set (match_operand:P 0 "register_operand" "=d") 3144 (match_operand:P 1 "global_got_operand" ""))] 3145 "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT" 3146 "#" 3147 "&& reload_completed" 3148 [(set (match_dup 0) 3149 (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] 3150{ 3151 operands[2] = pic_offset_table_rtx; 3152 operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); 3153} 3154 [(set_attr "got" "load") 3155 (set_attr "mode" "<MODE>")]) 3156 3157;; Insns for loading the high part of a local symbol. 3158 3159(define_insn_and_split "*got_page<mode>" 3160 [(set (match_operand:P 0 "register_operand" "=d") 3161 (high:P (match_operand:P 1 "local_got_operand" "")))] 3162 "TARGET_EXPLICIT_RELOCS" 3163 "#" 3164 "&& reload_completed" 3165 [(set (match_dup 0) 3166 (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] 3167{ 3168 operands[2] = pic_offset_table_rtx; 3169 operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE); 3170} 3171 [(set_attr "got" "load") 3172 (set_attr "mode" "<MODE>")]) 3173 3174;; Lower-level instructions for loading an address from the GOT. 3175;; We could use MEMs, but an unspec gives more optimization 3176;; opportunities. 3177 3178(define_insn "load_got<mode>" 3179 [(set (match_operand:P 0 "register_operand" "=d") 3180 (unspec:P [(match_operand:P 1 "register_operand" "d") 3181 (match_operand:P 2 "immediate_operand" "")] 3182 UNSPEC_LOAD_GOT))] 3183 "" 3184 "<load>\t%0,%R2(%1)" 3185 [(set_attr "type" "load") 3186 (set_attr "mode" "<MODE>") 3187 (set_attr "length" "4")]) 3188 3189;; Instructions for adding the low 16 bits of an address to a register. 3190;; Operand 2 is the address: print_operand works out which relocation 3191;; should be applied. 3192 3193(define_insn "*low<mode>" 3194 [(set (match_operand:P 0 "register_operand" "=d") 3195 (lo_sum:P (match_operand:P 1 "register_operand" "d") 3196 (match_operand:P 2 "immediate_operand" "")))] 3197 "!TARGET_MIPS16" 3198 "<d>addiu\t%0,%1,%R2" 3199 [(set_attr "type" "arith") 3200 (set_attr "mode" "<MODE>")]) 3201 3202(define_insn "*low<mode>_mips16" 3203 [(set (match_operand:P 0 "register_operand" "=d") 3204 (lo_sum:P (match_operand:P 1 "register_operand" "0") 3205 (match_operand:P 2 "immediate_operand" "")))] 3206 "TARGET_MIPS16" 3207 "<d>addiu\t%0,%R2" 3208 [(set_attr "type" "arith") 3209 (set_attr "mode" "<MODE>") 3210 (set_attr "length" "8")]) 3211 3212;; Allow combine to split complex const_int load sequences, using operand 2 3213;; to store the intermediate results. See move_operand for details. 3214(define_split 3215 [(set (match_operand:GPR 0 "register_operand") 3216 (match_operand:GPR 1 "splittable_const_int_operand")) 3217 (clobber (match_operand:GPR 2 "register_operand"))] 3218 "" 3219 [(const_int 0)] 3220{ 3221 mips_move_integer (operands[0], operands[2], INTVAL (operands[1])); 3222 DONE; 3223}) 3224 3225;; Likewise, for symbolic operands. 3226(define_split 3227 [(set (match_operand:P 0 "register_operand") 3228 (match_operand:P 1 "splittable_symbolic_operand")) 3229 (clobber (match_operand:P 2 "register_operand"))] 3230 "" 3231 [(set (match_dup 0) (match_dup 1))] 3232 { operands[1] = mips_split_symbol (operands[2], operands[1]); }) 3233 3234;; 64-bit integer moves 3235 3236;; Unlike most other insns, the move insns can't be split with 3237;; different predicates, because register spilling and other parts of 3238;; the compiler, have memoized the insn number already. 3239 3240(define_expand "movdi" 3241 [(set (match_operand:DI 0 "") 3242 (match_operand:DI 1 ""))] 3243 "" 3244{ 3245 if (mips_legitimize_move (DImode, operands[0], operands[1])) 3246 DONE; 3247}) 3248 3249;; For mips16, we need a special case to handle storing $31 into 3250;; memory, since we don't have a constraint to match $31. This 3251;; instruction can be generated by save_restore_insns. 3252 3253(define_insn "*mov<mode>_ra" 3254 [(set (match_operand:GPR 0 "stack_operand" "=m") 3255 (reg:GPR 31))] 3256 "TARGET_MIPS16" 3257 "<store>\t$31,%0" 3258 [(set_attr "type" "store") 3259 (set_attr "mode" "<MODE>")]) 3260 3261(define_insn "*movdi_32bit" 3262 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m") 3263 (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))] 3264 "!TARGET_64BIT && !TARGET_MIPS16 3265 && (register_operand (operands[0], DImode) 3266 || reg_or_0_operand (operands[1], DImode))" 3267 { return mips_output_move (operands[0], operands[1]); } 3268 [(set_attr "type" "arith,arith,load,store,mthilo,mfhilo,xfer,load,xfer,store") 3269 (set_attr "mode" "DI") 3270 (set_attr "length" "8,16,*,*,8,8,8,*,8,*")]) 3271 3272(define_insn "*movdi_32bit_mips16" 3273 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") 3274 (match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))] 3275 "!TARGET_64BIT && TARGET_MIPS16 3276 && (register_operand (operands[0], DImode) 3277 || register_operand (operands[1], DImode))" 3278 { return mips_output_move (operands[0], operands[1]); } 3279 [(set_attr "type" "arith,arith,arith,arith,arith,load,store,mfhilo") 3280 (set_attr "mode" "DI") 3281 (set_attr "length" "8,8,8,8,12,*,*,8")]) 3282 3283(define_insn "*movdi_64bit" 3284 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m") 3285 (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))] 3286 "TARGET_64BIT && !TARGET_MIPS16 3287 && (register_operand (operands[0], DImode) 3288 || reg_or_0_operand (operands[1], DImode))" 3289 { return mips_output_move (operands[0], operands[1]); } 3290 [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,mthilo,xfer,load,xfer,store") 3291 (set_attr "mode" "DI") 3292 (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,8,*,8,*")]) 3293 3294(define_insn "*movdi_64bit_mips16" 3295 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") 3296 (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,m,d"))] 3297 "TARGET_64BIT && TARGET_MIPS16 3298 && (register_operand (operands[0], DImode) 3299 || register_operand (operands[1], DImode))" 3300 { return mips_output_move (operands[0], operands[1]); } 3301 [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store") 3302 (set_attr "mode" "DI") 3303 (set_attr_alternative "length" 3304 [(const_int 4) 3305 (const_int 4) 3306 (const_int 4) 3307 (if_then_else (match_operand:VOID 1 "m16_uimm8_1") 3308 (const_int 4) 3309 (const_int 8)) 3310 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") 3311 (const_int 8) 3312 (const_int 12)) 3313 (const_string "*") 3314 (const_string "*") 3315 (const_string "*")])]) 3316 3317 3318;; On the mips16, we can split ld $r,N($r) into an add and a load, 3319;; when the original load is a 4 byte instruction but the add and the 3320;; load are 2 2 byte instructions. 3321 3322(define_split 3323 [(set (match_operand:DI 0 "register_operand") 3324 (mem:DI (plus:DI (match_dup 0) 3325 (match_operand:DI 1 "const_int_operand"))))] 3326 "TARGET_64BIT && TARGET_MIPS16 && reload_completed 3327 && !TARGET_DEBUG_D_MODE 3328 && REG_P (operands[0]) 3329 && M16_REG_P (REGNO (operands[0])) 3330 && GET_CODE (operands[1]) == CONST_INT 3331 && ((INTVAL (operands[1]) < 0 3332 && INTVAL (operands[1]) >= -0x10) 3333 || (INTVAL (operands[1]) >= 32 * 8 3334 && INTVAL (operands[1]) <= 31 * 8 + 0x8) 3335 || (INTVAL (operands[1]) >= 0 3336 && INTVAL (operands[1]) < 32 * 8 3337 && (INTVAL (operands[1]) & 7) != 0))" 3338 [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) 3339 (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))] 3340{ 3341 HOST_WIDE_INT val = INTVAL (operands[1]); 3342 3343 if (val < 0) 3344 operands[2] = const0_rtx; 3345 else if (val >= 32 * 8) 3346 { 3347 int off = val & 7; 3348 3349 operands[1] = GEN_INT (0x8 + off); 3350 operands[2] = GEN_INT (val - off - 0x8); 3351 } 3352 else 3353 { 3354 int off = val & 7; 3355 3356 operands[1] = GEN_INT (off); 3357 operands[2] = GEN_INT (val - off); 3358 } 3359}) 3360 3361;; 32-bit Integer moves 3362 3363;; Unlike most other insns, the move insns can't be split with 3364;; different predicates, because register spilling and other parts of 3365;; the compiler, have memoized the insn number already. 3366 3367(define_expand "movsi" 3368 [(set (match_operand:SI 0 "") 3369 (match_operand:SI 1 ""))] 3370 "" 3371{ 3372 if (mips_legitimize_move (SImode, operands[0], operands[1])) 3373 DONE; 3374}) 3375 3376;; The difference between these two is whether or not ints are allowed 3377;; in FP registers (off by default, use -mdebugh to enable). 3378 3379(define_insn "*movsi_internal" 3380 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m") 3381 (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))] 3382 "!TARGET_MIPS16 3383 && (register_operand (operands[0], SImode) 3384 || reg_or_0_operand (operands[1], SImode))" 3385 { return mips_output_move (operands[0], operands[1]); } 3386 [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,mfhilo,xfer,load,xfer,store") 3387 (set_attr "mode" "SI") 3388 (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")]) 3389 3390(define_insn "*movsi_mips16" 3391 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") 3392 (match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d"))] 3393 "TARGET_MIPS16 3394 && (register_operand (operands[0], SImode) 3395 || register_operand (operands[1], SImode))" 3396 { return mips_output_move (operands[0], operands[1]); } 3397 [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store") 3398 (set_attr "mode" "SI") 3399 (set_attr_alternative "length" 3400 [(const_int 4) 3401 (const_int 4) 3402 (const_int 4) 3403 (if_then_else (match_operand:VOID 1 "m16_uimm8_1") 3404 (const_int 4) 3405 (const_int 8)) 3406 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") 3407 (const_int 8) 3408 (const_int 12)) 3409 (const_string "*") 3410 (const_string "*") 3411 (const_string "*")])]) 3412 3413;; On the mips16, we can split lw $r,N($r) into an add and a load, 3414;; when the original load is a 4 byte instruction but the add and the 3415;; load are 2 2 byte instructions. 3416 3417(define_split 3418 [(set (match_operand:SI 0 "register_operand") 3419 (mem:SI (plus:SI (match_dup 0) 3420 (match_operand:SI 1 "const_int_operand"))))] 3421 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3422 && REG_P (operands[0]) 3423 && M16_REG_P (REGNO (operands[0])) 3424 && GET_CODE (operands[1]) == CONST_INT 3425 && ((INTVAL (operands[1]) < 0 3426 && INTVAL (operands[1]) >= -0x80) 3427 || (INTVAL (operands[1]) >= 32 * 4 3428 && INTVAL (operands[1]) <= 31 * 4 + 0x7c) 3429 || (INTVAL (operands[1]) >= 0 3430 && INTVAL (operands[1]) < 32 * 4 3431 && (INTVAL (operands[1]) & 3) != 0))" 3432 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) 3433 (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))] 3434{ 3435 HOST_WIDE_INT val = INTVAL (operands[1]); 3436 3437 if (val < 0) 3438 operands[2] = const0_rtx; 3439 else if (val >= 32 * 4) 3440 { 3441 int off = val & 3; 3442 3443 operands[1] = GEN_INT (0x7c + off); 3444 operands[2] = GEN_INT (val - off - 0x7c); 3445 } 3446 else 3447 { 3448 int off = val & 3; 3449 3450 operands[1] = GEN_INT (off); 3451 operands[2] = GEN_INT (val - off); 3452 } 3453}) 3454 3455;; On the mips16, we can split a load of certain constants into a load 3456;; and an add. This turns a 4 byte instruction into 2 2 byte 3457;; instructions. 3458 3459(define_split 3460 [(set (match_operand:SI 0 "register_operand") 3461 (match_operand:SI 1 "const_int_operand"))] 3462 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3463 && REG_P (operands[0]) 3464 && M16_REG_P (REGNO (operands[0])) 3465 && GET_CODE (operands[1]) == CONST_INT 3466 && INTVAL (operands[1]) >= 0x100 3467 && INTVAL (operands[1]) <= 0xff + 0x7f" 3468 [(set (match_dup 0) (match_dup 1)) 3469 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 3470{ 3471 int val = INTVAL (operands[1]); 3472 3473 operands[1] = GEN_INT (0xff); 3474 operands[2] = GEN_INT (val - 0xff); 3475}) 3476 3477;; This insn handles moving CCmode values. It's really just a 3478;; slightly simplified copy of movsi_internal2, with additional cases 3479;; to move a condition register to a general register and to move 3480;; between the general registers and the floating point registers. 3481 3482(define_insn "movcc" 3483 [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m") 3484 (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))] 3485 "ISA_HAS_8CC && TARGET_HARD_FLOAT" 3486 { return mips_output_move (operands[0], operands[1]); } 3487 [(set_attr "type" "xfer,arith,load,store,xfer,xfer,fmove,fpload,fpstore") 3488 (set_attr "mode" "SI") 3489 (set_attr "length" "8,4,*,*,4,4,4,*,*")]) 3490 3491;; Reload condition code registers. reload_incc and reload_outcc 3492;; both handle moves from arbitrary operands into condition code 3493;; registers. reload_incc handles the more common case in which 3494;; a source operand is constrained to be in a condition-code 3495;; register, but has not been allocated to one. 3496;; 3497;; Sometimes, such as in movcc, we have a CCmode destination whose 3498;; constraints do not include 'z'. reload_outcc handles the case 3499;; when such an operand is allocated to a condition-code register. 3500;; 3501;; Note that reloads from a condition code register to some 3502;; other location can be done using ordinary moves. Moving 3503;; into a GPR takes a single movcc, moving elsewhere takes 3504;; two. We can leave these cases to the generic reload code. 3505(define_expand "reload_incc" 3506 [(set (match_operand:CC 0 "fcc_reload_operand" "=z") 3507 (match_operand:CC 1 "general_operand" "")) 3508 (clobber (match_operand:TF 2 "register_operand" "=&f"))] 3509 "ISA_HAS_8CC && TARGET_HARD_FLOAT" 3510{ 3511 mips_emit_fcc_reload (operands[0], operands[1], operands[2]); 3512 DONE; 3513}) 3514 3515(define_expand "reload_outcc" 3516 [(set (match_operand:CC 0 "fcc_reload_operand" "=z") 3517 (match_operand:CC 1 "register_operand" "")) 3518 (clobber (match_operand:TF 2 "register_operand" "=&f"))] 3519 "ISA_HAS_8CC && TARGET_HARD_FLOAT" 3520{ 3521 mips_emit_fcc_reload (operands[0], operands[1], operands[2]); 3522 DONE; 3523}) 3524 3525;; MIPS4 supports loading and storing a floating point register from 3526;; the sum of two general registers. We use two versions for each of 3527;; these four instructions: one where the two general registers are 3528;; SImode, and one where they are DImode. This is because general 3529;; registers will be in SImode when they hold 32 bit values, but, 3530;; since the 32 bit values are always sign extended, the [ls][wd]xc1 3531;; instructions will still work correctly. 3532 3533;; ??? Perhaps it would be better to support these instructions by 3534;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since 3535;; these instructions can only be used to load and store floating 3536;; point registers, that would probably cause trouble in reload. 3537 3538(define_insn "*<ANYF:loadx>_<P:mode>" 3539 [(set (match_operand:ANYF 0 "register_operand" "=f") 3540 (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d") 3541 (match_operand:P 2 "register_operand" "d"))))] 3542 "ISA_HAS_FP4" 3543 "<ANYF:loadx>\t%0,%1(%2)" 3544 [(set_attr "type" "fpidxload") 3545 (set_attr "mode" "<ANYF:UNITMODE>")]) 3546 3547(define_insn "*<ANYF:storex>_<P:mode>" 3548 [(set (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d") 3549 (match_operand:P 2 "register_operand" "d"))) 3550 (match_operand:ANYF 0 "register_operand" "f"))] 3551 "ISA_HAS_FP4" 3552 "<ANYF:storex>\t%0,%1(%2)" 3553 [(set_attr "type" "fpidxstore") 3554 (set_attr "mode" "<ANYF:UNITMODE>")]) 3555 3556;; 16-bit Integer moves 3557 3558;; Unlike most other insns, the move insns can't be split with 3559;; different predicates, because register spilling and other parts of 3560;; the compiler, have memoized the insn number already. 3561;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. 3562 3563(define_expand "movhi" 3564 [(set (match_operand:HI 0 "") 3565 (match_operand:HI 1 ""))] 3566 "" 3567{ 3568 if (mips_legitimize_move (HImode, operands[0], operands[1])) 3569 DONE; 3570}) 3571 3572(define_insn "*movhi_internal" 3573 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x") 3574 (match_operand:HI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))] 3575 "!TARGET_MIPS16 3576 && (register_operand (operands[0], HImode) 3577 || reg_or_0_operand (operands[1], HImode))" 3578 "@ 3579 move\t%0,%1 3580 li\t%0,%1 3581 lhu\t%0,%1 3582 sh\t%z1,%0 3583 mfc1\t%0,%1 3584 mtc1\t%1,%0 3585 mov.s\t%0,%1 3586 mt%0\t%1" 3587 [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo") 3588 (set_attr "mode" "HI") 3589 (set_attr "length" "4,4,*,*,4,4,4,4")]) 3590 3591(define_insn "*movhi_mips16" 3592 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") 3593 (match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d"))] 3594 "TARGET_MIPS16 3595 && (register_operand (operands[0], HImode) 3596 || register_operand (operands[1], HImode))" 3597 "@ 3598 move\t%0,%1 3599 move\t%0,%1 3600 move\t%0,%1 3601 li\t%0,%1 3602 # 3603 lhu\t%0,%1 3604 sh\t%1,%0" 3605 [(set_attr "type" "arith,arith,arith,arith,arith,load,store") 3606 (set_attr "mode" "HI") 3607 (set_attr_alternative "length" 3608 [(const_int 4) 3609 (const_int 4) 3610 (const_int 4) 3611 (if_then_else (match_operand:VOID 1 "m16_uimm8_1") 3612 (const_int 4) 3613 (const_int 8)) 3614 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") 3615 (const_int 8) 3616 (const_int 12)) 3617 (const_string "*") 3618 (const_string "*")])]) 3619 3620 3621;; On the mips16, we can split lh $r,N($r) into an add and a load, 3622;; when the original load is a 4 byte instruction but the add and the 3623;; load are 2 2 byte instructions. 3624 3625(define_split 3626 [(set (match_operand:HI 0 "register_operand") 3627 (mem:HI (plus:SI (match_dup 0) 3628 (match_operand:SI 1 "const_int_operand"))))] 3629 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3630 && REG_P (operands[0]) 3631 && M16_REG_P (REGNO (operands[0])) 3632 && GET_CODE (operands[1]) == CONST_INT 3633 && ((INTVAL (operands[1]) < 0 3634 && INTVAL (operands[1]) >= -0x80) 3635 || (INTVAL (operands[1]) >= 32 * 2 3636 && INTVAL (operands[1]) <= 31 * 2 + 0x7e) 3637 || (INTVAL (operands[1]) >= 0 3638 && INTVAL (operands[1]) < 32 * 2 3639 && (INTVAL (operands[1]) & 1) != 0))" 3640 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) 3641 (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))] 3642{ 3643 HOST_WIDE_INT val = INTVAL (operands[1]); 3644 3645 if (val < 0) 3646 operands[2] = const0_rtx; 3647 else if (val >= 32 * 2) 3648 { 3649 int off = val & 1; 3650 3651 operands[1] = GEN_INT (0x7e + off); 3652 operands[2] = GEN_INT (val - off - 0x7e); 3653 } 3654 else 3655 { 3656 int off = val & 1; 3657 3658 operands[1] = GEN_INT (off); 3659 operands[2] = GEN_INT (val - off); 3660 } 3661}) 3662 3663;; 8-bit Integer moves 3664 3665;; Unlike most other insns, the move insns can't be split with 3666;; different predicates, because register spilling and other parts of 3667;; the compiler, have memoized the insn number already. 3668;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. 3669 3670(define_expand "movqi" 3671 [(set (match_operand:QI 0 "") 3672 (match_operand:QI 1 ""))] 3673 "" 3674{ 3675 if (mips_legitimize_move (QImode, operands[0], operands[1])) 3676 DONE; 3677}) 3678 3679(define_insn "*movqi_internal" 3680 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x") 3681 (match_operand:QI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))] 3682 "!TARGET_MIPS16 3683 && (register_operand (operands[0], QImode) 3684 || reg_or_0_operand (operands[1], QImode))" 3685 "@ 3686 move\t%0,%1 3687 li\t%0,%1 3688 lbu\t%0,%1 3689 sb\t%z1,%0 3690 mfc1\t%0,%1 3691 mtc1\t%1,%0 3692 mov.s\t%0,%1 3693 mt%0\t%1" 3694 [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo") 3695 (set_attr "mode" "QI") 3696 (set_attr "length" "4,4,*,*,4,4,4,4")]) 3697 3698(define_insn "*movqi_mips16" 3699 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") 3700 (match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d"))] 3701 "TARGET_MIPS16 3702 && (register_operand (operands[0], QImode) 3703 || register_operand (operands[1], QImode))" 3704 "@ 3705 move\t%0,%1 3706 move\t%0,%1 3707 move\t%0,%1 3708 li\t%0,%1 3709 # 3710 lbu\t%0,%1 3711 sb\t%1,%0" 3712 [(set_attr "type" "arith,arith,arith,arith,arith,load,store") 3713 (set_attr "mode" "QI") 3714 (set_attr "length" "4,4,4,4,8,*,*")]) 3715 3716;; On the mips16, we can split lb $r,N($r) into an add and a load, 3717;; when the original load is a 4 byte instruction but the add and the 3718;; load are 2 2 byte instructions. 3719 3720(define_split 3721 [(set (match_operand:QI 0 "register_operand") 3722 (mem:QI (plus:SI (match_dup 0) 3723 (match_operand:SI 1 "const_int_operand"))))] 3724 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3725 && REG_P (operands[0]) 3726 && M16_REG_P (REGNO (operands[0])) 3727 && GET_CODE (operands[1]) == CONST_INT 3728 && ((INTVAL (operands[1]) < 0 3729 && INTVAL (operands[1]) >= -0x80) 3730 || (INTVAL (operands[1]) >= 32 3731 && INTVAL (operands[1]) <= 31 + 0x7f))" 3732 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) 3733 (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))] 3734{ 3735 HOST_WIDE_INT val = INTVAL (operands[1]); 3736 3737 if (val < 0) 3738 operands[2] = const0_rtx; 3739 else 3740 { 3741 operands[1] = GEN_INT (0x7f); 3742 operands[2] = GEN_INT (val - 0x7f); 3743 } 3744}) 3745 3746;; 32-bit floating point moves 3747 3748(define_expand "movsf" 3749 [(set (match_operand:SF 0 "") 3750 (match_operand:SF 1 ""))] 3751 "" 3752{ 3753 if (mips_legitimize_move (SFmode, operands[0], operands[1])) 3754 DONE; 3755}) 3756 3757(define_insn "*movsf_hardfloat" 3758 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3759 (match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))] 3760 "TARGET_HARD_FLOAT 3761 && (register_operand (operands[0], SFmode) 3762 || reg_or_0_operand (operands[1], SFmode))" 3763 { return mips_output_move (operands[0], operands[1]); } 3764 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3765 (set_attr "mode" "SF") 3766 (set_attr "length" "4,4,*,*,*,4,4,4,*,*")]) 3767 3768(define_insn "*movsf_softfloat" 3769 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m") 3770 (match_operand:SF 1 "move_operand" "Gd,m,d"))] 3771 "TARGET_SOFT_FLOAT && !TARGET_MIPS16 3772 && (register_operand (operands[0], SFmode) 3773 || reg_or_0_operand (operands[1], SFmode))" 3774 { return mips_output_move (operands[0], operands[1]); } 3775 [(set_attr "type" "arith,load,store") 3776 (set_attr "mode" "SF") 3777 (set_attr "length" "4,*,*")]) 3778 3779(define_insn "*movsf_mips16" 3780 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,m") 3781 (match_operand:SF 1 "move_operand" "d,d,y,m,d"))] 3782 "TARGET_MIPS16 3783 && (register_operand (operands[0], SFmode) 3784 || register_operand (operands[1], SFmode))" 3785 { return mips_output_move (operands[0], operands[1]); } 3786 [(set_attr "type" "arith,arith,arith,load,store") 3787 (set_attr "mode" "SF") 3788 (set_attr "length" "4,4,4,*,*")]) 3789 3790 3791;; 64-bit floating point moves 3792 3793(define_expand "movdf" 3794 [(set (match_operand:DF 0 "") 3795 (match_operand:DF 1 ""))] 3796 "" 3797{ 3798 if (mips_legitimize_move (DFmode, operands[0], operands[1])) 3799 DONE; 3800}) 3801 3802(define_insn "*movdf_hardfloat_64bit" 3803 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3804 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))] 3805 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_64BIT 3806 && (register_operand (operands[0], DFmode) 3807 || reg_or_0_operand (operands[1], DFmode))" 3808 { return mips_output_move (operands[0], operands[1]); } 3809 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3810 (set_attr "mode" "DF") 3811 (set_attr "length" "4,4,*,*,*,4,4,4,*,*")]) 3812 3813(define_insn "*movdf_hardfloat_32bit" 3814 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3815 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))] 3816 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT 3817 && (register_operand (operands[0], DFmode) 3818 || reg_or_0_operand (operands[1], DFmode))" 3819 { return mips_output_move (operands[0], operands[1]); } 3820 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3821 (set_attr "mode" "DF") 3822 (set_attr "length" "4,8,*,*,*,8,8,8,*,*")]) 3823 3824(define_insn "*movdf_softfloat" 3825 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,m,d,f,f") 3826 (match_operand:DF 1 "move_operand" "dG,m,dG,f,d,f"))] 3827 "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16 3828 && (register_operand (operands[0], DFmode) 3829 || reg_or_0_operand (operands[1], DFmode))" 3830 { return mips_output_move (operands[0], operands[1]); } 3831 [(set_attr "type" "arith,load,store,xfer,xfer,fmove") 3832 (set_attr "mode" "DF") 3833 (set_attr "length" "8,*,*,4,4,4")]) 3834 3835(define_insn "*movdf_mips16" 3836 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,m") 3837 (match_operand:DF 1 "move_operand" "d,d,y,m,d"))] 3838 "TARGET_MIPS16 3839 && (register_operand (operands[0], DFmode) 3840 || register_operand (operands[1], DFmode))" 3841 { return mips_output_move (operands[0], operands[1]); } 3842 [(set_attr "type" "arith,arith,arith,load,store") 3843 (set_attr "mode" "DF") 3844 (set_attr "length" "8,8,8,*,*")]) 3845 3846(define_split 3847 [(set (match_operand:DI 0 "nonimmediate_operand") 3848 (match_operand:DI 1 "move_operand"))] 3849 "reload_completed && !TARGET_64BIT 3850 && mips_split_64bit_move_p (operands[0], operands[1])" 3851 [(const_int 0)] 3852{ 3853 mips_split_64bit_move (operands[0], operands[1]); 3854 DONE; 3855}) 3856 3857(define_split 3858 [(set (match_operand:DF 0 "nonimmediate_operand") 3859 (match_operand:DF 1 "move_operand"))] 3860 "reload_completed && !TARGET_64BIT 3861 && mips_split_64bit_move_p (operands[0], operands[1])" 3862 [(const_int 0)] 3863{ 3864 mips_split_64bit_move (operands[0], operands[1]); 3865 DONE; 3866}) 3867 3868;; When generating mips16 code, split moves of negative constants into 3869;; a positive "li" followed by a negation. 3870(define_split 3871 [(set (match_operand 0 "register_operand") 3872 (match_operand 1 "const_int_operand"))] 3873 "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0" 3874 [(set (match_dup 2) 3875 (match_dup 3)) 3876 (set (match_dup 2) 3877 (neg:SI (match_dup 2)))] 3878{ 3879 operands[2] = gen_lowpart (SImode, operands[0]); 3880 operands[3] = GEN_INT (-INTVAL (operands[1])); 3881}) 3882 3883;; 64-bit paired-single floating point moves 3884 3885(define_expand "movv2sf" 3886 [(set (match_operand:V2SF 0) 3887 (match_operand:V2SF 1))] 3888 "TARGET_PAIRED_SINGLE_FLOAT" 3889{ 3890 if (mips_legitimize_move (V2SFmode, operands[0], operands[1])) 3891 DONE; 3892}) 3893 3894(define_insn "movv2sf_hardfloat_64bit" 3895 [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3896 (match_operand:V2SF 1 "move_operand" "f,YG,m,f,YG,*d,*f,*d*YG,*m,*d"))] 3897 "TARGET_PAIRED_SINGLE_FLOAT 3898 && TARGET_64BIT 3899 && (register_operand (operands[0], V2SFmode) 3900 || reg_or_0_operand (operands[1], V2SFmode))" 3901 { return mips_output_move (operands[0], operands[1]); } 3902 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3903 (set_attr "mode" "SF") 3904 (set_attr "length" "4,4,*,*,*,4,4,4,*,*")]) 3905 3906;; The HI and LO registers are not truly independent. If we move an mthi 3907;; instruction before an mflo instruction, it will make the result of the 3908;; mflo unpredictable. The same goes for mtlo and mfhi. 3909;; 3910;; We cope with this by making the mflo and mfhi patterns use both HI and LO. 3911;; Operand 1 is the register we want, operand 2 is the other one. 3912;; 3913;; When generating VR4120 or VR4130 code, we use macc{,hi} and 3914;; dmacc{,hi} instead of mfhi and mflo. This avoids both the normal 3915;; MIPS III hi/lo hazards and the errata related to -mfix-vr4130. 3916 3917(define_expand "mfhilo_<mode>" 3918 [(set (match_operand:GPR 0 "register_operand") 3919 (unspec:GPR [(match_operand:GPR 1 "register_operand") 3920 (match_operand:GPR 2 "register_operand")] 3921 UNSPEC_MFHILO))]) 3922 3923(define_insn "*mfhilo_<mode>" 3924 [(set (match_operand:GPR 0 "register_operand" "=d,d") 3925 (unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l") 3926 (match_operand:GPR 2 "register_operand" "l,h")] 3927 UNSPEC_MFHILO))] 3928 "!ISA_HAS_MACCHI" 3929 "mf%1\t%0" 3930 [(set_attr "type" "mfhilo") 3931 (set_attr "mode" "<MODE>")]) 3932 3933(define_insn "*mfhilo_<mode>_macc" 3934 [(set (match_operand:GPR 0 "register_operand" "=d,d") 3935 (unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l") 3936 (match_operand:GPR 2 "register_operand" "l,h")] 3937 UNSPEC_MFHILO))] 3938 "ISA_HAS_MACCHI" 3939{ 3940 if (REGNO (operands[1]) == HI_REGNUM) 3941 return "<d>macchi\t%0,%.,%."; 3942 else 3943 return "<d>macc\t%0,%.,%."; 3944} 3945 [(set_attr "type" "mfhilo") 3946 (set_attr "mode" "<MODE>")]) 3947 3948;; Patterns for loading or storing part of a paired floating point 3949;; register. We need them because odd-numbered floating-point registers 3950;; are not fully independent: see mips_split_64bit_move. 3951 3952;; Load the low word of operand 0 with operand 1. 3953(define_insn "load_df_low" 3954 [(set (match_operand:DF 0 "register_operand" "=f,f") 3955 (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")] 3956 UNSPEC_LOAD_DF_LOW))] 3957 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" 3958{ 3959 operands[0] = mips_subword (operands[0], 0); 3960 return mips_output_move (operands[0], operands[1]); 3961} 3962 [(set_attr "type" "xfer,fpload") 3963 (set_attr "mode" "SF")]) 3964 3965;; Load the high word of operand 0 from operand 1, preserving the value 3966;; in the low word. 3967(define_insn "load_df_high" 3968 [(set (match_operand:DF 0 "register_operand" "=f,f") 3969 (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m") 3970 (match_operand:DF 2 "register_operand" "0,0")] 3971 UNSPEC_LOAD_DF_HIGH))] 3972 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" 3973{ 3974 operands[0] = mips_subword (operands[0], 1); 3975 return mips_output_move (operands[0], operands[1]); 3976} 3977 [(set_attr "type" "xfer,fpload") 3978 (set_attr "mode" "SF")]) 3979 3980;; Store the high word of operand 1 in operand 0. The corresponding 3981;; low-word move is done in the normal way. 3982(define_insn "store_df_high" 3983 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m") 3984 (unspec:SI [(match_operand:DF 1 "register_operand" "f,f")] 3985 UNSPEC_STORE_DF_HIGH))] 3986 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" 3987{ 3988 operands[1] = mips_subword (operands[1], 1); 3989 return mips_output_move (operands[0], operands[1]); 3990} 3991 [(set_attr "type" "xfer,fpstore") 3992 (set_attr "mode" "SF")]) 3993 3994;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset 3995;; of _gp from the start of this function. Operand 1 is the incoming 3996;; function address. 3997(define_insn_and_split "loadgp" 3998 [(unspec_volatile [(match_operand 0 "" "") 3999 (match_operand 1 "register_operand" "")] UNSPEC_LOADGP)] 4000 "mips_current_loadgp_style () == LOADGP_NEWABI" 4001 "#" 4002 "" 4003 [(set (match_dup 2) (match_dup 3)) 4004 (set (match_dup 2) (match_dup 4)) 4005 (set (match_dup 2) (match_dup 5))] 4006{ 4007 operands[2] = pic_offset_table_rtx; 4008 operands[3] = gen_rtx_HIGH (Pmode, operands[0]); 4009 operands[4] = gen_rtx_PLUS (Pmode, operands[2], operands[1]); 4010 operands[5] = gen_rtx_LO_SUM (Pmode, operands[2], operands[0]); 4011} 4012 [(set_attr "length" "12")]) 4013 4014;; Likewise, for -mno-shared code. Operand 0 is the __gnu_local_gp symbol. 4015(define_insn_and_split "loadgp_noshared" 4016 [(unspec_volatile [(match_operand 0 "" "")] UNSPEC_LOADGP)] 4017 "mips_current_loadgp_style () == LOADGP_ABSOLUTE" 4018 "#" 4019 "" 4020 [(const_int 0)] 4021{ 4022 emit_move_insn (pic_offset_table_rtx, operands[0]); 4023 DONE; 4024} 4025 [(set_attr "length" "8")]) 4026 4027;; The use of gp is hidden when not using explicit relocations. 4028;; This blockage instruction prevents the gp load from being 4029;; scheduled after an implicit use of gp. It also prevents 4030;; the load from being deleted as dead. 4031(define_insn "loadgp_blockage" 4032 [(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)] 4033 "" 4034 "" 4035 [(set_attr "type" "unknown") 4036 (set_attr "mode" "none") 4037 (set_attr "length" "0")]) 4038 4039;; Emit a .cprestore directive, which normally expands to a single store 4040;; instruction. Note that we continue to use .cprestore for explicit reloc 4041;; code so that jals inside inline asms will work correctly. 4042(define_insn "cprestore" 4043 [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")] 4044 UNSPEC_CPRESTORE)] 4045 "" 4046{ 4047 if (set_nomacro && which_alternative == 1) 4048 return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro"; 4049 else 4050 return ".cprestore\t%0"; 4051} 4052 [(set_attr "type" "store") 4053 (set_attr "length" "4,12")]) 4054 4055;; Block moves, see mips.c for more details. 4056;; Argument 0 is the destination 4057;; Argument 1 is the source 4058;; Argument 2 is the length 4059;; Argument 3 is the alignment 4060 4061(define_expand "movmemsi" 4062 [(parallel [(set (match_operand:BLK 0 "general_operand") 4063 (match_operand:BLK 1 "general_operand")) 4064 (use (match_operand:SI 2 "")) 4065 (use (match_operand:SI 3 "const_int_operand"))])] 4066 "!TARGET_MIPS16 && !TARGET_MEMCPY" 4067{ 4068 if (mips_expand_block_move (operands[0], operands[1], operands[2])) 4069 DONE; 4070 else 4071 FAIL; 4072}) 4073 4074;; 4075;; .................... 4076;; 4077;; SHIFTS 4078;; 4079;; .................... 4080 4081(define_expand "<optab><mode>3" 4082 [(set (match_operand:GPR 0 "register_operand") 4083 (any_shift:GPR (match_operand:GPR 1 "register_operand") 4084 (match_operand:SI 2 "arith_operand")))] 4085 "" 4086{ 4087 /* On the mips16, a shift of more than 8 is a four byte instruction, 4088 so, for a shift between 8 and 16, it is just as fast to do two 4089 shifts of 8 or less. If there is a lot of shifting going on, we 4090 may win in CSE. Otherwise combine will put the shifts back 4091 together again. This can be called by function_arg, so we must 4092 be careful not to allocate a new register if we've reached the 4093 reload pass. */ 4094 if (TARGET_MIPS16 4095 && optimize 4096 && GET_CODE (operands[2]) == CONST_INT 4097 && INTVAL (operands[2]) > 8 4098 && INTVAL (operands[2]) <= 16 4099 && !reload_in_progress 4100 && !reload_completed) 4101 { 4102 rtx temp = gen_reg_rtx (<MODE>mode); 4103 4104 emit_insn (gen_<optab><mode>3 (temp, operands[1], GEN_INT (8))); 4105 emit_insn (gen_<optab><mode>3 (operands[0], temp, 4106 GEN_INT (INTVAL (operands[2]) - 8))); 4107 DONE; 4108 } 4109}) 4110 4111(define_insn "*<optab><mode>3" 4112 [(set (match_operand:GPR 0 "register_operand" "=d") 4113 (any_shift:GPR (match_operand:GPR 1 "register_operand" "d") 4114 (match_operand:SI 2 "arith_operand" "dI")))] 4115 "!TARGET_MIPS16" 4116{ 4117 if (GET_CODE (operands[2]) == CONST_INT) 4118 operands[2] = GEN_INT (INTVAL (operands[2]) 4119 & (GET_MODE_BITSIZE (<MODE>mode) - 1)); 4120 4121 return "<d><insn>\t%0,%1,%2"; 4122} 4123 [(set_attr "type" "shift") 4124 (set_attr "mode" "<MODE>")]) 4125 4126(define_insn "*<optab>si3_extend" 4127 [(set (match_operand:DI 0 "register_operand" "=d") 4128 (sign_extend:DI 4129 (any_shift:SI (match_operand:SI 1 "register_operand" "d") 4130 (match_operand:SI 2 "arith_operand" "dI"))))] 4131 "TARGET_64BIT && !TARGET_MIPS16" 4132{ 4133 if (GET_CODE (operands[2]) == CONST_INT) 4134 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 4135 4136 return "<insn>\t%0,%1,%2"; 4137} 4138 [(set_attr "type" "shift") 4139 (set_attr "mode" "SI")]) 4140 4141(define_insn "*<optab>si3_mips16" 4142 [(set (match_operand:SI 0 "register_operand" "=d,d") 4143 (any_shift:SI (match_operand:SI 1 "register_operand" "0,d") 4144 (match_operand:SI 2 "arith_operand" "d,I")))] 4145 "TARGET_MIPS16" 4146{ 4147 if (which_alternative == 0) 4148 return "<insn>\t%0,%2"; 4149 4150 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 4151 return "<insn>\t%0,%1,%2"; 4152} 4153 [(set_attr "type" "shift") 4154 (set_attr "mode" "SI") 4155 (set_attr_alternative "length" 4156 [(const_int 4) 4157 (if_then_else (match_operand 2 "m16_uimm3_b") 4158 (const_int 4) 4159 (const_int 8))])]) 4160 4161;; We need separate DImode MIPS16 patterns because of the irregularity 4162;; of right shifts. 4163(define_insn "*ashldi3_mips16" 4164 [(set (match_operand:DI 0 "register_operand" "=d,d") 4165 (ashift:DI (match_operand:DI 1 "register_operand" "0,d") 4166 (match_operand:SI 2 "arith_operand" "d,I")))] 4167 "TARGET_64BIT && TARGET_MIPS16" 4168{ 4169 if (which_alternative == 0) 4170 return "dsll\t%0,%2"; 4171 4172 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); 4173 return "dsll\t%0,%1,%2"; 4174} 4175 [(set_attr "type" "shift") 4176 (set_attr "mode" "DI") 4177 (set_attr_alternative "length" 4178 [(const_int 4) 4179 (if_then_else (match_operand 2 "m16_uimm3_b") 4180 (const_int 4) 4181 (const_int 8))])]) 4182 4183(define_insn "*ashrdi3_mips16" 4184 [(set (match_operand:DI 0 "register_operand" "=d,d") 4185 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0") 4186 (match_operand:SI 2 "arith_operand" "d,I")))] 4187 "TARGET_64BIT && TARGET_MIPS16" 4188{ 4189 if (GET_CODE (operands[2]) == CONST_INT) 4190 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); 4191 4192 return "dsra\t%0,%2"; 4193} 4194 [(set_attr "type" "shift") 4195 (set_attr "mode" "DI") 4196 (set_attr_alternative "length" 4197 [(const_int 4) 4198 (if_then_else (match_operand 2 "m16_uimm3_b") 4199 (const_int 4) 4200 (const_int 8))])]) 4201 4202(define_insn "*lshrdi3_mips16" 4203 [(set (match_operand:DI 0 "register_operand" "=d,d") 4204 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0") 4205 (match_operand:SI 2 "arith_operand" "d,I")))] 4206 "TARGET_64BIT && TARGET_MIPS16" 4207{ 4208 if (GET_CODE (operands[2]) == CONST_INT) 4209 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); 4210 4211 return "dsrl\t%0,%2"; 4212} 4213 [(set_attr "type" "shift") 4214 (set_attr "mode" "DI") 4215 (set_attr_alternative "length" 4216 [(const_int 4) 4217 (if_then_else (match_operand 2 "m16_uimm3_b") 4218 (const_int 4) 4219 (const_int 8))])]) 4220 4221;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. 4222 4223(define_split 4224 [(set (match_operand:GPR 0 "register_operand") 4225 (any_shift:GPR (match_operand:GPR 1 "register_operand") 4226 (match_operand:GPR 2 "const_int_operand")))] 4227 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 4228 && GET_CODE (operands[2]) == CONST_INT 4229 && INTVAL (operands[2]) > 8 4230 && INTVAL (operands[2]) <= 16" 4231 [(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8))) 4232 (set (match_dup 0) (any_shift:GPR (match_dup 0) (match_dup 2)))] 4233 { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) 4234 4235;; If we load a byte on the mips16 as a bitfield, the resulting 4236;; sequence of instructions is too complicated for combine, because it 4237;; involves four instructions: a load, a shift, a constant load into a 4238;; register, and an and (the key problem here is that the mips16 does 4239;; not have and immediate). We recognize a shift of a load in order 4240;; to make it simple enough for combine to understand. 4241;; 4242;; The length here is the worst case: the length of the split version 4243;; will be more accurate. 4244(define_insn_and_split "" 4245 [(set (match_operand:SI 0 "register_operand" "=d") 4246 (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") 4247 (match_operand:SI 2 "immediate_operand" "I")))] 4248 "TARGET_MIPS16" 4249 "#" 4250 "" 4251 [(set (match_dup 0) (match_dup 1)) 4252 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] 4253 "" 4254 [(set_attr "type" "load") 4255 (set_attr "mode" "SI") 4256 (set_attr "length" "16")]) 4257 4258(define_insn "rotr<mode>3" 4259 [(set (match_operand:GPR 0 "register_operand" "=d") 4260 (rotatert:GPR (match_operand:GPR 1 "register_operand" "d") 4261 (match_operand:SI 2 "arith_operand" "dI")))] 4262 "ISA_HAS_ROTR_<MODE>" 4263{ 4264 if (GET_CODE (operands[2]) == CONST_INT) 4265 gcc_assert (INTVAL (operands[2]) >= 0 4266 && INTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)); 4267 4268 return "<d>ror\t%0,%1,%2"; 4269} 4270 [(set_attr "type" "shift") 4271 (set_attr "mode" "<MODE>")]) 4272 4273;; 4274;; .................... 4275;; 4276;; COMPARISONS 4277;; 4278;; .................... 4279 4280;; Flow here is rather complex: 4281;; 4282;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments 4283;; into cmp_operands[] but generates no RTL. 4284;; 4285;; 2) The appropriate branch define_expand is called, which then 4286;; creates the appropriate RTL for the comparison and branch. 4287;; Different CC modes are used, based on what type of branch is 4288;; done, so that we can constrain things appropriately. There 4289;; are assumptions in the rest of GCC that break if we fold the 4290;; operands into the branches for integer operations, and use cc0 4291;; for floating point, so we use the fp status register instead. 4292;; If needed, an appropriate temporary is created to hold the 4293;; of the integer compare. 4294 4295(define_expand "cmp<mode>" 4296 [(set (cc0) 4297 (compare:CC (match_operand:GPR 0 "register_operand") 4298 (match_operand:GPR 1 "nonmemory_operand")))] 4299 "" 4300{ 4301 cmp_operands[0] = operands[0]; 4302 cmp_operands[1] = operands[1]; 4303 DONE; 4304}) 4305 4306(define_expand "cmp<mode>" 4307 [(set (cc0) 4308 (compare:CC (match_operand:SCALARF 0 "register_operand") 4309 (match_operand:SCALARF 1 "register_operand")))] 4310 "" 4311{ 4312 cmp_operands[0] = operands[0]; 4313 cmp_operands[1] = operands[1]; 4314 DONE; 4315}) 4316 4317;; 4318;; .................... 4319;; 4320;; CONDITIONAL BRANCHES 4321;; 4322;; .................... 4323 4324;; Conditional branches on floating-point equality tests. 4325 4326(define_insn "*branch_fp" 4327 [(set (pc) 4328 (if_then_else 4329 (match_operator 0 "equality_operator" 4330 [(match_operand:CC 2 "register_operand" "z") 4331 (const_int 0)]) 4332 (label_ref (match_operand 1 "" "")) 4333 (pc)))] 4334 "TARGET_HARD_FLOAT" 4335{ 4336 return mips_output_conditional_branch (insn, operands, 4337 MIPS_BRANCH ("b%F0", "%Z2%1"), 4338 MIPS_BRANCH ("b%W0", "%Z2%1")); 4339} 4340 [(set_attr "type" "branch") 4341 (set_attr "mode" "none")]) 4342 4343(define_insn "*branch_fp_inverted" 4344 [(set (pc) 4345 (if_then_else 4346 (match_operator 0 "equality_operator" 4347 [(match_operand:CC 2 "register_operand" "z") 4348 (const_int 0)]) 4349 (pc) 4350 (label_ref (match_operand 1 "" ""))))] 4351 "TARGET_HARD_FLOAT" 4352{ 4353 return mips_output_conditional_branch (insn, operands, 4354 MIPS_BRANCH ("b%W0", "%Z2%1"), 4355 MIPS_BRANCH ("b%F0", "%Z2%1")); 4356} 4357 [(set_attr "type" "branch") 4358 (set_attr "mode" "none")]) 4359 4360;; Conditional branches on ordered comparisons with zero. 4361 4362(define_insn "*branch_order<mode>" 4363 [(set (pc) 4364 (if_then_else 4365 (match_operator 0 "order_operator" 4366 [(match_operand:GPR 2 "register_operand" "d") 4367 (const_int 0)]) 4368 (label_ref (match_operand 1 "" "")) 4369 (pc)))] 4370 "!TARGET_MIPS16" 4371 { return mips_output_order_conditional_branch (insn, operands, false); } 4372 [(set_attr "type" "branch") 4373 (set_attr "mode" "none")]) 4374 4375(define_insn "*branch_order<mode>_inverted" 4376 [(set (pc) 4377 (if_then_else 4378 (match_operator 0 "order_operator" 4379 [(match_operand:GPR 2 "register_operand" "d") 4380 (const_int 0)]) 4381 (pc) 4382 (label_ref (match_operand 1 "" ""))))] 4383 "!TARGET_MIPS16" 4384 { return mips_output_order_conditional_branch (insn, operands, true); } 4385 [(set_attr "type" "branch") 4386 (set_attr "mode" "none")]) 4387 4388;; Conditional branch on equality comparison. 4389 4390(define_insn "*branch_equality<mode>" 4391 [(set (pc) 4392 (if_then_else 4393 (match_operator 0 "equality_operator" 4394 [(match_operand:GPR 2 "register_operand" "d") 4395 (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) 4396 (label_ref (match_operand 1 "" "")) 4397 (pc)))] 4398 "!TARGET_MIPS16" 4399{ 4400 return mips_output_conditional_branch (insn, operands, 4401 MIPS_BRANCH ("b%C0", "%2,%z3,%1"), 4402 MIPS_BRANCH ("b%N0", "%2,%z3,%1")); 4403} 4404 [(set_attr "type" "branch") 4405 (set_attr "mode" "none")]) 4406 4407(define_insn "*branch_equality<mode>_inverted" 4408 [(set (pc) 4409 (if_then_else 4410 (match_operator 0 "equality_operator" 4411 [(match_operand:GPR 2 "register_operand" "d") 4412 (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) 4413 (pc) 4414 (label_ref (match_operand 1 "" ""))))] 4415 "!TARGET_MIPS16" 4416{ 4417 return mips_output_conditional_branch (insn, operands, 4418 MIPS_BRANCH ("b%N0", "%2,%z3,%1"), 4419 MIPS_BRANCH ("b%C0", "%2,%z3,%1")); 4420} 4421 [(set_attr "type" "branch") 4422 (set_attr "mode" "none")]) 4423 4424;; MIPS16 branches 4425 4426(define_insn "*branch_equality<mode>_mips16" 4427 [(set (pc) 4428 (if_then_else 4429 (match_operator 0 "equality_operator" 4430 [(match_operand:GPR 1 "register_operand" "d,t") 4431 (const_int 0)]) 4432 (match_operand 2 "pc_or_label_operand" "") 4433 (match_operand 3 "pc_or_label_operand" "")))] 4434 "TARGET_MIPS16" 4435{ 4436 if (operands[2] != pc_rtx) 4437 { 4438 if (which_alternative == 0) 4439 return "b%C0z\t%1,%2"; 4440 else 4441 return "bt%C0z\t%2"; 4442 } 4443 else 4444 { 4445 if (which_alternative == 0) 4446 return "b%N0z\t%1,%3"; 4447 else 4448 return "bt%N0z\t%3"; 4449 } 4450} 4451 [(set_attr "type" "branch") 4452 (set_attr "mode" "none") 4453 (set_attr "length" "8")]) 4454 4455(define_expand "b<code>" 4456 [(set (pc) 4457 (if_then_else (any_cond:CC (cc0) 4458 (const_int 0)) 4459 (label_ref (match_operand 0 "")) 4460 (pc)))] 4461 "" 4462{ 4463 gen_conditional_branch (operands, <CODE>); 4464 DONE; 4465}) 4466 4467;; Used to implement built-in functions. 4468(define_expand "condjump" 4469 [(set (pc) 4470 (if_then_else (match_operand 0) 4471 (label_ref (match_operand 1)) 4472 (pc)))]) 4473 4474;; 4475;; .................... 4476;; 4477;; SETTING A REGISTER FROM A COMPARISON 4478;; 4479;; .................... 4480 4481(define_expand "seq" 4482 [(set (match_operand:SI 0 "register_operand") 4483 (eq:SI (match_dup 1) 4484 (match_dup 2)))] 4485 "" 4486 { if (mips_emit_scc (EQ, operands[0])) DONE; else FAIL; }) 4487 4488(define_insn "*seq_<mode>" 4489 [(set (match_operand:GPR 0 "register_operand" "=d") 4490 (eq:GPR (match_operand:GPR 1 "register_operand" "d") 4491 (const_int 0)))] 4492 "!TARGET_MIPS16" 4493 "sltu\t%0,%1,1" 4494 [(set_attr "type" "slt") 4495 (set_attr "mode" "<MODE>")]) 4496 4497(define_insn "*seq_<mode>_mips16" 4498 [(set (match_operand:GPR 0 "register_operand" "=t") 4499 (eq:GPR (match_operand:GPR 1 "register_operand" "d") 4500 (const_int 0)))] 4501 "TARGET_MIPS16" 4502 "sltu\t%1,1" 4503 [(set_attr "type" "slt") 4504 (set_attr "mode" "<MODE>")]) 4505 4506;; "sne" uses sltu instructions in which the first operand is $0. 4507;; This isn't possible in mips16 code. 4508 4509(define_expand "sne" 4510 [(set (match_operand:SI 0 "register_operand") 4511 (ne:SI (match_dup 1) 4512 (match_dup 2)))] 4513 "!TARGET_MIPS16" 4514 { if (mips_emit_scc (NE, operands[0])) DONE; else FAIL; }) 4515 4516(define_insn "*sne_<mode>" 4517 [(set (match_operand:GPR 0 "register_operand" "=d") 4518 (ne:GPR (match_operand:GPR 1 "register_operand" "d") 4519 (const_int 0)))] 4520 "!TARGET_MIPS16" 4521 "sltu\t%0,%.,%1" 4522 [(set_attr "type" "slt") 4523 (set_attr "mode" "<MODE>")]) 4524 4525(define_expand "sgt" 4526 [(set (match_operand:SI 0 "register_operand") 4527 (gt:SI (match_dup 1) 4528 (match_dup 2)))] 4529 "" 4530 { if (mips_emit_scc (GT, operands[0])) DONE; else FAIL; }) 4531 4532(define_insn "*sgt_<mode>" 4533 [(set (match_operand:GPR 0 "register_operand" "=d") 4534 (gt:GPR (match_operand:GPR 1 "register_operand" "d") 4535 (match_operand:GPR 2 "reg_or_0_operand" "dJ")))] 4536 "!TARGET_MIPS16" 4537 "slt\t%0,%z2,%1" 4538 [(set_attr "type" "slt") 4539 (set_attr "mode" "<MODE>")]) 4540 4541(define_insn "*sgt_<mode>_mips16" 4542 [(set (match_operand:GPR 0 "register_operand" "=t") 4543 (gt:GPR (match_operand:GPR 1 "register_operand" "d") 4544 (match_operand:GPR 2 "register_operand" "d")))] 4545 "TARGET_MIPS16" 4546 "slt\t%2,%1" 4547 [(set_attr "type" "slt") 4548 (set_attr "mode" "<MODE>")]) 4549 4550(define_expand "sge" 4551 [(set (match_operand:SI 0 "register_operand") 4552 (ge:SI (match_dup 1) 4553 (match_dup 2)))] 4554 "" 4555 { if (mips_emit_scc (GE, operands[0])) DONE; else FAIL; }) 4556 4557(define_insn "*sge_<mode>" 4558 [(set (match_operand:GPR 0 "register_operand" "=d") 4559 (ge:GPR (match_operand:GPR 1 "register_operand" "d") 4560 (const_int 1)))] 4561 "!TARGET_MIPS16" 4562 "slt\t%0,%.,%1" 4563 [(set_attr "type" "slt") 4564 (set_attr "mode" "<MODE>")]) 4565 4566(define_expand "slt" 4567 [(set (match_operand:SI 0 "register_operand") 4568 (lt:SI (match_dup 1) 4569 (match_dup 2)))] 4570 "" 4571 { if (mips_emit_scc (LT, operands[0])) DONE; else FAIL; }) 4572 4573(define_insn "*slt_<mode>" 4574 [(set (match_operand:GPR 0 "register_operand" "=d") 4575 (lt:GPR (match_operand:GPR 1 "register_operand" "d") 4576 (match_operand:GPR 2 "arith_operand" "dI")))] 4577 "!TARGET_MIPS16" 4578 "slt\t%0,%1,%2" 4579 [(set_attr "type" "slt") 4580 (set_attr "mode" "<MODE>")]) 4581 4582(define_insn "*slt_<mode>_mips16" 4583 [(set (match_operand:GPR 0 "register_operand" "=t,t") 4584 (lt:GPR (match_operand:GPR 1 "register_operand" "d,d") 4585 (match_operand:GPR 2 "arith_operand" "d,I")))] 4586 "TARGET_MIPS16" 4587 "slt\t%1,%2" 4588 [(set_attr "type" "slt") 4589 (set_attr "mode" "<MODE>") 4590 (set_attr_alternative "length" 4591 [(const_int 4) 4592 (if_then_else (match_operand 2 "m16_uimm8_1") 4593 (const_int 4) 4594 (const_int 8))])]) 4595 4596(define_expand "sle" 4597 [(set (match_operand:SI 0 "register_operand") 4598 (le:SI (match_dup 1) 4599 (match_dup 2)))] 4600 "" 4601 { if (mips_emit_scc (LE, operands[0])) DONE; else FAIL; }) 4602 4603(define_insn "*sle_<mode>" 4604 [(set (match_operand:GPR 0 "register_operand" "=d") 4605 (le:GPR (match_operand:GPR 1 "register_operand" "d") 4606 (match_operand:GPR 2 "sle_operand" "")))] 4607 "!TARGET_MIPS16" 4608{ 4609 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4610 return "slt\t%0,%1,%2"; 4611} 4612 [(set_attr "type" "slt") 4613 (set_attr "mode" "<MODE>")]) 4614 4615(define_insn "*sle_<mode>_mips16" 4616 [(set (match_operand:GPR 0 "register_operand" "=t") 4617 (le:GPR (match_operand:GPR 1 "register_operand" "d") 4618 (match_operand:GPR 2 "sle_operand" "")))] 4619 "TARGET_MIPS16" 4620{ 4621 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4622 return "slt\t%1,%2"; 4623} 4624 [(set_attr "type" "slt") 4625 (set_attr "mode" "<MODE>") 4626 (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1") 4627 (const_int 4) 4628 (const_int 8)))]) 4629 4630(define_expand "sgtu" 4631 [(set (match_operand:SI 0 "register_operand") 4632 (gtu:SI (match_dup 1) 4633 (match_dup 2)))] 4634 "" 4635 { if (mips_emit_scc (GTU, operands[0])) DONE; else FAIL; }) 4636 4637(define_insn "*sgtu_<mode>" 4638 [(set (match_operand:GPR 0 "register_operand" "=d") 4639 (gtu:GPR (match_operand:GPR 1 "register_operand" "d") 4640 (match_operand:GPR 2 "reg_or_0_operand" "dJ")))] 4641 "!TARGET_MIPS16" 4642 "sltu\t%0,%z2,%1" 4643 [(set_attr "type" "slt") 4644 (set_attr "mode" "<MODE>")]) 4645 4646(define_insn "*sgtu_<mode>_mips16" 4647 [(set (match_operand:GPR 0 "register_operand" "=t") 4648 (gtu:GPR (match_operand:GPR 1 "register_operand" "d") 4649 (match_operand:GPR 2 "register_operand" "d")))] 4650 "TARGET_MIPS16" 4651 "sltu\t%2,%1" 4652 [(set_attr "type" "slt") 4653 (set_attr "mode" "<MODE>")]) 4654 4655(define_expand "sgeu" 4656 [(set (match_operand:SI 0 "register_operand") 4657 (geu:SI (match_dup 1) 4658 (match_dup 2)))] 4659 "" 4660 { if (mips_emit_scc (GEU, operands[0])) DONE; else FAIL; }) 4661 4662(define_insn "*sge_<mode>" 4663 [(set (match_operand:GPR 0 "register_operand" "=d") 4664 (geu:GPR (match_operand:GPR 1 "register_operand" "d") 4665 (const_int 1)))] 4666 "!TARGET_MIPS16" 4667 "sltu\t%0,%.,%1" 4668 [(set_attr "type" "slt") 4669 (set_attr "mode" "<MODE>")]) 4670 4671(define_expand "sltu" 4672 [(set (match_operand:SI 0 "register_operand") 4673 (ltu:SI (match_dup 1) 4674 (match_dup 2)))] 4675 "" 4676 { if (mips_emit_scc (LTU, operands[0])) DONE; else FAIL; }) 4677 4678(define_insn "*sltu_<mode>" 4679 [(set (match_operand:GPR 0 "register_operand" "=d") 4680 (ltu:GPR (match_operand:GPR 1 "register_operand" "d") 4681 (match_operand:GPR 2 "arith_operand" "dI")))] 4682 "!TARGET_MIPS16" 4683 "sltu\t%0,%1,%2" 4684 [(set_attr "type" "slt") 4685 (set_attr "mode" "<MODE>")]) 4686 4687(define_insn "*sltu_<mode>_mips16" 4688 [(set (match_operand:GPR 0 "register_operand" "=t,t") 4689 (ltu:GPR (match_operand:GPR 1 "register_operand" "d,d") 4690 (match_operand:GPR 2 "arith_operand" "d,I")))] 4691 "TARGET_MIPS16" 4692 "sltu\t%1,%2" 4693 [(set_attr "type" "slt") 4694 (set_attr "mode" "<MODE>") 4695 (set_attr_alternative "length" 4696 [(const_int 4) 4697 (if_then_else (match_operand 2 "m16_uimm8_1") 4698 (const_int 4) 4699 (const_int 8))])]) 4700 4701(define_expand "sleu" 4702 [(set (match_operand:SI 0 "register_operand") 4703 (leu:SI (match_dup 1) 4704 (match_dup 2)))] 4705 "" 4706 { if (mips_emit_scc (LEU, operands[0])) DONE; else FAIL; }) 4707 4708(define_insn "*sleu_<mode>" 4709 [(set (match_operand:GPR 0 "register_operand" "=d") 4710 (leu:GPR (match_operand:GPR 1 "register_operand" "d") 4711 (match_operand:GPR 2 "sleu_operand" "")))] 4712 "!TARGET_MIPS16" 4713{ 4714 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4715 return "sltu\t%0,%1,%2"; 4716} 4717 [(set_attr "type" "slt") 4718 (set_attr "mode" "<MODE>")]) 4719 4720(define_insn "*sleu_<mode>_mips16" 4721 [(set (match_operand:GPR 0 "register_operand" "=t") 4722 (leu:GPR (match_operand:GPR 1 "register_operand" "d") 4723 (match_operand:GPR 2 "sleu_operand" "")))] 4724 "TARGET_MIPS16" 4725{ 4726 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4727 return "sltu\t%1,%2"; 4728} 4729 [(set_attr "type" "slt") 4730 (set_attr "mode" "<MODE>") 4731 (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1") 4732 (const_int 4) 4733 (const_int 8)))]) 4734 4735;; 4736;; .................... 4737;; 4738;; FLOATING POINT COMPARISONS 4739;; 4740;; .................... 4741 4742(define_insn "s<code>_<mode>" 4743 [(set (match_operand:CC 0 "register_operand" "=z") 4744 (fcond:CC (match_operand:SCALARF 1 "register_operand" "f") 4745 (match_operand:SCALARF 2 "register_operand" "f")))] 4746 "" 4747 "c.<fcond>.<fmt>\t%Z0%1,%2" 4748 [(set_attr "type" "fcmp") 4749 (set_attr "mode" "FPSW")]) 4750 4751(define_insn "s<code>_<mode>" 4752 [(set (match_operand:CC 0 "register_operand" "=z") 4753 (swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f") 4754 (match_operand:SCALARF 2 "register_operand" "f")))] 4755 "" 4756 "c.<swapped_fcond>.<fmt>\t%Z0%2,%1" 4757 [(set_attr "type" "fcmp") 4758 (set_attr "mode" "FPSW")]) 4759 4760;; 4761;; .................... 4762;; 4763;; UNCONDITIONAL BRANCHES 4764;; 4765;; .................... 4766 4767;; Unconditional branches. 4768 4769(define_insn "jump" 4770 [(set (pc) 4771 (label_ref (match_operand 0 "" "")))] 4772 "!TARGET_MIPS16" 4773{ 4774 if (flag_pic) 4775 { 4776 if (get_attr_length (insn) <= 8) 4777 return "%*b\t%l0%/"; 4778 else 4779 { 4780 output_asm_insn (mips_output_load_label (), operands); 4781 return "%*jr\t%@%/%]"; 4782 } 4783 } 4784 else 4785 return "%*j\t%l0%/"; 4786} 4787 [(set_attr "type" "jump") 4788 (set_attr "mode" "none") 4789 (set (attr "length") 4790 ;; We can't use `j' when emitting PIC. Emit a branch if it's 4791 ;; in range, otherwise load the address of the branch target into 4792 ;; $at and then jump to it. 4793 (if_then_else 4794 (ior (eq (symbol_ref "flag_pic") (const_int 0)) 4795 (lt (abs (minus (match_dup 0) 4796 (plus (pc) (const_int 4)))) 4797 (const_int 131072))) 4798 (const_int 4) (const_int 16)))]) 4799 4800;; We need a different insn for the mips16, because a mips16 branch 4801;; does not have a delay slot. 4802 4803(define_insn "" 4804 [(set (pc) 4805 (label_ref (match_operand 0 "" "")))] 4806 "TARGET_MIPS16" 4807 "b\t%l0" 4808 [(set_attr "type" "branch") 4809 (set_attr "mode" "none") 4810 (set_attr "length" "8")]) 4811 4812(define_expand "indirect_jump" 4813 [(set (pc) (match_operand 0 "register_operand"))] 4814 "" 4815{ 4816 operands[0] = force_reg (Pmode, operands[0]); 4817 if (Pmode == SImode) 4818 emit_jump_insn (gen_indirect_jumpsi (operands[0])); 4819 else 4820 emit_jump_insn (gen_indirect_jumpdi (operands[0])); 4821 DONE; 4822}) 4823 4824(define_insn "indirect_jump<mode>" 4825 [(set (pc) (match_operand:P 0 "register_operand" "d"))] 4826 "" 4827 "%*j\t%0%/" 4828 [(set_attr "type" "jump") 4829 (set_attr "mode" "none")]) 4830 4831(define_expand "tablejump" 4832 [(set (pc) 4833 (match_operand 0 "register_operand")) 4834 (use (label_ref (match_operand 1 "")))] 4835 "" 4836{ 4837 if (TARGET_MIPS16) 4838 operands[0] = expand_binop (Pmode, add_optab, 4839 convert_to_mode (Pmode, operands[0], false), 4840 gen_rtx_LABEL_REF (Pmode, operands[1]), 4841 0, 0, OPTAB_WIDEN); 4842 else if (TARGET_GPWORD) 4843 operands[0] = expand_binop (Pmode, add_optab, operands[0], 4844 pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); 4845 4846 if (Pmode == SImode) 4847 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); 4848 else 4849 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); 4850 DONE; 4851}) 4852 4853(define_insn "tablejump<mode>" 4854 [(set (pc) 4855 (match_operand:P 0 "register_operand" "d")) 4856 (use (label_ref (match_operand 1 "" "")))] 4857 "" 4858 "%*j\t%0%/" 4859 [(set_attr "type" "jump") 4860 (set_attr "mode" "none")]) 4861 4862;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well. 4863;; While it is possible to either pull it off the stack (in the 4864;; o32 case) or recalculate it given t9 and our target label, 4865;; it takes 3 or 4 insns to do so. 4866 4867(define_expand "builtin_setjmp_setup" 4868 [(use (match_operand 0 "register_operand"))] 4869 "TARGET_ABICALLS" 4870{ 4871 rtx addr; 4872 4873 addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3); 4874 emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx); 4875 DONE; 4876}) 4877 4878;; Restore the gp that we saved above. Despite the earlier comment, it seems 4879;; that older code did recalculate the gp from $25. Continue to jump through 4880;; $25 for compatibility (we lose nothing by doing so). 4881 4882(define_expand "builtin_longjmp" 4883 [(use (match_operand 0 "register_operand"))] 4884 "TARGET_ABICALLS" 4885{ 4886 /* The elements of the buffer are, in order: */ 4887 int W = GET_MODE_SIZE (Pmode); 4888 rtx fp = gen_rtx_MEM (Pmode, operands[0]); 4889 rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); 4890 rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); 4891 rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); 4892 rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM); 4893 /* Use gen_raw_REG to avoid being given pic_offset_table_rtx. 4894 The target is bound to be using $28 as the global pointer 4895 but the current function might not be. */ 4896 rtx gp = gen_raw_REG (Pmode, GLOBAL_POINTER_REGNUM); 4897 4898 /* This bit is similar to expand_builtin_longjmp except that it 4899 restores $gp as well. */ 4900 emit_move_insn (hard_frame_pointer_rtx, fp); 4901 emit_move_insn (pv, lab); 4902 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); 4903 emit_move_insn (gp, gpv); 4904 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 4905 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 4906 emit_insn (gen_rtx_USE (VOIDmode, gp)); 4907 emit_indirect_jump (pv); 4908 DONE; 4909}) 4910 4911;; 4912;; .................... 4913;; 4914;; Function prologue/epilogue 4915;; 4916;; .................... 4917;; 4918 4919(define_expand "prologue" 4920 [(const_int 1)] 4921 "" 4922{ 4923 mips_expand_prologue (); 4924 DONE; 4925}) 4926 4927;; Block any insns from being moved before this point, since the 4928;; profiling call to mcount can use various registers that aren't 4929;; saved or used to pass arguments. 4930 4931(define_insn "blockage" 4932 [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] 4933 "" 4934 "" 4935 [(set_attr "type" "unknown") 4936 (set_attr "mode" "none") 4937 (set_attr "length" "0")]) 4938 4939(define_expand "epilogue" 4940 [(const_int 2)] 4941 "" 4942{ 4943 mips_expand_epilogue (false); 4944 DONE; 4945}) 4946 4947(define_expand "sibcall_epilogue" 4948 [(const_int 2)] 4949 "" 4950{ 4951 mips_expand_epilogue (true); 4952 DONE; 4953}) 4954 4955;; Trivial return. Make it look like a normal return insn as that 4956;; allows jump optimizations to work better. 4957 4958(define_insn "return" 4959 [(return)] 4960 "mips_can_use_return_insn ()" 4961 "%*j\t$31%/" 4962 [(set_attr "type" "jump") 4963 (set_attr "mode" "none")]) 4964 4965;; Normal return. 4966 4967(define_insn "return_internal" 4968 [(return) 4969 (use (match_operand 0 "pmode_register_operand" ""))] 4970 "" 4971 "%*j\t%0%/" 4972 [(set_attr "type" "jump") 4973 (set_attr "mode" "none")]) 4974 4975;; This is used in compiling the unwind routines. 4976(define_expand "eh_return" 4977 [(use (match_operand 0 "general_operand"))] 4978 "" 4979{ 4980 enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode; 4981 4982 if (GET_MODE (operands[0]) != gpr_mode) 4983 operands[0] = convert_to_mode (gpr_mode, operands[0], 0); 4984 if (TARGET_64BIT) 4985 emit_insn (gen_eh_set_lr_di (operands[0])); 4986 else 4987 emit_insn (gen_eh_set_lr_si (operands[0])); 4988 4989 DONE; 4990}) 4991 4992;; Clobber the return address on the stack. We can't expand this 4993;; until we know where it will be put in the stack frame. 4994 4995(define_insn "eh_set_lr_si" 4996 [(unspec [(match_operand:SI 0 "register_operand" "d")] UNSPEC_EH_RETURN) 4997 (clobber (match_scratch:SI 1 "=&d"))] 4998 "! TARGET_64BIT" 4999 "#") 5000 5001(define_insn "eh_set_lr_di" 5002 [(unspec [(match_operand:DI 0 "register_operand" "d")] UNSPEC_EH_RETURN) 5003 (clobber (match_scratch:DI 1 "=&d"))] 5004 "TARGET_64BIT" 5005 "#") 5006 5007(define_split 5008 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) 5009 (clobber (match_scratch 1))] 5010 "reload_completed && !TARGET_DEBUG_D_MODE" 5011 [(const_int 0)] 5012{ 5013 mips_set_return_address (operands[0], operands[1]); 5014 DONE; 5015}) 5016 5017(define_insn_and_split "exception_receiver" 5018 [(set (reg:SI 28) 5019 (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))] 5020 "TARGET_ABICALLS && TARGET_OLDABI" 5021 "#" 5022 "&& reload_completed" 5023 [(const_int 0)] 5024{ 5025 mips_restore_gp (); 5026 DONE; 5027} 5028 [(set_attr "type" "load") 5029 (set_attr "length" "12")]) 5030 5031;; 5032;; .................... 5033;; 5034;; FUNCTION CALLS 5035;; 5036;; .................... 5037 5038;; Instructions to load a call address from the GOT. The address might 5039;; point to a function or to a lazy binding stub. In the latter case, 5040;; the stub will use the dynamic linker to resolve the function, which 5041;; in turn will change the GOT entry to point to the function's real 5042;; address. 5043;; 5044;; This means that every call, even pure and constant ones, can 5045;; potentially modify the GOT entry. And once a stub has been called, 5046;; we must not call it again. 5047;; 5048;; We represent this restriction using an imaginary fixed register that 5049;; acts like a GOT version number. By making the register call-clobbered, 5050;; we tell the target-independent code that the address could be changed 5051;; by any call insn. 5052(define_insn "load_call<mode>" 5053 [(set (match_operand:P 0 "register_operand" "=c") 5054 (unspec:P [(match_operand:P 1 "register_operand" "r") 5055 (match_operand:P 2 "immediate_operand" "") 5056 (reg:P FAKE_CALL_REGNO)] 5057 UNSPEC_LOAD_CALL))] 5058 "TARGET_ABICALLS" 5059 "<load>\t%0,%R2(%1)" 5060 [(set_attr "type" "load") 5061 (set_attr "mode" "<MODE>") 5062 (set_attr "length" "4")]) 5063 5064;; Sibling calls. All these patterns use jump instructions. 5065 5066;; If TARGET_SIBCALLS, call_insn_operand will only accept constant 5067;; addresses if a direct jump is acceptable. Since the 'S' constraint 5068;; is defined in terms of call_insn_operand, the same is true of the 5069;; constraints. 5070 5071;; When we use an indirect jump, we need a register that will be 5072;; preserved by the epilogue. Since TARGET_ABICALLS forces us to 5073;; use $25 for this purpose -- and $25 is never clobbered by the 5074;; epilogue -- we might as well use it for !TARGET_ABICALLS as well. 5075 5076(define_expand "sibcall" 5077 [(parallel [(call (match_operand 0 "") 5078 (match_operand 1 "")) 5079 (use (match_operand 2 "")) ;; next_arg_reg 5080 (use (match_operand 3 ""))])] ;; struct_value_size_rtx 5081 "TARGET_SIBCALLS" 5082{ 5083 mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], true); 5084 DONE; 5085}) 5086 5087(define_insn "sibcall_internal" 5088 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S")) 5089 (match_operand 1 "" ""))] 5090 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" 5091 { return MIPS_CALL ("j", operands, 0); } 5092 [(set_attr "type" "call")]) 5093 5094(define_expand "sibcall_value" 5095 [(parallel [(set (match_operand 0 "") 5096 (call (match_operand 1 "") 5097 (match_operand 2 ""))) 5098 (use (match_operand 3 ""))])] ;; next_arg_reg 5099 "TARGET_SIBCALLS" 5100{ 5101 mips_expand_call (operands[0], XEXP (operands[1], 0), 5102 operands[2], operands[3], true); 5103 DONE; 5104}) 5105 5106(define_insn "sibcall_value_internal" 5107 [(set (match_operand 0 "register_operand" "=df,df") 5108 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) 5109 (match_operand 2 "" "")))] 5110 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" 5111 { return MIPS_CALL ("j", operands, 1); } 5112 [(set_attr "type" "call")]) 5113 5114(define_insn "sibcall_value_multiple_internal" 5115 [(set (match_operand 0 "register_operand" "=df,df") 5116 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) 5117 (match_operand 2 "" ""))) 5118 (set (match_operand 3 "register_operand" "=df,df") 5119 (call (mem:SI (match_dup 1)) 5120 (match_dup 2)))] 5121 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" 5122 { return MIPS_CALL ("j", operands, 1); } 5123 [(set_attr "type" "call")]) 5124 5125(define_expand "call" 5126 [(parallel [(call (match_operand 0 "") 5127 (match_operand 1 "")) 5128 (use (match_operand 2 "")) ;; next_arg_reg 5129 (use (match_operand 3 ""))])] ;; struct_value_size_rtx 5130 "" 5131{ 5132 mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], false); 5133 DONE; 5134}) 5135 5136;; This instruction directly corresponds to an assembly-language "jal". 5137;; There are four cases: 5138;; 5139;; - -mno-abicalls: 5140;; Both symbolic and register destinations are OK. The pattern 5141;; always expands to a single mips instruction. 5142;; 5143;; - -mabicalls/-mno-explicit-relocs: 5144;; Again, both symbolic and register destinations are OK. 5145;; The call is treated as a multi-instruction black box. 5146;; 5147;; - -mabicalls/-mexplicit-relocs with n32 or n64: 5148;; Only "jal $25" is allowed. This expands to a single "jalr $25" 5149;; instruction. 5150;; 5151;; - -mabicalls/-mexplicit-relocs with o32 or o64: 5152;; Only "jal $25" is allowed. The call is actually two instructions: 5153;; "jalr $25" followed by an insn to reload $gp. 5154;; 5155;; In the last case, we can generate the individual instructions with 5156;; a define_split. There are several things to be wary of: 5157;; 5158;; - We can't expose the load of $gp before reload. If we did, 5159;; it might get removed as dead, but reload can introduce new 5160;; uses of $gp by rematerializing constants. 5161;; 5162;; - We shouldn't restore $gp after calls that never return. 5163;; It isn't valid to insert instructions between a noreturn 5164;; call and the following barrier. 5165;; 5166;; - The splitter deliberately changes the liveness of $gp. The unsplit 5167;; instruction preserves $gp and so have no effect on its liveness. 5168;; But once we generate the separate insns, it becomes obvious that 5169;; $gp is not live on entry to the call. 5170;; 5171;; ??? The operands[2] = insn check is a hack to make the original insn 5172;; available to the splitter. 5173(define_insn_and_split "call_internal" 5174 [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S")) 5175 (match_operand 1 "" "")) 5176 (clobber (reg:SI 31))] 5177 "" 5178 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); } 5179 "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)" 5180 [(const_int 0)] 5181{ 5182 emit_call_insn (gen_call_split (operands[0], operands[1])); 5183 if (!find_reg_note (operands[2], REG_NORETURN, 0)) 5184 mips_restore_gp (); 5185 DONE; 5186} 5187 [(set_attr "jal" "indirect,direct") 5188 (set_attr "extended_mips16" "no,yes")]) 5189 5190(define_insn "call_split" 5191 [(call (mem:SI (match_operand 0 "call_insn_operand" "cS")) 5192 (match_operand 1 "" "")) 5193 (clobber (reg:SI 31)) 5194 (clobber (reg:SI 28))] 5195 "TARGET_SPLIT_CALLS" 5196 { return MIPS_CALL ("jal", operands, 0); } 5197 [(set_attr "type" "call")]) 5198 5199(define_expand "call_value" 5200 [(parallel [(set (match_operand 0 "") 5201 (call (match_operand 1 "") 5202 (match_operand 2 ""))) 5203 (use (match_operand 3 ""))])] ;; next_arg_reg 5204 "" 5205{ 5206 mips_expand_call (operands[0], XEXP (operands[1], 0), 5207 operands[2], operands[3], false); 5208 DONE; 5209}) 5210 5211;; See comment for call_internal. 5212(define_insn_and_split "call_value_internal" 5213 [(set (match_operand 0 "register_operand" "=df,df") 5214 (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) 5215 (match_operand 2 "" ""))) 5216 (clobber (reg:SI 31))] 5217 "" 5218 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } 5219 "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)" 5220 [(const_int 0)] 5221{ 5222 emit_call_insn (gen_call_value_split (operands[0], operands[1], 5223 operands[2])); 5224 if (!find_reg_note (operands[3], REG_NORETURN, 0)) 5225 mips_restore_gp (); 5226 DONE; 5227} 5228 [(set_attr "jal" "indirect,direct") 5229 (set_attr "extended_mips16" "no,yes")]) 5230 5231(define_insn "call_value_split" 5232 [(set (match_operand 0 "register_operand" "=df") 5233 (call (mem:SI (match_operand 1 "call_insn_operand" "cS")) 5234 (match_operand 2 "" ""))) 5235 (clobber (reg:SI 31)) 5236 (clobber (reg:SI 28))] 5237 "TARGET_SPLIT_CALLS" 5238 { return MIPS_CALL ("jal", operands, 1); } 5239 [(set_attr "type" "call")]) 5240 5241;; See comment for call_internal. 5242(define_insn_and_split "call_value_multiple_internal" 5243 [(set (match_operand 0 "register_operand" "=df,df") 5244 (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) 5245 (match_operand 2 "" ""))) 5246 (set (match_operand 3 "register_operand" "=df,df") 5247 (call (mem:SI (match_dup 1)) 5248 (match_dup 2))) 5249 (clobber (reg:SI 31))] 5250 "" 5251 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } 5252 "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)" 5253 [(const_int 0)] 5254{ 5255 emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1], 5256 operands[2], operands[3])); 5257 if (!find_reg_note (operands[4], REG_NORETURN, 0)) 5258 mips_restore_gp (); 5259 DONE; 5260} 5261 [(set_attr "jal" "indirect,direct") 5262 (set_attr "extended_mips16" "no,yes")]) 5263 5264(define_insn "call_value_multiple_split" 5265 [(set (match_operand 0 "register_operand" "=df") 5266 (call (mem:SI (match_operand 1 "call_insn_operand" "cS")) 5267 (match_operand 2 "" ""))) 5268 (set (match_operand 3 "register_operand" "=df") 5269 (call (mem:SI (match_dup 1)) 5270 (match_dup 2))) 5271 (clobber (reg:SI 31)) 5272 (clobber (reg:SI 28))] 5273 "TARGET_SPLIT_CALLS" 5274 { return MIPS_CALL ("jal", operands, 1); } 5275 [(set_attr "type" "call")]) 5276 5277;; Call subroutine returning any type. 5278 5279(define_expand "untyped_call" 5280 [(parallel [(call (match_operand 0 "") 5281 (const_int 0)) 5282 (match_operand 1 "") 5283 (match_operand 2 "")])] 5284 "" 5285{ 5286 int i; 5287 5288 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 5289 5290 for (i = 0; i < XVECLEN (operands[2], 0); i++) 5291 { 5292 rtx set = XVECEXP (operands[2], 0, i); 5293 emit_move_insn (SET_DEST (set), SET_SRC (set)); 5294 } 5295 5296 emit_insn (gen_blockage ()); 5297 DONE; 5298}) 5299 5300;; 5301;; .................... 5302;; 5303;; MISC. 5304;; 5305;; .................... 5306;; 5307 5308 5309(define_insn "prefetch" 5310 [(prefetch (match_operand:QI 0 "address_operand" "p") 5311 (match_operand 1 "const_int_operand" "n") 5312 (match_operand 2 "const_int_operand" "n"))] 5313 "ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS" 5314{ 5315 operands[1] = mips_prefetch_cookie (operands[1], operands[2]); 5316 return "pref\t%1,%a0"; 5317} 5318 [(set_attr "type" "prefetch")]) 5319 5320(define_insn "*prefetch_indexed_<mode>" 5321 [(prefetch (plus:P (match_operand:P 0 "register_operand" "d") 5322 (match_operand:P 1 "register_operand" "d")) 5323 (match_operand 2 "const_int_operand" "n") 5324 (match_operand 3 "const_int_operand" "n"))] 5325 "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 5326{ 5327 operands[2] = mips_prefetch_cookie (operands[2], operands[3]); 5328 return "prefx\t%2,%1(%0)"; 5329} 5330 [(set_attr "type" "prefetchx")]) 5331 5332(define_insn "nop" 5333 [(const_int 0)] 5334 "" 5335 "%(nop%)" 5336 [(set_attr "type" "nop") 5337 (set_attr "mode" "none")]) 5338 5339;; Like nop, but commented out when outside a .set noreorder block. 5340(define_insn "hazard_nop" 5341 [(const_int 1)] 5342 "" 5343 { 5344 if (set_noreorder) 5345 return "nop"; 5346 else 5347 return "#nop"; 5348 } 5349 [(set_attr "type" "nop")]) 5350 5351;; MIPS4 Conditional move instructions. 5352 5353(define_insn "*mov<GPR:mode>_on_<MOVECC:mode>" 5354 [(set (match_operand:GPR 0 "register_operand" "=d,d") 5355 (if_then_else:GPR 5356 (match_operator:MOVECC 4 "equality_operator" 5357 [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>") 5358 (const_int 0)]) 5359 (match_operand:GPR 2 "reg_or_0_operand" "dJ,0") 5360 (match_operand:GPR 3 "reg_or_0_operand" "0,dJ")))] 5361 "ISA_HAS_CONDMOVE" 5362 "@ 5363 mov%T4\t%0,%z2,%1 5364 mov%t4\t%0,%z3,%1" 5365 [(set_attr "type" "condmove") 5366 (set_attr "mode" "<GPR:MODE>")]) 5367 5368(define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>" 5369 [(set (match_operand:SCALARF 0 "register_operand" "=f,f") 5370 (if_then_else:SCALARF 5371 (match_operator:MOVECC 4 "equality_operator" 5372 [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>") 5373 (const_int 0)]) 5374 (match_operand:SCALARF 2 "register_operand" "f,0") 5375 (match_operand:SCALARF 3 "register_operand" "0,f")))] 5376 "ISA_HAS_CONDMOVE" 5377 "@ 5378 mov%T4.<fmt>\t%0,%2,%1 5379 mov%t4.<fmt>\t%0,%3,%1" 5380 [(set_attr "type" "condmove") 5381 (set_attr "mode" "<SCALARF:MODE>")]) 5382 5383;; These are the main define_expand's used to make conditional moves. 5384 5385(define_expand "mov<mode>cc" 5386 [(set (match_dup 4) (match_operand 1 "comparison_operator")) 5387 (set (match_operand:GPR 0 "register_operand") 5388 (if_then_else:GPR (match_dup 5) 5389 (match_operand:GPR 2 "reg_or_0_operand") 5390 (match_operand:GPR 3 "reg_or_0_operand")))] 5391 "ISA_HAS_CONDMOVE" 5392{ 5393 gen_conditional_move (operands); 5394 DONE; 5395}) 5396 5397(define_expand "mov<mode>cc" 5398 [(set (match_dup 4) (match_operand 1 "comparison_operator")) 5399 (set (match_operand:SCALARF 0 "register_operand") 5400 (if_then_else:SCALARF (match_dup 5) 5401 (match_operand:SCALARF 2 "register_operand") 5402 (match_operand:SCALARF 3 "register_operand")))] 5403 "ISA_HAS_CONDMOVE" 5404{ 5405 gen_conditional_move (operands); 5406 DONE; 5407}) 5408 5409;; 5410;; .................... 5411;; 5412;; mips16 inline constant tables 5413;; 5414;; .................... 5415;; 5416 5417(define_insn "consttable_int" 5418 [(unspec_volatile [(match_operand 0 "consttable_operand" "") 5419 (match_operand 1 "const_int_operand" "")] 5420 UNSPEC_CONSTTABLE_INT)] 5421 "TARGET_MIPS16" 5422{ 5423 assemble_integer (operands[0], INTVAL (operands[1]), 5424 BITS_PER_UNIT * INTVAL (operands[1]), 1); 5425 return ""; 5426} 5427 [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))]) 5428 5429(define_insn "consttable_float" 5430 [(unspec_volatile [(match_operand 0 "consttable_operand" "")] 5431 UNSPEC_CONSTTABLE_FLOAT)] 5432 "TARGET_MIPS16" 5433{ 5434 REAL_VALUE_TYPE d; 5435 5436 gcc_assert (GET_CODE (operands[0]) == CONST_DOUBLE); 5437 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); 5438 assemble_real (d, GET_MODE (operands[0]), 5439 GET_MODE_BITSIZE (GET_MODE (operands[0]))); 5440 return ""; 5441} 5442 [(set (attr "length") 5443 (symbol_ref "GET_MODE_SIZE (GET_MODE (operands[0]))"))]) 5444 5445(define_insn "align" 5446 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPEC_ALIGN)] 5447 "" 5448 ".align\t%0" 5449 [(set (attr "length") (symbol_ref "(1 << INTVAL (operands[0])) - 1"))]) 5450 5451(define_split 5452 [(match_operand 0 "small_data_pattern")] 5453 "reload_completed" 5454 [(match_dup 0)] 5455 { operands[0] = mips_rewrite_small_data (operands[0]); }) 5456 5457; Thread-Local Storage 5458 5459; The TLS base pointer is accessed via "rdhwr $v1, $29". No current 5460; MIPS architecture defines this register, and no current 5461; implementation provides it; instead, any OS which supports TLS is 5462; expected to trap and emulate this instruction. rdhwr is part of the 5463; MIPS 32r2 specification, but we use it on any architecture because 5464; we expect it to be emulated. Use .set to force the assembler to 5465; accept it. 5466 5467(define_insn "tls_get_tp_<mode>" 5468 [(set (match_operand:P 0 "register_operand" "=v") 5469 (unspec:P [(const_int 0)] 5470 UNSPEC_TLS_GET_TP))] 5471 "HAVE_AS_TLS && !TARGET_MIPS16" 5472 ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop" 5473 [(set_attr "type" "unknown") 5474 ; Since rdhwr always generates a trap for now, putting it in a delay 5475 ; slot would make the kernel's emulation of it much slower. 5476 (set_attr "can_delay" "no") 5477 (set_attr "mode" "<MODE>")]) 5478 5479; The MIPS Paired-Single Floating Point and MIPS-3D Instructions. 5480 5481(include "mips-ps-3d.md") 5482 5483; The MIPS DSP Instructions. 5484 5485(include "mips-dsp.md")
| 1046 return "mul\t%0,%1,%2"; 1047 return "mult\t%0,%1,%2"; 1048} 1049 [(set_attr "type" "imul3,imul") 1050 (set_attr "mode" "SI")]) 1051 1052(define_insn "muldi3_mult3" 1053 [(set (match_operand:DI 0 "register_operand" "=d") 1054 (mult:DI (match_operand:DI 1 "register_operand" "d") 1055 (match_operand:DI 2 "register_operand" "d"))) 1056 (clobber (match_scratch:DI 3 "=h")) 1057 (clobber (match_scratch:DI 4 "=l"))] 1058 "TARGET_64BIT && GENERATE_MULT3_DI" 1059 "dmult\t%0,%1,%2" 1060 [(set_attr "type" "imul3") 1061 (set_attr "mode" "DI")]) 1062 1063;; If a register gets allocated to LO, and we spill to memory, the reload 1064;; will include a move from LO to a GPR. Merge it into the multiplication 1065;; if it can set the GPR directly. 1066;; 1067;; Operand 0: LO 1068;; Operand 1: GPR (1st multiplication operand) 1069;; Operand 2: GPR (2nd multiplication operand) 1070;; Operand 3: HI 1071;; Operand 4: GPR (destination) 1072(define_peephole2 1073 [(parallel 1074 [(set (match_operand:SI 0 "register_operand") 1075 (mult:SI (match_operand:SI 1 "register_operand") 1076 (match_operand:SI 2 "register_operand"))) 1077 (clobber (match_operand:SI 3 "register_operand")) 1078 (clobber (scratch:SI))]) 1079 (set (match_operand:SI 4 "register_operand") 1080 (unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] 1081 "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])" 1082 [(parallel 1083 [(set (match_dup 4) 1084 (mult:SI (match_dup 1) 1085 (match_dup 2))) 1086 (clobber (match_dup 3)) 1087 (clobber (match_dup 0))])]) 1088 1089(define_insn "mul<mode>3_internal" 1090 [(set (match_operand:GPR 0 "register_operand" "=l") 1091 (mult:GPR (match_operand:GPR 1 "register_operand" "d") 1092 (match_operand:GPR 2 "register_operand" "d"))) 1093 (clobber (match_scratch:GPR 3 "=h"))] 1094 "!TARGET_FIX_R4000" 1095 "<d>mult\t%1,%2" 1096 [(set_attr "type" "imul") 1097 (set_attr "mode" "<MODE>")]) 1098 1099(define_insn "mul<mode>3_r4000" 1100 [(set (match_operand:GPR 0 "register_operand" "=d") 1101 (mult:GPR (match_operand:GPR 1 "register_operand" "d") 1102 (match_operand:GPR 2 "register_operand" "d"))) 1103 (clobber (match_scratch:GPR 3 "=h")) 1104 (clobber (match_scratch:GPR 4 "=l"))] 1105 "TARGET_FIX_R4000" 1106 "<d>mult\t%1,%2\;mflo\t%0" 1107 [(set_attr "type" "imul") 1108 (set_attr "mode" "<MODE>") 1109 (set_attr "length" "8")]) 1110 1111;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead 1112;; of "mult; mflo". They have the same latency, but the first form gives 1113;; us an extra cycle to compute the operands. 1114 1115;; Operand 0: LO 1116;; Operand 1: GPR (1st multiplication operand) 1117;; Operand 2: GPR (2nd multiplication operand) 1118;; Operand 3: HI 1119;; Operand 4: GPR (destination) 1120(define_peephole2 1121 [(parallel 1122 [(set (match_operand:SI 0 "register_operand") 1123 (mult:SI (match_operand:SI 1 "register_operand") 1124 (match_operand:SI 2 "register_operand"))) 1125 (clobber (match_operand:SI 3 "register_operand"))]) 1126 (set (match_operand:SI 4 "register_operand") 1127 (unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] 1128 "ISA_HAS_MACC && !GENERATE_MULT3_SI" 1129 [(set (match_dup 0) 1130 (const_int 0)) 1131 (parallel 1132 [(set (match_dup 0) 1133 (plus:SI (mult:SI (match_dup 1) 1134 (match_dup 2)) 1135 (match_dup 0))) 1136 (set (match_dup 4) 1137 (plus:SI (mult:SI (match_dup 1) 1138 (match_dup 2)) 1139 (match_dup 0))) 1140 (clobber (match_dup 3))])]) 1141 1142;; Multiply-accumulate patterns 1143 1144;; For processors that can copy the output to a general register: 1145;; 1146;; The all-d alternative is needed because the combiner will find this 1147;; pattern and then register alloc/reload will move registers around to 1148;; make them fit, and we don't want to trigger unnecessary loads to LO. 1149;; 1150;; The last alternative should be made slightly less desirable, but adding 1151;; "?" to the constraint is too strong, and causes values to be loaded into 1152;; LO even when that's more costly. For now, using "*d" mostly does the 1153;; trick. 1154(define_insn "*mul_acc_si" 1155 [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") 1156 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") 1157 (match_operand:SI 2 "register_operand" "d,d,d")) 1158 (match_operand:SI 3 "register_operand" "0,l,*d"))) 1159 (clobber (match_scratch:SI 4 "=h,h,h")) 1160 (clobber (match_scratch:SI 5 "=X,3,l")) 1161 (clobber (match_scratch:SI 6 "=X,X,&d"))] 1162 "(TARGET_MIPS3900 1163 || ISA_HAS_MADD_MSUB) 1164 && !TARGET_MIPS16" 1165{ 1166 static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" }; 1167 if (which_alternative == 2) 1168 return "#"; 1169 if (ISA_HAS_MADD_MSUB && which_alternative != 0) 1170 return "#"; 1171 return madd[which_alternative]; 1172} 1173 [(set_attr "type" "imadd,imadd,multi") 1174 (set_attr "mode" "SI") 1175 (set_attr "length" "4,4,8")]) 1176 1177;; Split the above insn if we failed to get LO allocated. 1178(define_split 1179 [(set (match_operand:SI 0 "register_operand") 1180 (plus:SI (mult:SI (match_operand:SI 1 "register_operand") 1181 (match_operand:SI 2 "register_operand")) 1182 (match_operand:SI 3 "register_operand"))) 1183 (clobber (match_scratch:SI 4)) 1184 (clobber (match_scratch:SI 5)) 1185 (clobber (match_scratch:SI 6))] 1186 "reload_completed && !TARGET_DEBUG_D_MODE 1187 && GP_REG_P (true_regnum (operands[0])) 1188 && GP_REG_P (true_regnum (operands[3]))" 1189 [(parallel [(set (match_dup 6) 1190 (mult:SI (match_dup 1) (match_dup 2))) 1191 (clobber (match_dup 4)) 1192 (clobber (match_dup 5))]) 1193 (set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))] 1194 "") 1195 1196;; Splitter to copy result of MADD to a general register 1197(define_split 1198 [(set (match_operand:SI 0 "register_operand") 1199 (plus:SI (mult:SI (match_operand:SI 1 "register_operand") 1200 (match_operand:SI 2 "register_operand")) 1201 (match_operand:SI 3 "register_operand"))) 1202 (clobber (match_scratch:SI 4)) 1203 (clobber (match_scratch:SI 5)) 1204 (clobber (match_scratch:SI 6))] 1205 "reload_completed && !TARGET_DEBUG_D_MODE 1206 && GP_REG_P (true_regnum (operands[0])) 1207 && true_regnum (operands[3]) == LO_REGNUM" 1208 [(parallel [(set (match_dup 3) 1209 (plus:SI (mult:SI (match_dup 1) (match_dup 2)) 1210 (match_dup 3))) 1211 (clobber (match_dup 4)) 1212 (clobber (match_dup 5)) 1213 (clobber (match_dup 6))]) 1214 (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] 1215 "") 1216 1217(define_insn "*macc" 1218 [(set (match_operand:SI 0 "register_operand" "=l,d") 1219 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") 1220 (match_operand:SI 2 "register_operand" "d,d")) 1221 (match_operand:SI 3 "register_operand" "0,l"))) 1222 (clobber (match_scratch:SI 4 "=h,h")) 1223 (clobber (match_scratch:SI 5 "=X,3"))] 1224 "ISA_HAS_MACC" 1225{ 1226 if (which_alternative == 1) 1227 return "macc\t%0,%1,%2"; 1228 else if (TARGET_MIPS5500) 1229 return "madd\t%1,%2"; 1230 else 1231 /* The VR4130 assumes that there is a two-cycle latency between a macc 1232 that "writes" to $0 and an instruction that reads from it. We avoid 1233 this by assigning to $1 instead. */ 1234 return "%[macc\t%@,%1,%2%]"; 1235} 1236 [(set_attr "type" "imadd") 1237 (set_attr "mode" "SI")]) 1238 1239(define_insn "*msac" 1240 [(set (match_operand:SI 0 "register_operand" "=l,d") 1241 (minus:SI (match_operand:SI 1 "register_operand" "0,l") 1242 (mult:SI (match_operand:SI 2 "register_operand" "d,d") 1243 (match_operand:SI 3 "register_operand" "d,d")))) 1244 (clobber (match_scratch:SI 4 "=h,h")) 1245 (clobber (match_scratch:SI 5 "=X,1"))] 1246 "ISA_HAS_MSAC" 1247{ 1248 if (which_alternative == 1) 1249 return "msac\t%0,%2,%3"; 1250 else if (TARGET_MIPS5500) 1251 return "msub\t%2,%3"; 1252 else 1253 return "msac\t$0,%2,%3"; 1254} 1255 [(set_attr "type" "imadd") 1256 (set_attr "mode" "SI")]) 1257 1258;; An msac-like instruction implemented using negation and a macc. 1259(define_insn_and_split "*msac_using_macc" 1260 [(set (match_operand:SI 0 "register_operand" "=l,d") 1261 (minus:SI (match_operand:SI 1 "register_operand" "0,l") 1262 (mult:SI (match_operand:SI 2 "register_operand" "d,d") 1263 (match_operand:SI 3 "register_operand" "d,d")))) 1264 (clobber (match_scratch:SI 4 "=h,h")) 1265 (clobber (match_scratch:SI 5 "=X,1")) 1266 (clobber (match_scratch:SI 6 "=d,d"))] 1267 "ISA_HAS_MACC && !ISA_HAS_MSAC" 1268 "#" 1269 "&& reload_completed" 1270 [(set (match_dup 6) 1271 (neg:SI (match_dup 3))) 1272 (parallel 1273 [(set (match_dup 0) 1274 (plus:SI (mult:SI (match_dup 2) 1275 (match_dup 6)) 1276 (match_dup 1))) 1277 (clobber (match_dup 4)) 1278 (clobber (match_dup 5))])] 1279 "" 1280 [(set_attr "type" "imadd") 1281 (set_attr "length" "8")]) 1282 1283;; Patterns generated by the define_peephole2 below. 1284 1285(define_insn "*macc2" 1286 [(set (match_operand:SI 0 "register_operand" "=l") 1287 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") 1288 (match_operand:SI 2 "register_operand" "d")) 1289 (match_dup 0))) 1290 (set (match_operand:SI 3 "register_operand" "=d") 1291 (plus:SI (mult:SI (match_dup 1) 1292 (match_dup 2)) 1293 (match_dup 0))) 1294 (clobber (match_scratch:SI 4 "=h"))] 1295 "ISA_HAS_MACC && reload_completed" 1296 "macc\t%3,%1,%2" 1297 [(set_attr "type" "imadd") 1298 (set_attr "mode" "SI")]) 1299 1300(define_insn "*msac2" 1301 [(set (match_operand:SI 0 "register_operand" "=l") 1302 (minus:SI (match_dup 0) 1303 (mult:SI (match_operand:SI 1 "register_operand" "d") 1304 (match_operand:SI 2 "register_operand" "d")))) 1305 (set (match_operand:SI 3 "register_operand" "=d") 1306 (minus:SI (match_dup 0) 1307 (mult:SI (match_dup 1) 1308 (match_dup 2)))) 1309 (clobber (match_scratch:SI 4 "=h"))] 1310 "ISA_HAS_MSAC && reload_completed" 1311 "msac\t%3,%1,%2" 1312 [(set_attr "type" "imadd") 1313 (set_attr "mode" "SI")]) 1314 1315;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2> 1316;; Similarly msac. 1317;; 1318;; Operand 0: LO 1319;; Operand 1: macc/msac 1320;; Operand 2: HI 1321;; Operand 3: GPR (destination) 1322(define_peephole2 1323 [(parallel 1324 [(set (match_operand:SI 0 "register_operand") 1325 (match_operand:SI 1 "macc_msac_operand")) 1326 (clobber (match_operand:SI 2 "register_operand")) 1327 (clobber (scratch:SI))]) 1328 (set (match_operand:SI 3 "register_operand") 1329 (unspec:SI [(match_dup 0) (match_dup 2)] UNSPEC_MFHILO))] 1330 "" 1331 [(parallel [(set (match_dup 0) 1332 (match_dup 1)) 1333 (set (match_dup 3) 1334 (match_dup 1)) 1335 (clobber (match_dup 2))])] 1336 "") 1337 1338;; When we have a three-address multiplication instruction, it should 1339;; be faster to do a separate multiply and add, rather than moving 1340;; something into LO in order to use a macc instruction. 1341;; 1342;; This peephole needs a scratch register to cater for the case when one 1343;; of the multiplication operands is the same as the destination. 1344;; 1345;; Operand 0: GPR (scratch) 1346;; Operand 1: LO 1347;; Operand 2: GPR (addend) 1348;; Operand 3: GPR (destination) 1349;; Operand 4: macc/msac 1350;; Operand 5: HI 1351;; Operand 6: new multiplication 1352;; Operand 7: new addition/subtraction 1353(define_peephole2 1354 [(match_scratch:SI 0 "d") 1355 (set (match_operand:SI 1 "register_operand") 1356 (match_operand:SI 2 "register_operand")) 1357 (match_dup 0) 1358 (parallel 1359 [(set (match_operand:SI 3 "register_operand") 1360 (match_operand:SI 4 "macc_msac_operand")) 1361 (clobber (match_operand:SI 5 "register_operand")) 1362 (clobber (match_dup 1))])] 1363 "GENERATE_MULT3_SI 1364 && true_regnum (operands[1]) == LO_REGNUM 1365 && peep2_reg_dead_p (2, operands[1]) 1366 && GP_REG_P (true_regnum (operands[3]))" 1367 [(parallel [(set (match_dup 0) 1368 (match_dup 6)) 1369 (clobber (match_dup 5)) 1370 (clobber (match_dup 1))]) 1371 (set (match_dup 3) 1372 (match_dup 7))] 1373{ 1374 operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); 1375 operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, 1376 operands[2], operands[0]); 1377}) 1378 1379;; Same as above, except LO is the initial target of the macc. 1380;; 1381;; Operand 0: GPR (scratch) 1382;; Operand 1: LO 1383;; Operand 2: GPR (addend) 1384;; Operand 3: macc/msac 1385;; Operand 4: HI 1386;; Operand 5: GPR (destination) 1387;; Operand 6: new multiplication 1388;; Operand 7: new addition/subtraction 1389(define_peephole2 1390 [(match_scratch:SI 0 "d") 1391 (set (match_operand:SI 1 "register_operand") 1392 (match_operand:SI 2 "register_operand")) 1393 (match_dup 0) 1394 (parallel 1395 [(set (match_dup 1) 1396 (match_operand:SI 3 "macc_msac_operand")) 1397 (clobber (match_operand:SI 4 "register_operand")) 1398 (clobber (scratch:SI))]) 1399 (match_dup 0) 1400 (set (match_operand:SI 5 "register_operand") 1401 (unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))] 1402 "GENERATE_MULT3_SI && peep2_reg_dead_p (3, operands[1])" 1403 [(parallel [(set (match_dup 0) 1404 (match_dup 6)) 1405 (clobber (match_dup 4)) 1406 (clobber (match_dup 1))]) 1407 (set (match_dup 5) 1408 (match_dup 7))] 1409{ 1410 operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1); 1411 operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, 1412 operands[2], operands[0]); 1413}) 1414 1415(define_insn "*mul_sub_si" 1416 [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") 1417 (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d") 1418 (mult:SI (match_operand:SI 2 "register_operand" "d,d,d") 1419 (match_operand:SI 3 "register_operand" "d,d,d")))) 1420 (clobber (match_scratch:SI 4 "=h,h,h")) 1421 (clobber (match_scratch:SI 5 "=X,1,l")) 1422 (clobber (match_scratch:SI 6 "=X,X,&d"))] 1423 "ISA_HAS_MADD_MSUB" 1424 "@ 1425 msub\t%2,%3 1426 # 1427 #" 1428 [(set_attr "type" "imadd,multi,multi") 1429 (set_attr "mode" "SI") 1430 (set_attr "length" "4,8,8")]) 1431 1432;; Split the above insn if we failed to get LO allocated. 1433(define_split 1434 [(set (match_operand:SI 0 "register_operand") 1435 (minus:SI (match_operand:SI 1 "register_operand") 1436 (mult:SI (match_operand:SI 2 "register_operand") 1437 (match_operand:SI 3 "register_operand")))) 1438 (clobber (match_scratch:SI 4)) 1439 (clobber (match_scratch:SI 5)) 1440 (clobber (match_scratch:SI 6))] 1441 "reload_completed && !TARGET_DEBUG_D_MODE 1442 && GP_REG_P (true_regnum (operands[0])) 1443 && GP_REG_P (true_regnum (operands[1]))" 1444 [(parallel [(set (match_dup 6) 1445 (mult:SI (match_dup 2) (match_dup 3))) 1446 (clobber (match_dup 4)) 1447 (clobber (match_dup 5))]) 1448 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 6)))] 1449 "") 1450 1451;; Splitter to copy result of MSUB to a general register 1452(define_split 1453 [(set (match_operand:SI 0 "register_operand") 1454 (minus:SI (match_operand:SI 1 "register_operand") 1455 (mult:SI (match_operand:SI 2 "register_operand") 1456 (match_operand:SI 3 "register_operand")))) 1457 (clobber (match_scratch:SI 4)) 1458 (clobber (match_scratch:SI 5)) 1459 (clobber (match_scratch:SI 6))] 1460 "reload_completed && !TARGET_DEBUG_D_MODE 1461 && GP_REG_P (true_regnum (operands[0])) 1462 && true_regnum (operands[1]) == LO_REGNUM" 1463 [(parallel [(set (match_dup 1) 1464 (minus:SI (match_dup 1) 1465 (mult:SI (match_dup 2) (match_dup 3)))) 1466 (clobber (match_dup 4)) 1467 (clobber (match_dup 5)) 1468 (clobber (match_dup 6))]) 1469 (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] 1470 "") 1471 1472(define_insn "*muls" 1473 [(set (match_operand:SI 0 "register_operand" "=l,d") 1474 (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") 1475 (match_operand:SI 2 "register_operand" "d,d")))) 1476 (clobber (match_scratch:SI 3 "=h,h")) 1477 (clobber (match_scratch:SI 4 "=X,l"))] 1478 "ISA_HAS_MULS" 1479 "@ 1480 muls\t$0,%1,%2 1481 muls\t%0,%1,%2" 1482 [(set_attr "type" "imul,imul3") 1483 (set_attr "mode" "SI")]) 1484 1485;; ??? We could define a mulditi3 pattern when TARGET_64BIT. 1486 1487(define_expand "<u>mulsidi3" 1488 [(parallel 1489 [(set (match_operand:DI 0 "register_operand") 1490 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) 1491 (any_extend:DI (match_operand:SI 2 "register_operand")))) 1492 (clobber (scratch:DI)) 1493 (clobber (scratch:DI)) 1494 (clobber (scratch:DI))])] 1495 "!TARGET_64BIT || !TARGET_FIX_R4000" 1496{ 1497 if (!TARGET_64BIT) 1498 { 1499 if (!TARGET_FIX_R4000) 1500 emit_insn (gen_<u>mulsidi3_32bit_internal (operands[0], operands[1], 1501 operands[2])); 1502 else 1503 emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1], 1504 operands[2])); 1505 DONE; 1506 } 1507}) 1508 1509(define_insn "<u>mulsidi3_32bit_internal" 1510 [(set (match_operand:DI 0 "register_operand" "=x") 1511 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1512 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 1513 "!TARGET_64BIT && !TARGET_FIX_R4000" 1514 "mult<u>\t%1,%2" 1515 [(set_attr "type" "imul") 1516 (set_attr "mode" "SI")]) 1517 1518(define_insn "<u>mulsidi3_32bit_r4000" 1519 [(set (match_operand:DI 0 "register_operand" "=d") 1520 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1521 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) 1522 (clobber (match_scratch:DI 3 "=x"))] 1523 "!TARGET_64BIT && TARGET_FIX_R4000" 1524 "mult<u>\t%1,%2\;mflo\t%L0;mfhi\t%M0" 1525 [(set_attr "type" "imul") 1526 (set_attr "mode" "SI") 1527 (set_attr "length" "12")]) 1528 1529(define_insn_and_split "*<u>mulsidi3_64bit" 1530 [(set (match_operand:DI 0 "register_operand" "=d") 1531 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1532 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))) 1533 (clobber (match_scratch:DI 3 "=l")) 1534 (clobber (match_scratch:DI 4 "=h")) 1535 (clobber (match_scratch:DI 5 "=d"))] 1536 "TARGET_64BIT && !TARGET_FIX_R4000" 1537 "#" 1538 "&& reload_completed" 1539 [(parallel 1540 [(set (match_dup 3) 1541 (sign_extend:DI 1542 (mult:SI (match_dup 1) 1543 (match_dup 2)))) 1544 (set (match_dup 4) 1545 (ashiftrt:DI 1546 (mult:DI (any_extend:DI (match_dup 1)) 1547 (any_extend:DI (match_dup 2))) 1548 (const_int 32)))]) 1549 1550 ;; OP5 <- LO, OP0 <- HI 1551 (set (match_dup 5) (unspec:DI [(match_dup 3) (match_dup 4)] UNSPEC_MFHILO)) 1552 (set (match_dup 0) (unspec:DI [(match_dup 4) (match_dup 3)] UNSPEC_MFHILO)) 1553 1554 ;; Zero-extend OP5. 1555 (set (match_dup 5) 1556 (ashift:DI (match_dup 5) 1557 (const_int 32))) 1558 (set (match_dup 5) 1559 (lshiftrt:DI (match_dup 5) 1560 (const_int 32))) 1561 1562 ;; Shift OP0 into place. 1563 (set (match_dup 0) 1564 (ashift:DI (match_dup 0) 1565 (const_int 32))) 1566 1567 ;; OR the two halves together 1568 (set (match_dup 0) 1569 (ior:DI (match_dup 0) 1570 (match_dup 5)))] 1571 "" 1572 [(set_attr "type" "imul") 1573 (set_attr "mode" "SI") 1574 (set_attr "length" "24")]) 1575 1576(define_insn "*<u>mulsidi3_64bit_parts" 1577 [(set (match_operand:DI 0 "register_operand" "=l") 1578 (sign_extend:DI 1579 (mult:SI (match_operand:SI 2 "register_operand" "d") 1580 (match_operand:SI 3 "register_operand" "d")))) 1581 (set (match_operand:DI 1 "register_operand" "=h") 1582 (ashiftrt:DI 1583 (mult:DI (any_extend:DI (match_dup 2)) 1584 (any_extend:DI (match_dup 3))) 1585 (const_int 32)))] 1586 "TARGET_64BIT && !TARGET_FIX_R4000" 1587 "mult<u>\t%2,%3" 1588 [(set_attr "type" "imul") 1589 (set_attr "mode" "SI")]) 1590 1591;; Widening multiply with negation. 1592(define_insn "*muls<u>_di" 1593 [(set (match_operand:DI 0 "register_operand" "=x") 1594 (neg:DI 1595 (mult:DI 1596 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1597 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] 1598 "!TARGET_64BIT && ISA_HAS_MULS" 1599 "muls<u>\t$0,%1,%2" 1600 [(set_attr "type" "imul") 1601 (set_attr "mode" "SI")]) 1602 1603(define_insn "*msac<u>_di" 1604 [(set (match_operand:DI 0 "register_operand" "=x") 1605 (minus:DI 1606 (match_operand:DI 3 "register_operand" "0") 1607 (mult:DI 1608 (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1609 (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] 1610 "!TARGET_64BIT && ISA_HAS_MSAC" 1611{ 1612 if (TARGET_MIPS5500) 1613 return "msub<u>\t%1,%2"; 1614 else 1615 return "msac<u>\t$0,%1,%2"; 1616} 1617 [(set_attr "type" "imadd") 1618 (set_attr "mode" "SI")]) 1619 1620;; _highpart patterns 1621 1622(define_expand "<su>mulsi3_highpart" 1623 [(set (match_operand:SI 0 "register_operand") 1624 (truncate:SI 1625 (lshiftrt:DI 1626 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand")) 1627 (any_extend:DI (match_operand:SI 2 "register_operand"))) 1628 (const_int 32))))] 1629 "ISA_HAS_MULHI || !TARGET_FIX_R4000" 1630{ 1631 if (ISA_HAS_MULHI) 1632 emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0], 1633 operands[1], 1634 operands[2])); 1635 else 1636 emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1], 1637 operands[2])); 1638 DONE; 1639}) 1640 1641(define_insn "<su>mulsi3_highpart_internal" 1642 [(set (match_operand:SI 0 "register_operand" "=h") 1643 (truncate:SI 1644 (lshiftrt:DI 1645 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1646 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) 1647 (const_int 32)))) 1648 (clobber (match_scratch:SI 3 "=l"))] 1649 "!ISA_HAS_MULHI && !TARGET_FIX_R4000" 1650 "mult<u>\t%1,%2" 1651 [(set_attr "type" "imul") 1652 (set_attr "mode" "SI")]) 1653 1654(define_insn "<su>mulsi3_highpart_mulhi_internal" 1655 [(set (match_operand:SI 0 "register_operand" "=h,d") 1656 (truncate:SI 1657 (lshiftrt:DI 1658 (mult:DI 1659 (any_extend:DI (match_operand:SI 1 "register_operand" "d,d")) 1660 (any_extend:DI (match_operand:SI 2 "register_operand" "d,d"))) 1661 (const_int 32)))) 1662 (clobber (match_scratch:SI 3 "=l,l")) 1663 (clobber (match_scratch:SI 4 "=X,h"))] 1664 "ISA_HAS_MULHI" 1665 "@ 1666 mult<u>\t%1,%2 1667 mulhi<u>\t%0,%1,%2" 1668 [(set_attr "type" "imul,imul3") 1669 (set_attr "mode" "SI")]) 1670 1671(define_insn "*<su>mulsi3_highpart_neg_mulhi_internal" 1672 [(set (match_operand:SI 0 "register_operand" "=h,d") 1673 (truncate:SI 1674 (lshiftrt:DI 1675 (neg:DI 1676 (mult:DI 1677 (any_extend:DI (match_operand:SI 1 "register_operand" "d,d")) 1678 (any_extend:DI (match_operand:SI 2 "register_operand" "d,d")))) 1679 (const_int 32)))) 1680 (clobber (match_scratch:SI 3 "=l,l")) 1681 (clobber (match_scratch:SI 4 "=X,h"))] 1682 "ISA_HAS_MULHI" 1683 "@ 1684 mulshi<u>\t%.,%1,%2 1685 mulshi<u>\t%0,%1,%2" 1686 [(set_attr "type" "imul,imul3") 1687 (set_attr "mode" "SI")]) 1688 1689;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120 1690;; errata MD(0), which says that dmultu does not always produce the 1691;; correct result. 1692(define_insn "<su>muldi3_highpart" 1693 [(set (match_operand:DI 0 "register_operand" "=h") 1694 (truncate:DI 1695 (lshiftrt:TI 1696 (mult:TI 1697 (any_extend:TI (match_operand:DI 1 "register_operand" "d")) 1698 (any_extend:TI (match_operand:DI 2 "register_operand" "d"))) 1699 (const_int 64)))) 1700 (clobber (match_scratch:DI 3 "=l"))] 1701 "TARGET_64BIT && !TARGET_FIX_R4000 1702 && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)" 1703 "dmult<u>\t%1,%2" 1704 [(set_attr "type" "imul") 1705 (set_attr "mode" "DI")]) 1706 1707;; The R4650 supports a 32 bit multiply/ 64 bit accumulate 1708;; instruction. The HI/LO registers are used as a 64 bit accumulator. 1709 1710(define_insn "madsi" 1711 [(set (match_operand:SI 0 "register_operand" "+l") 1712 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") 1713 (match_operand:SI 2 "register_operand" "d")) 1714 (match_dup 0))) 1715 (clobber (match_scratch:SI 3 "=h"))] 1716 "TARGET_MAD" 1717 "mad\t%1,%2" 1718 [(set_attr "type" "imadd") 1719 (set_attr "mode" "SI")]) 1720 1721(define_insn "*<su>mul_acc_di" 1722 [(set (match_operand:DI 0 "register_operand" "=x") 1723 (plus:DI 1724 (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) 1725 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) 1726 (match_operand:DI 3 "register_operand" "0")))] 1727 "(TARGET_MAD || ISA_HAS_MACC) 1728 && !TARGET_64BIT" 1729{ 1730 if (TARGET_MAD) 1731 return "mad<u>\t%1,%2"; 1732 else if (TARGET_MIPS5500) 1733 return "madd<u>\t%1,%2"; 1734 else 1735 /* See comment in *macc. */ 1736 return "%[macc<u>\t%@,%1,%2%]"; 1737} 1738 [(set_attr "type" "imadd") 1739 (set_attr "mode" "SI")]) 1740 1741;; Floating point multiply accumulate instructions. 1742 1743(define_insn "*madd<mode>" 1744 [(set (match_operand:ANYF 0 "register_operand" "=f") 1745 (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 1746 (match_operand:ANYF 2 "register_operand" "f")) 1747 (match_operand:ANYF 3 "register_operand" "f")))] 1748 "ISA_HAS_FP4 && TARGET_FUSED_MADD" 1749 "madd.<fmt>\t%0,%3,%1,%2" 1750 [(set_attr "type" "fmadd") 1751 (set_attr "mode" "<UNITMODE>")]) 1752 1753(define_insn "*msub<mode>" 1754 [(set (match_operand:ANYF 0 "register_operand" "=f") 1755 (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 1756 (match_operand:ANYF 2 "register_operand" "f")) 1757 (match_operand:ANYF 3 "register_operand" "f")))] 1758 "ISA_HAS_FP4 && TARGET_FUSED_MADD" 1759 "msub.<fmt>\t%0,%3,%1,%2" 1760 [(set_attr "type" "fmadd") 1761 (set_attr "mode" "<UNITMODE>")]) 1762 1763(define_insn "*nmadd<mode>" 1764 [(set (match_operand:ANYF 0 "register_operand" "=f") 1765 (neg:ANYF (plus:ANYF 1766 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 1767 (match_operand:ANYF 2 "register_operand" "f")) 1768 (match_operand:ANYF 3 "register_operand" "f"))))] 1769 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1770 && HONOR_SIGNED_ZEROS (<MODE>mode) 1771 && !HONOR_NANS (<MODE>mode)" 1772 "nmadd.<fmt>\t%0,%3,%1,%2" 1773 [(set_attr "type" "fmadd") 1774 (set_attr "mode" "<UNITMODE>")]) 1775 1776(define_insn "*nmadd<mode>_fastmath" 1777 [(set (match_operand:ANYF 0 "register_operand" "=f") 1778 (minus:ANYF 1779 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 1780 (match_operand:ANYF 2 "register_operand" "f")) 1781 (match_operand:ANYF 3 "register_operand" "f")))] 1782 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1783 && !HONOR_SIGNED_ZEROS (<MODE>mode) 1784 && !HONOR_NANS (<MODE>mode)" 1785 "nmadd.<fmt>\t%0,%3,%1,%2" 1786 [(set_attr "type" "fmadd") 1787 (set_attr "mode" "<UNITMODE>")]) 1788 1789(define_insn "*nmsub<mode>" 1790 [(set (match_operand:ANYF 0 "register_operand" "=f") 1791 (neg:ANYF (minus:ANYF 1792 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") 1793 (match_operand:ANYF 3 "register_operand" "f")) 1794 (match_operand:ANYF 1 "register_operand" "f"))))] 1795 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1796 && HONOR_SIGNED_ZEROS (<MODE>mode) 1797 && !HONOR_NANS (<MODE>mode)" 1798 "nmsub.<fmt>\t%0,%1,%2,%3" 1799 [(set_attr "type" "fmadd") 1800 (set_attr "mode" "<UNITMODE>")]) 1801 1802(define_insn "*nmsub<mode>_fastmath" 1803 [(set (match_operand:ANYF 0 "register_operand" "=f") 1804 (minus:ANYF 1805 (match_operand:ANYF 1 "register_operand" "f") 1806 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") 1807 (match_operand:ANYF 3 "register_operand" "f"))))] 1808 "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD 1809 && !HONOR_SIGNED_ZEROS (<MODE>mode) 1810 && !HONOR_NANS (<MODE>mode)" 1811 "nmsub.<fmt>\t%0,%1,%2,%3" 1812 [(set_attr "type" "fmadd") 1813 (set_attr "mode" "<UNITMODE>")]) 1814 1815;; 1816;; .................... 1817;; 1818;; DIVISION and REMAINDER 1819;; 1820;; .................... 1821;; 1822 1823(define_expand "div<mode>3" 1824 [(set (match_operand:ANYF 0 "register_operand") 1825 (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand") 1826 (match_operand:ANYF 2 "register_operand")))] 1827 "<divide_condition>" 1828{ 1829 if (const_1_operand (operands[1], <MODE>mode)) 1830 if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations)) 1831 operands[1] = force_reg (<MODE>mode, operands[1]); 1832}) 1833 1834;; These patterns work around the early SB-1 rev2 core "F1" erratum: 1835;; 1836;; If an mfc1 or dmfc1 happens to access the floating point register 1837;; file at the same time a long latency operation (div, sqrt, recip, 1838;; sqrt) iterates an intermediate result back through the floating 1839;; point register file bypass, then instead returning the correct 1840;; register value the mfc1 or dmfc1 operation returns the intermediate 1841;; result of the long latency operation. 1842;; 1843;; The workaround is to insert an unconditional 'mov' from/to the 1844;; long latency op destination register. 1845 1846(define_insn "*div<mode>3" 1847 [(set (match_operand:ANYF 0 "register_operand" "=f") 1848 (div:ANYF (match_operand:ANYF 1 "register_operand" "f") 1849 (match_operand:ANYF 2 "register_operand" "f")))] 1850 "<divide_condition>" 1851{ 1852 if (TARGET_FIX_SB1) 1853 return "div.<fmt>\t%0,%1,%2\;mov.<fmt>\t%0,%0"; 1854 else 1855 return "div.<fmt>\t%0,%1,%2"; 1856} 1857 [(set_attr "type" "fdiv") 1858 (set_attr "mode" "<UNITMODE>") 1859 (set (attr "length") 1860 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1861 (const_int 8) 1862 (const_int 4)))]) 1863 1864(define_insn "*recip<mode>3" 1865 [(set (match_operand:ANYF 0 "register_operand" "=f") 1866 (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") 1867 (match_operand:ANYF 2 "register_operand" "f")))] 1868 "<recip_condition> && flag_unsafe_math_optimizations" 1869{ 1870 if (TARGET_FIX_SB1) 1871 return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; 1872 else 1873 return "recip.<fmt>\t%0,%2"; 1874} 1875 [(set_attr "type" "frdiv") 1876 (set_attr "mode" "<UNITMODE>") 1877 (set (attr "length") 1878 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1879 (const_int 8) 1880 (const_int 4)))]) 1881 1882;; VR4120 errata MD(A1): signed division instructions do not work correctly 1883;; with negative operands. We use special libgcc functions instead. 1884(define_insn "divmod<mode>4" 1885 [(set (match_operand:GPR 0 "register_operand" "=l") 1886 (div:GPR (match_operand:GPR 1 "register_operand" "d") 1887 (match_operand:GPR 2 "register_operand" "d"))) 1888 (set (match_operand:GPR 3 "register_operand" "=h") 1889 (mod:GPR (match_dup 1) 1890 (match_dup 2)))] 1891 "!TARGET_FIX_VR4120" 1892 { return mips_output_division ("<d>div\t$0,%1,%2", operands); } 1893 [(set_attr "type" "idiv") 1894 (set_attr "mode" "<MODE>")]) 1895 1896(define_insn "udivmod<mode>4" 1897 [(set (match_operand:GPR 0 "register_operand" "=l") 1898 (udiv:GPR (match_operand:GPR 1 "register_operand" "d") 1899 (match_operand:GPR 2 "register_operand" "d"))) 1900 (set (match_operand:GPR 3 "register_operand" "=h") 1901 (umod:GPR (match_dup 1) 1902 (match_dup 2)))] 1903 "" 1904 { return mips_output_division ("<d>divu\t$0,%1,%2", operands); } 1905 [(set_attr "type" "idiv") 1906 (set_attr "mode" "<MODE>")]) 1907 1908;; 1909;; .................... 1910;; 1911;; SQUARE ROOT 1912;; 1913;; .................... 1914 1915;; These patterns work around the early SB-1 rev2 core "F1" erratum (see 1916;; "*div[sd]f3" comment for details). 1917 1918(define_insn "sqrt<mode>2" 1919 [(set (match_operand:ANYF 0 "register_operand" "=f") 1920 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 1921 "<sqrt_condition>" 1922{ 1923 if (TARGET_FIX_SB1) 1924 return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0"; 1925 else 1926 return "sqrt.<fmt>\t%0,%1"; 1927} 1928 [(set_attr "type" "fsqrt") 1929 (set_attr "mode" "<UNITMODE>") 1930 (set (attr "length") 1931 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1932 (const_int 8) 1933 (const_int 4)))]) 1934 1935(define_insn "*rsqrt<mode>a" 1936 [(set (match_operand:ANYF 0 "register_operand" "=f") 1937 (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") 1938 (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))] 1939 "<recip_condition> && flag_unsafe_math_optimizations" 1940{ 1941 if (TARGET_FIX_SB1) 1942 return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; 1943 else 1944 return "rsqrt.<fmt>\t%0,%2"; 1945} 1946 [(set_attr "type" "frsqrt") 1947 (set_attr "mode" "<UNITMODE>") 1948 (set (attr "length") 1949 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1950 (const_int 8) 1951 (const_int 4)))]) 1952 1953(define_insn "*rsqrt<mode>b" 1954 [(set (match_operand:ANYF 0 "register_operand" "=f") 1955 (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") 1956 (match_operand:ANYF 2 "register_operand" "f"))))] 1957 "<recip_condition> && flag_unsafe_math_optimizations" 1958{ 1959 if (TARGET_FIX_SB1) 1960 return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; 1961 else 1962 return "rsqrt.<fmt>\t%0,%2"; 1963} 1964 [(set_attr "type" "frsqrt") 1965 (set_attr "mode" "<UNITMODE>") 1966 (set (attr "length") 1967 (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) 1968 (const_int 8) 1969 (const_int 4)))]) 1970 1971;; 1972;; .................... 1973;; 1974;; ABSOLUTE VALUE 1975;; 1976;; .................... 1977 1978;; Do not use the integer abs macro instruction, since that signals an 1979;; exception on -2147483648 (sigh). 1980 1981;; abs.fmt is an arithmetic instruction and treats all NaN inputs as 1982;; invalid; it does not clear their sign bits. We therefore can't use 1983;; abs.fmt if the signs of NaNs matter. 1984 1985(define_insn "abs<mode>2" 1986 [(set (match_operand:ANYF 0 "register_operand" "=f") 1987 (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 1988 "!HONOR_NANS (<MODE>mode)" 1989 "abs.<fmt>\t%0,%1" 1990 [(set_attr "type" "fabs") 1991 (set_attr "mode" "<UNITMODE>")]) 1992 1993;; 1994;; ................... 1995;; 1996;; Count leading zeroes. 1997;; 1998;; ................... 1999;; 2000 2001(define_insn "clz<mode>2" 2002 [(set (match_operand:GPR 0 "register_operand" "=d") 2003 (clz:GPR (match_operand:GPR 1 "register_operand" "d")))] 2004 "ISA_HAS_CLZ_CLO" 2005 "<d>clz\t%0,%1" 2006 [(set_attr "type" "clz") 2007 (set_attr "mode" "<MODE>")]) 2008 2009;; 2010;; .................... 2011;; 2012;; NEGATION and ONE'S COMPLEMENT 2013;; 2014;; .................... 2015 2016(define_insn "negsi2" 2017 [(set (match_operand:SI 0 "register_operand" "=d") 2018 (neg:SI (match_operand:SI 1 "register_operand" "d")))] 2019 "" 2020{ 2021 if (TARGET_MIPS16) 2022 return "neg\t%0,%1"; 2023 else 2024 return "subu\t%0,%.,%1"; 2025} 2026 [(set_attr "type" "arith") 2027 (set_attr "mode" "SI")]) 2028 2029(define_insn "negdi2" 2030 [(set (match_operand:DI 0 "register_operand" "=d") 2031 (neg:DI (match_operand:DI 1 "register_operand" "d")))] 2032 "TARGET_64BIT && !TARGET_MIPS16" 2033 "dsubu\t%0,%.,%1" 2034 [(set_attr "type" "arith") 2035 (set_attr "mode" "DI")]) 2036 2037;; neg.fmt is an arithmetic instruction and treats all NaN inputs as 2038;; invalid; it does not flip their sign bit. We therefore can't use 2039;; neg.fmt if the signs of NaNs matter. 2040 2041(define_insn "neg<mode>2" 2042 [(set (match_operand:ANYF 0 "register_operand" "=f") 2043 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 2044 "!HONOR_NANS (<MODE>mode)" 2045 "neg.<fmt>\t%0,%1" 2046 [(set_attr "type" "fneg") 2047 (set_attr "mode" "<UNITMODE>")]) 2048 2049(define_insn "one_cmpl<mode>2" 2050 [(set (match_operand:GPR 0 "register_operand" "=d") 2051 (not:GPR (match_operand:GPR 1 "register_operand" "d")))] 2052 "" 2053{ 2054 if (TARGET_MIPS16) 2055 return "not\t%0,%1"; 2056 else 2057 return "nor\t%0,%.,%1"; 2058} 2059 [(set_attr "type" "arith") 2060 (set_attr "mode" "<MODE>")]) 2061 2062;; 2063;; .................... 2064;; 2065;; LOGICAL 2066;; 2067;; .................... 2068;; 2069 2070;; Many of these instructions use trivial define_expands, because we 2071;; want to use a different set of constraints when TARGET_MIPS16. 2072 2073(define_expand "and<mode>3" 2074 [(set (match_operand:GPR 0 "register_operand") 2075 (and:GPR (match_operand:GPR 1 "register_operand") 2076 (match_operand:GPR 2 "uns_arith_operand")))] 2077 "" 2078{ 2079 if (TARGET_MIPS16) 2080 operands[2] = force_reg (<MODE>mode, operands[2]); 2081}) 2082 2083(define_insn "*and<mode>3" 2084 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2085 (and:GPR (match_operand:GPR 1 "register_operand" "%d,d") 2086 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] 2087 "!TARGET_MIPS16" 2088 "@ 2089 and\t%0,%1,%2 2090 andi\t%0,%1,%x2" 2091 [(set_attr "type" "arith") 2092 (set_attr "mode" "<MODE>")]) 2093 2094(define_insn "*and<mode>3_mips16" 2095 [(set (match_operand:GPR 0 "register_operand" "=d") 2096 (and:GPR (match_operand:GPR 1 "register_operand" "%0") 2097 (match_operand:GPR 2 "register_operand" "d")))] 2098 "TARGET_MIPS16" 2099 "and\t%0,%2" 2100 [(set_attr "type" "arith") 2101 (set_attr "mode" "<MODE>")]) 2102 2103(define_expand "ior<mode>3" 2104 [(set (match_operand:GPR 0 "register_operand") 2105 (ior:GPR (match_operand:GPR 1 "register_operand") 2106 (match_operand:GPR 2 "uns_arith_operand")))] 2107 "" 2108{ 2109 if (TARGET_MIPS16) 2110 operands[2] = force_reg (<MODE>mode, operands[2]); 2111}) 2112 2113(define_insn "*ior<mode>3" 2114 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2115 (ior:GPR (match_operand:GPR 1 "register_operand" "%d,d") 2116 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] 2117 "!TARGET_MIPS16" 2118 "@ 2119 or\t%0,%1,%2 2120 ori\t%0,%1,%x2" 2121 [(set_attr "type" "arith") 2122 (set_attr "mode" "<MODE>")]) 2123 2124(define_insn "*ior<mode>3_mips16" 2125 [(set (match_operand:GPR 0 "register_operand" "=d") 2126 (ior:GPR (match_operand:GPR 1 "register_operand" "%0") 2127 (match_operand:GPR 2 "register_operand" "d")))] 2128 "TARGET_MIPS16" 2129 "or\t%0,%2" 2130 [(set_attr "type" "arith") 2131 (set_attr "mode" "<MODE>")]) 2132 2133(define_expand "xor<mode>3" 2134 [(set (match_operand:GPR 0 "register_operand") 2135 (xor:GPR (match_operand:GPR 1 "register_operand") 2136 (match_operand:GPR 2 "uns_arith_operand")))] 2137 "" 2138 "") 2139 2140(define_insn "" 2141 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2142 (xor:GPR (match_operand:GPR 1 "register_operand" "%d,d") 2143 (match_operand:GPR 2 "uns_arith_operand" "d,K")))] 2144 "!TARGET_MIPS16" 2145 "@ 2146 xor\t%0,%1,%2 2147 xori\t%0,%1,%x2" 2148 [(set_attr "type" "arith") 2149 (set_attr "mode" "<MODE>")]) 2150 2151(define_insn "" 2152 [(set (match_operand:GPR 0 "register_operand" "=d,t,t") 2153 (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d") 2154 (match_operand:GPR 2 "uns_arith_operand" "d,K,d")))] 2155 "TARGET_MIPS16" 2156 "@ 2157 xor\t%0,%2 2158 cmpi\t%1,%2 2159 cmp\t%1,%2" 2160 [(set_attr "type" "arith") 2161 (set_attr "mode" "<MODE>") 2162 (set_attr_alternative "length" 2163 [(const_int 4) 2164 (if_then_else (match_operand:VOID 2 "m16_uimm8_1") 2165 (const_int 4) 2166 (const_int 8)) 2167 (const_int 4)])]) 2168 2169(define_insn "*nor<mode>3" 2170 [(set (match_operand:GPR 0 "register_operand" "=d") 2171 (and:GPR (not:GPR (match_operand:GPR 1 "register_operand" "d")) 2172 (not:GPR (match_operand:GPR 2 "register_operand" "d"))))] 2173 "!TARGET_MIPS16" 2174 "nor\t%0,%1,%2" 2175 [(set_attr "type" "arith") 2176 (set_attr "mode" "<MODE>")]) 2177 2178;; 2179;; .................... 2180;; 2181;; TRUNCATION 2182;; 2183;; .................... 2184 2185 2186 2187(define_insn "truncdfsf2" 2188 [(set (match_operand:SF 0 "register_operand" "=f") 2189 (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] 2190 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2191 "cvt.s.d\t%0,%1" 2192 [(set_attr "type" "fcvt") 2193 (set_attr "cnv_mode" "D2S") 2194 (set_attr "mode" "SF")]) 2195 2196;; Integer truncation patterns. Truncating SImode values to smaller 2197;; modes is a no-op, as it is for most other GCC ports. Truncating 2198;; DImode values to SImode is not a no-op for TARGET_64BIT since we 2199;; need to make sure that the lower 32 bits are properly sign-extended 2200;; (see TRULY_NOOP_TRUNCATION). Truncating DImode values into modes 2201;; smaller than SImode is equivalent to two separate truncations: 2202;; 2203;; A B 2204;; DI ---> HI == DI ---> SI ---> HI 2205;; DI ---> QI == DI ---> SI ---> QI 2206;; 2207;; Step A needs a real instruction but step B does not. 2208 2209(define_insn "truncdisi2" 2210 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m") 2211 (truncate:SI (match_operand:DI 1 "register_operand" "d,d")))] 2212 "TARGET_64BIT" 2213 "@ 2214 sll\t%0,%1,0 2215 sw\t%1,%0" 2216 [(set_attr "type" "shift,store") 2217 (set_attr "mode" "SI") 2218 (set_attr "extended_mips16" "yes,*")]) 2219 2220(define_insn "truncdihi2" 2221 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") 2222 (truncate:HI (match_operand:DI 1 "register_operand" "d,d")))] 2223 "TARGET_64BIT" 2224 "@ 2225 sll\t%0,%1,0 2226 sh\t%1,%0" 2227 [(set_attr "type" "shift,store") 2228 (set_attr "mode" "SI") 2229 (set_attr "extended_mips16" "yes,*")]) 2230 2231(define_insn "truncdiqi2" 2232 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") 2233 (truncate:QI (match_operand:DI 1 "register_operand" "d,d")))] 2234 "TARGET_64BIT" 2235 "@ 2236 sll\t%0,%1,0 2237 sb\t%1,%0" 2238 [(set_attr "type" "shift,store") 2239 (set_attr "mode" "SI") 2240 (set_attr "extended_mips16" "yes,*")]) 2241 2242;; Combiner patterns to optimize shift/truncate combinations. 2243 2244(define_insn "" 2245 [(set (match_operand:SI 0 "register_operand" "=d") 2246 (truncate:SI 2247 (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") 2248 (match_operand:DI 2 "const_arith_operand" ""))))] 2249 "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32" 2250 "dsra\t%0,%1,%2" 2251 [(set_attr "type" "shift") 2252 (set_attr "mode" "SI")]) 2253 2254(define_insn "" 2255 [(set (match_operand:SI 0 "register_operand" "=d") 2256 (truncate:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") 2257 (const_int 32))))] 2258 "TARGET_64BIT && !TARGET_MIPS16" 2259 "dsra\t%0,%1,32" 2260 [(set_attr "type" "shift") 2261 (set_attr "mode" "SI")]) 2262 2263 2264;; Combiner patterns for truncate/sign_extend combinations. They use 2265;; the shift/truncate patterns above. 2266 2267(define_insn_and_split "" 2268 [(set (match_operand:SI 0 "register_operand" "=d") 2269 (sign_extend:SI 2270 (truncate:HI (match_operand:DI 1 "register_operand" "d"))))] 2271 "TARGET_64BIT && !TARGET_MIPS16" 2272 "#" 2273 "&& reload_completed" 2274 [(set (match_dup 2) 2275 (ashift:DI (match_dup 1) 2276 (const_int 48))) 2277 (set (match_dup 0) 2278 (truncate:SI (ashiftrt:DI (match_dup 2) 2279 (const_int 48))))] 2280 { operands[2] = gen_lowpart (DImode, operands[0]); }) 2281 2282(define_insn_and_split "" 2283 [(set (match_operand:SI 0 "register_operand" "=d") 2284 (sign_extend:SI 2285 (truncate:QI (match_operand:DI 1 "register_operand" "d"))))] 2286 "TARGET_64BIT && !TARGET_MIPS16" 2287 "#" 2288 "&& reload_completed" 2289 [(set (match_dup 2) 2290 (ashift:DI (match_dup 1) 2291 (const_int 56))) 2292 (set (match_dup 0) 2293 (truncate:SI (ashiftrt:DI (match_dup 2) 2294 (const_int 56))))] 2295 { operands[2] = gen_lowpart (DImode, operands[0]); }) 2296 2297 2298;; Combiner patterns to optimize truncate/zero_extend combinations. 2299 2300(define_insn "" 2301 [(set (match_operand:SI 0 "register_operand" "=d") 2302 (zero_extend:SI (truncate:HI 2303 (match_operand:DI 1 "register_operand" "d"))))] 2304 "TARGET_64BIT && !TARGET_MIPS16" 2305 "andi\t%0,%1,0xffff" 2306 [(set_attr "type" "arith") 2307 (set_attr "mode" "SI")]) 2308 2309(define_insn "" 2310 [(set (match_operand:SI 0 "register_operand" "=d") 2311 (zero_extend:SI (truncate:QI 2312 (match_operand:DI 1 "register_operand" "d"))))] 2313 "TARGET_64BIT && !TARGET_MIPS16" 2314 "andi\t%0,%1,0xff" 2315 [(set_attr "type" "arith") 2316 (set_attr "mode" "SI")]) 2317 2318(define_insn "" 2319 [(set (match_operand:HI 0 "register_operand" "=d") 2320 (zero_extend:HI (truncate:QI 2321 (match_operand:DI 1 "register_operand" "d"))))] 2322 "TARGET_64BIT && !TARGET_MIPS16" 2323 "andi\t%0,%1,0xff" 2324 [(set_attr "type" "arith") 2325 (set_attr "mode" "HI")]) 2326 2327;; 2328;; .................... 2329;; 2330;; ZERO EXTENSION 2331;; 2332;; .................... 2333 2334;; Extension insns. 2335 2336(define_insn_and_split "zero_extendsidi2" 2337 [(set (match_operand:DI 0 "register_operand" "=d,d") 2338 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))] 2339 "TARGET_64BIT" 2340 "@ 2341 # 2342 lwu\t%0,%1" 2343 "&& reload_completed && REG_P (operands[1])" 2344 [(set (match_dup 0) 2345 (ashift:DI (match_dup 1) (const_int 32))) 2346 (set (match_dup 0) 2347 (lshiftrt:DI (match_dup 0) (const_int 32)))] 2348 { operands[1] = gen_lowpart (DImode, operands[1]); } 2349 [(set_attr "type" "multi,load") 2350 (set_attr "mode" "DI") 2351 (set_attr "length" "8,*")]) 2352 2353;; Combine is not allowed to convert this insn into a zero_extendsidi2 2354;; because of TRULY_NOOP_TRUNCATION. 2355 2356(define_insn_and_split "*clear_upper32" 2357 [(set (match_operand:DI 0 "register_operand" "=d,d") 2358 (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o") 2359 (const_int 4294967295)))] 2360 "TARGET_64BIT" 2361{ 2362 if (which_alternative == 0) 2363 return "#"; 2364 2365 operands[1] = gen_lowpart (SImode, operands[1]); 2366 return "lwu\t%0,%1"; 2367} 2368 "&& reload_completed && REG_P (operands[1])" 2369 [(set (match_dup 0) 2370 (ashift:DI (match_dup 1) (const_int 32))) 2371 (set (match_dup 0) 2372 (lshiftrt:DI (match_dup 0) (const_int 32)))] 2373 "" 2374 [(set_attr "type" "multi,load") 2375 (set_attr "mode" "DI") 2376 (set_attr "length" "8,*")]) 2377 2378(define_expand "zero_extend<SHORT:mode><GPR:mode>2" 2379 [(set (match_operand:GPR 0 "register_operand") 2380 (zero_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))] 2381 "" 2382{ 2383 if (TARGET_MIPS16 && !GENERATE_MIPS16E 2384 && !memory_operand (operands[1], <SHORT:MODE>mode)) 2385 { 2386 emit_insn (gen_and<GPR:mode>3 (operands[0], 2387 gen_lowpart (<GPR:MODE>mode, operands[1]), 2388 force_reg (<GPR:MODE>mode, 2389 GEN_INT (<SHORT:mask>)))); 2390 DONE; 2391 } 2392}) 2393 2394(define_insn "*zero_extend<SHORT:mode><GPR:mode>2" 2395 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2396 (zero_extend:GPR 2397 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] 2398 "!TARGET_MIPS16" 2399 "@ 2400 andi\t%0,%1,<SHORT:mask> 2401 l<SHORT:size>u\t%0,%1" 2402 [(set_attr "type" "arith,load") 2403 (set_attr "mode" "<GPR:MODE>")]) 2404 2405(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16e" 2406 [(set (match_operand:GPR 0 "register_operand" "=d") 2407 (zero_extend:GPR (match_operand:SHORT 1 "register_operand" "0")))] 2408 "GENERATE_MIPS16E" 2409 "ze<SHORT:size>\t%0" 2410 [(set_attr "type" "arith") 2411 (set_attr "mode" "<GPR:MODE>")]) 2412 2413(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16" 2414 [(set (match_operand:GPR 0 "register_operand" "=d") 2415 (zero_extend:GPR (match_operand:SHORT 1 "memory_operand" "m")))] 2416 "TARGET_MIPS16" 2417 "l<SHORT:size>u\t%0,%1" 2418 [(set_attr "type" "load") 2419 (set_attr "mode" "<GPR:MODE>")]) 2420 2421(define_expand "zero_extendqihi2" 2422 [(set (match_operand:HI 0 "register_operand") 2423 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))] 2424 "" 2425{ 2426 if (TARGET_MIPS16 && !memory_operand (operands[1], QImode)) 2427 { 2428 emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]), 2429 operands[1])); 2430 DONE; 2431 } 2432}) 2433 2434(define_insn "*zero_extendqihi2" 2435 [(set (match_operand:HI 0 "register_operand" "=d,d") 2436 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] 2437 "!TARGET_MIPS16" 2438 "@ 2439 andi\t%0,%1,0x00ff 2440 lbu\t%0,%1" 2441 [(set_attr "type" "arith,load") 2442 (set_attr "mode" "HI")]) 2443 2444(define_insn "*zero_extendqihi2_mips16" 2445 [(set (match_operand:HI 0 "register_operand" "=d") 2446 (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] 2447 "TARGET_MIPS16" 2448 "lbu\t%0,%1" 2449 [(set_attr "type" "load") 2450 (set_attr "mode" "HI")]) 2451 2452;; 2453;; .................... 2454;; 2455;; SIGN EXTENSION 2456;; 2457;; .................... 2458 2459;; Extension insns. 2460;; Those for integer source operand are ordered widest source type first. 2461 2462;; When TARGET_64BIT, all SImode integer registers should already be in 2463;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2). We can 2464;; therefore get rid of register->register instructions if we constrain 2465;; the source to be in the same register as the destination. 2466;; 2467;; The register alternative has type "arith" so that the pre-reload 2468;; scheduler will treat it as a move. This reflects what happens if 2469;; the register alternative needs a reload. 2470(define_insn_and_split "extendsidi2" 2471 [(set (match_operand:DI 0 "register_operand" "=d,d") 2472 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))] 2473 "TARGET_64BIT" 2474 "@ 2475 # 2476 lw\t%0,%1" 2477 "&& reload_completed && register_operand (operands[1], VOIDmode)" 2478 [(const_int 0)] 2479{ 2480 emit_note (NOTE_INSN_DELETED); 2481 DONE; 2482} 2483 [(set_attr "type" "arith,load") 2484 (set_attr "mode" "DI")]) 2485 2486(define_expand "extend<SHORT:mode><GPR:mode>2" 2487 [(set (match_operand:GPR 0 "register_operand") 2488 (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))] 2489 "") 2490 2491(define_insn "*extend<SHORT:mode><GPR:mode>2_mips16e" 2492 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2493 (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand" "0,m")))] 2494 "GENERATE_MIPS16E" 2495 "@ 2496 se<SHORT:size>\t%0 2497 l<SHORT:size>\t%0,%1" 2498 [(set_attr "type" "arith,load") 2499 (set_attr "mode" "<GPR:MODE>")]) 2500 2501(define_insn_and_split "*extend<SHORT:mode><GPR:mode>2" 2502 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2503 (sign_extend:GPR 2504 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] 2505 "!ISA_HAS_SEB_SEH && !GENERATE_MIPS16E" 2506 "@ 2507 # 2508 l<SHORT:size>\t%0,%1" 2509 "&& reload_completed && REG_P (operands[1])" 2510 [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2))) 2511 (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))] 2512{ 2513 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]); 2514 operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode) 2515 - GET_MODE_BITSIZE (<SHORT:MODE>mode)); 2516} 2517 [(set_attr "type" "arith,load") 2518 (set_attr "mode" "<GPR:MODE>") 2519 (set_attr "length" "8,*")]) 2520 2521(define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>" 2522 [(set (match_operand:GPR 0 "register_operand" "=d,d") 2523 (sign_extend:GPR 2524 (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))] 2525 "ISA_HAS_SEB_SEH" 2526 "@ 2527 se<SHORT:size>\t%0,%1 2528 l<SHORT:size>\t%0,%1" 2529 [(set_attr "type" "arith,load") 2530 (set_attr "mode" "<GPR:MODE>")]) 2531 2532;; This pattern generates the same code as extendqisi2; split it into 2533;; that form after reload. 2534(define_insn_and_split "extendqihi2" 2535 [(set (match_operand:HI 0 "register_operand" "=d,d") 2536 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] 2537 "" 2538 "#" 2539 "reload_completed" 2540 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] 2541 { operands[0] = gen_lowpart (SImode, operands[0]); } 2542 [(set_attr "type" "arith,load") 2543 (set_attr "mode" "SI") 2544 (set_attr "length" "8,*")]) 2545 2546(define_insn "extendsfdf2" 2547 [(set (match_operand:DF 0 "register_operand" "=f") 2548 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] 2549 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2550 "cvt.d.s\t%0,%1" 2551 [(set_attr "type" "fcvt") 2552 (set_attr "cnv_mode" "S2D") 2553 (set_attr "mode" "DF")]) 2554 2555;; 2556;; .................... 2557;; 2558;; CONVERSIONS 2559;; 2560;; .................... 2561 2562(define_expand "fix_truncdfsi2" 2563 [(set (match_operand:SI 0 "register_operand") 2564 (fix:SI (match_operand:DF 1 "register_operand")))] 2565 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2566{ 2567 if (!ISA_HAS_TRUNC_W) 2568 { 2569 emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1])); 2570 DONE; 2571 } 2572}) 2573 2574(define_insn "fix_truncdfsi2_insn" 2575 [(set (match_operand:SI 0 "register_operand" "=f") 2576 (fix:SI (match_operand:DF 1 "register_operand" "f")))] 2577 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && ISA_HAS_TRUNC_W" 2578 "trunc.w.d %0,%1" 2579 [(set_attr "type" "fcvt") 2580 (set_attr "mode" "DF") 2581 (set_attr "cnv_mode" "D2I") 2582 (set_attr "length" "4")]) 2583 2584(define_insn "fix_truncdfsi2_macro" 2585 [(set (match_operand:SI 0 "register_operand" "=f") 2586 (fix:SI (match_operand:DF 1 "register_operand" "f"))) 2587 (clobber (match_scratch:DF 2 "=d"))] 2588 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W" 2589{ 2590 if (set_nomacro) 2591 return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro"; 2592 else 2593 return "trunc.w.d %0,%1,%2"; 2594} 2595 [(set_attr "type" "fcvt") 2596 (set_attr "mode" "DF") 2597 (set_attr "cnv_mode" "D2I") 2598 (set_attr "length" "36")]) 2599 2600(define_expand "fix_truncsfsi2" 2601 [(set (match_operand:SI 0 "register_operand") 2602 (fix:SI (match_operand:SF 1 "register_operand")))] 2603 "TARGET_HARD_FLOAT" 2604{ 2605 if (!ISA_HAS_TRUNC_W) 2606 { 2607 emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1])); 2608 DONE; 2609 } 2610}) 2611 2612(define_insn "fix_truncsfsi2_insn" 2613 [(set (match_operand:SI 0 "register_operand" "=f") 2614 (fix:SI (match_operand:SF 1 "register_operand" "f")))] 2615 "TARGET_HARD_FLOAT && ISA_HAS_TRUNC_W" 2616 "trunc.w.s %0,%1" 2617 [(set_attr "type" "fcvt") 2618 (set_attr "mode" "SF") 2619 (set_attr "cnv_mode" "S2I") 2620 (set_attr "length" "4")]) 2621 2622(define_insn "fix_truncsfsi2_macro" 2623 [(set (match_operand:SI 0 "register_operand" "=f") 2624 (fix:SI (match_operand:SF 1 "register_operand" "f"))) 2625 (clobber (match_scratch:SF 2 "=d"))] 2626 "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W" 2627{ 2628 if (set_nomacro) 2629 return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro"; 2630 else 2631 return "trunc.w.s %0,%1,%2"; 2632} 2633 [(set_attr "type" "fcvt") 2634 (set_attr "mode" "SF") 2635 (set_attr "cnv_mode" "S2I") 2636 (set_attr "length" "36")]) 2637 2638 2639(define_insn "fix_truncdfdi2" 2640 [(set (match_operand:DI 0 "register_operand" "=f") 2641 (fix:DI (match_operand:DF 1 "register_operand" "f")))] 2642 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2643 "trunc.l.d %0,%1" 2644 [(set_attr "type" "fcvt") 2645 (set_attr "mode" "DF") 2646 (set_attr "cnv_mode" "D2I") 2647 (set_attr "length" "4")]) 2648 2649 2650(define_insn "fix_truncsfdi2" 2651 [(set (match_operand:DI 0 "register_operand" "=f") 2652 (fix:DI (match_operand:SF 1 "register_operand" "f")))] 2653 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2654 "trunc.l.s %0,%1" 2655 [(set_attr "type" "fcvt") 2656 (set_attr "mode" "SF") 2657 (set_attr "cnv_mode" "S2I") 2658 (set_attr "length" "4")]) 2659 2660 2661(define_insn "floatsidf2" 2662 [(set (match_operand:DF 0 "register_operand" "=f") 2663 (float:DF (match_operand:SI 1 "register_operand" "f")))] 2664 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2665 "cvt.d.w\t%0,%1" 2666 [(set_attr "type" "fcvt") 2667 (set_attr "mode" "DF") 2668 (set_attr "cnv_mode" "I2D") 2669 (set_attr "length" "4")]) 2670 2671 2672(define_insn "floatdidf2" 2673 [(set (match_operand:DF 0 "register_operand" "=f") 2674 (float:DF (match_operand:DI 1 "register_operand" "f")))] 2675 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2676 "cvt.d.l\t%0,%1" 2677 [(set_attr "type" "fcvt") 2678 (set_attr "mode" "DF") 2679 (set_attr "cnv_mode" "I2D") 2680 (set_attr "length" "4")]) 2681 2682 2683(define_insn "floatsisf2" 2684 [(set (match_operand:SF 0 "register_operand" "=f") 2685 (float:SF (match_operand:SI 1 "register_operand" "f")))] 2686 "TARGET_HARD_FLOAT" 2687 "cvt.s.w\t%0,%1" 2688 [(set_attr "type" "fcvt") 2689 (set_attr "mode" "SF") 2690 (set_attr "cnv_mode" "I2S") 2691 (set_attr "length" "4")]) 2692 2693 2694(define_insn "floatdisf2" 2695 [(set (match_operand:SF 0 "register_operand" "=f") 2696 (float:SF (match_operand:DI 1 "register_operand" "f")))] 2697 "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT" 2698 "cvt.s.l\t%0,%1" 2699 [(set_attr "type" "fcvt") 2700 (set_attr "mode" "SF") 2701 (set_attr "cnv_mode" "I2S") 2702 (set_attr "length" "4")]) 2703 2704 2705(define_expand "fixuns_truncdfsi2" 2706 [(set (match_operand:SI 0 "register_operand") 2707 (unsigned_fix:SI (match_operand:DF 1 "register_operand")))] 2708 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 2709{ 2710 rtx reg1 = gen_reg_rtx (DFmode); 2711 rtx reg2 = gen_reg_rtx (DFmode); 2712 rtx reg3 = gen_reg_rtx (SImode); 2713 rtx label1 = gen_label_rtx (); 2714 rtx label2 = gen_label_rtx (); 2715 REAL_VALUE_TYPE offset; 2716 2717 real_2expN (&offset, 31); 2718 2719 if (reg1) /* Turn off complaints about unreached code. */ 2720 { 2721 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); 2722 do_pending_stack_adjust (); 2723 2724 emit_insn (gen_cmpdf (operands[1], reg1)); 2725 emit_jump_insn (gen_bge (label1)); 2726 2727 emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1])); 2728 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2729 gen_rtx_LABEL_REF (VOIDmode, label2))); 2730 emit_barrier (); 2731 2732 emit_label (label1); 2733 emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); 2734 emit_move_insn (reg3, GEN_INT (trunc_int_for_mode 2735 (BITMASK_HIGH, SImode))); 2736 2737 emit_insn (gen_fix_truncdfsi2 (operands[0], reg2)); 2738 emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); 2739 2740 emit_label (label2); 2741 2742 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2743 fields, and can't be used for REG_NOTES anyway). */ 2744 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2745 DONE; 2746 } 2747}) 2748 2749 2750(define_expand "fixuns_truncdfdi2" 2751 [(set (match_operand:DI 0 "register_operand") 2752 (unsigned_fix:DI (match_operand:DF 1 "register_operand")))] 2753 "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" 2754{ 2755 rtx reg1 = gen_reg_rtx (DFmode); 2756 rtx reg2 = gen_reg_rtx (DFmode); 2757 rtx reg3 = gen_reg_rtx (DImode); 2758 rtx label1 = gen_label_rtx (); 2759 rtx label2 = gen_label_rtx (); 2760 REAL_VALUE_TYPE offset; 2761 2762 real_2expN (&offset, 63); 2763 2764 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode)); 2765 do_pending_stack_adjust (); 2766 2767 emit_insn (gen_cmpdf (operands[1], reg1)); 2768 emit_jump_insn (gen_bge (label1)); 2769 2770 emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1])); 2771 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2772 gen_rtx_LABEL_REF (VOIDmode, label2))); 2773 emit_barrier (); 2774 2775 emit_label (label1); 2776 emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1)); 2777 emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); 2778 emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); 2779 2780 emit_insn (gen_fix_truncdfdi2 (operands[0], reg2)); 2781 emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); 2782 2783 emit_label (label2); 2784 2785 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2786 fields, and can't be used for REG_NOTES anyway). */ 2787 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2788 DONE; 2789}) 2790 2791 2792(define_expand "fixuns_truncsfsi2" 2793 [(set (match_operand:SI 0 "register_operand") 2794 (unsigned_fix:SI (match_operand:SF 1 "register_operand")))] 2795 "TARGET_HARD_FLOAT" 2796{ 2797 rtx reg1 = gen_reg_rtx (SFmode); 2798 rtx reg2 = gen_reg_rtx (SFmode); 2799 rtx reg3 = gen_reg_rtx (SImode); 2800 rtx label1 = gen_label_rtx (); 2801 rtx label2 = gen_label_rtx (); 2802 REAL_VALUE_TYPE offset; 2803 2804 real_2expN (&offset, 31); 2805 2806 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); 2807 do_pending_stack_adjust (); 2808 2809 emit_insn (gen_cmpsf (operands[1], reg1)); 2810 emit_jump_insn (gen_bge (label1)); 2811 2812 emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1])); 2813 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2814 gen_rtx_LABEL_REF (VOIDmode, label2))); 2815 emit_barrier (); 2816 2817 emit_label (label1); 2818 emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); 2819 emit_move_insn (reg3, GEN_INT (trunc_int_for_mode 2820 (BITMASK_HIGH, SImode))); 2821 2822 emit_insn (gen_fix_truncsfsi2 (operands[0], reg2)); 2823 emit_insn (gen_iorsi3 (operands[0], operands[0], reg3)); 2824 2825 emit_label (label2); 2826 2827 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2828 fields, and can't be used for REG_NOTES anyway). */ 2829 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2830 DONE; 2831}) 2832 2833 2834(define_expand "fixuns_truncsfdi2" 2835 [(set (match_operand:DI 0 "register_operand") 2836 (unsigned_fix:DI (match_operand:SF 1 "register_operand")))] 2837 "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT" 2838{ 2839 rtx reg1 = gen_reg_rtx (SFmode); 2840 rtx reg2 = gen_reg_rtx (SFmode); 2841 rtx reg3 = gen_reg_rtx (DImode); 2842 rtx label1 = gen_label_rtx (); 2843 rtx label2 = gen_label_rtx (); 2844 REAL_VALUE_TYPE offset; 2845 2846 real_2expN (&offset, 63); 2847 2848 emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode)); 2849 do_pending_stack_adjust (); 2850 2851 emit_insn (gen_cmpsf (operands[1], reg1)); 2852 emit_jump_insn (gen_bge (label1)); 2853 2854 emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1])); 2855 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, 2856 gen_rtx_LABEL_REF (VOIDmode, label2))); 2857 emit_barrier (); 2858 2859 emit_label (label1); 2860 emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1)); 2861 emit_move_insn (reg3, GEN_INT (BITMASK_HIGH)); 2862 emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32))); 2863 2864 emit_insn (gen_fix_truncsfdi2 (operands[0], reg2)); 2865 emit_insn (gen_iordi3 (operands[0], operands[0], reg3)); 2866 2867 emit_label (label2); 2868 2869 /* Allow REG_NOTES to be set on last insn (labels don't have enough 2870 fields, and can't be used for REG_NOTES anyway). */ 2871 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 2872 DONE; 2873}) 2874 2875;; 2876;; .................... 2877;; 2878;; DATA MOVEMENT 2879;; 2880;; .................... 2881 2882;; Bit field extract patterns which use lwl/lwr or ldl/ldr. 2883 2884(define_expand "extv" 2885 [(set (match_operand 0 "register_operand") 2886 (sign_extract (match_operand:QI 1 "memory_operand") 2887 (match_operand 2 "immediate_operand") 2888 (match_operand 3 "immediate_operand")))] 2889 "!TARGET_MIPS16" 2890{ 2891 if (mips_expand_unaligned_load (operands[0], operands[1], 2892 INTVAL (operands[2]), 2893 INTVAL (operands[3]))) 2894 DONE; 2895 else 2896 FAIL; 2897}) 2898 2899(define_expand "extzv" 2900 [(set (match_operand 0 "register_operand") 2901 (zero_extract (match_operand 1 "nonimmediate_operand") 2902 (match_operand 2 "immediate_operand") 2903 (match_operand 3 "immediate_operand")))] 2904 "!TARGET_MIPS16" 2905{ 2906 if (mips_expand_unaligned_load (operands[0], operands[1], 2907 INTVAL (operands[2]), 2908 INTVAL (operands[3]))) 2909 DONE; 2910 else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3])) 2911 { 2912 if (GET_MODE (operands[0]) == DImode) 2913 emit_insn (gen_extzvdi (operands[0], operands[1], operands[2], 2914 operands[3])); 2915 else 2916 emit_insn (gen_extzvsi (operands[0], operands[1], operands[2], 2917 operands[3])); 2918 DONE; 2919 } 2920 else 2921 FAIL; 2922}) 2923 2924(define_insn "extzv<mode>" 2925 [(set (match_operand:GPR 0 "register_operand" "=d") 2926 (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d") 2927 (match_operand:SI 2 "immediate_operand" "I") 2928 (match_operand:SI 3 "immediate_operand" "I")))] 2929 "mips_use_ins_ext_p (operands[1], operands[2], operands[3])" 2930 "<d>ext\t%0,%1,%3,%2" 2931 [(set_attr "type" "arith") 2932 (set_attr "mode" "<MODE>")]) 2933 2934 2935(define_expand "insv" 2936 [(set (zero_extract (match_operand 0 "nonimmediate_operand") 2937 (match_operand 1 "immediate_operand") 2938 (match_operand 2 "immediate_operand")) 2939 (match_operand 3 "reg_or_0_operand"))] 2940 "!TARGET_MIPS16" 2941{ 2942 if (mips_expand_unaligned_store (operands[0], operands[3], 2943 INTVAL (operands[1]), 2944 INTVAL (operands[2]))) 2945 DONE; 2946 else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2])) 2947 { 2948 if (GET_MODE (operands[0]) == DImode) 2949 emit_insn (gen_insvdi (operands[0], operands[1], operands[2], 2950 operands[3])); 2951 else 2952 emit_insn (gen_insvsi (operands[0], operands[1], operands[2], 2953 operands[3])); 2954 DONE; 2955 } 2956 else 2957 FAIL; 2958}) 2959 2960(define_insn "insv<mode>" 2961 [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d") 2962 (match_operand:SI 1 "immediate_operand" "I") 2963 (match_operand:SI 2 "immediate_operand" "I")) 2964 (match_operand:GPR 3 "reg_or_0_operand" "dJ"))] 2965 "mips_use_ins_ext_p (operands[0], operands[1], operands[2])" 2966 "<d>ins\t%0,%z3,%2,%1" 2967 [(set_attr "type" "arith") 2968 (set_attr "mode" "<MODE>")]) 2969 2970;; Unaligned word moves generated by the bit field patterns. 2971;; 2972;; As far as the rtl is concerned, both the left-part and right-part 2973;; instructions can access the whole field. However, the real operand 2974;; refers to just the first or the last byte (depending on endianness). 2975;; We therefore use two memory operands to each instruction, one to 2976;; describe the rtl effect and one to use in the assembly output. 2977;; 2978;; Operands 0 and 1 are the rtl-level target and source respectively. 2979;; This allows us to use the standard length calculations for the "load" 2980;; and "store" type attributes. 2981 2982(define_insn "mov_<load>l" 2983 [(set (match_operand:GPR 0 "register_operand" "=d") 2984 (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") 2985 (match_operand:QI 2 "memory_operand" "m")] 2986 UNSPEC_LOAD_LEFT))] 2987 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" 2988 "<load>l\t%0,%2" 2989 [(set_attr "type" "load") 2990 (set_attr "mode" "<MODE>")]) 2991 2992(define_insn "mov_<load>r" 2993 [(set (match_operand:GPR 0 "register_operand" "=d") 2994 (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") 2995 (match_operand:QI 2 "memory_operand" "m") 2996 (match_operand:GPR 3 "register_operand" "0")] 2997 UNSPEC_LOAD_RIGHT))] 2998 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])" 2999 "<load>r\t%0,%2" 3000 [(set_attr "type" "load") 3001 (set_attr "mode" "<MODE>")]) 3002 3003(define_insn "mov_<store>l" 3004 [(set (match_operand:BLK 0 "memory_operand" "=m") 3005 (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") 3006 (match_operand:QI 2 "memory_operand" "m")] 3007 UNSPEC_STORE_LEFT))] 3008 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" 3009 "<store>l\t%z1,%2" 3010 [(set_attr "type" "store") 3011 (set_attr "mode" "<MODE>")]) 3012 3013(define_insn "mov_<store>r" 3014 [(set (match_operand:BLK 0 "memory_operand" "+m") 3015 (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") 3016 (match_operand:QI 2 "memory_operand" "m") 3017 (match_dup 0)] 3018 UNSPEC_STORE_RIGHT))] 3019 "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])" 3020 "<store>r\t%z1,%2" 3021 [(set_attr "type" "store") 3022 (set_attr "mode" "<MODE>")]) 3023 3024;; An instruction to calculate the high part of a 64-bit SYMBOL_GENERAL. 3025;; The required value is: 3026;; 3027;; (%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16) 3028;; 3029;; which translates to: 3030;; 3031;; lui op0,%highest(op1) 3032;; daddiu op0,op0,%higher(op1) 3033;; dsll op0,op0,16 3034;; daddiu op0,op0,%hi(op1) 3035;; dsll op0,op0,16 3036;; 3037;; The split is deferred until after flow2 to allow the peephole2 below 3038;; to take effect. 3039(define_insn_and_split "*lea_high64" 3040 [(set (match_operand:DI 0 "register_operand" "=d") 3041 (high:DI (match_operand:DI 1 "general_symbolic_operand" "")))] 3042 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" 3043 "#" 3044 "&& flow2_completed" 3045 [(set (match_dup 0) (high:DI (match_dup 2))) 3046 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2))) 3047 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16))) 3048 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) 3049 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))] 3050{ 3051 operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); 3052 operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID); 3053} 3054 [(set_attr "length" "20")]) 3055 3056;; Use a scratch register to reduce the latency of the above pattern 3057;; on superscalar machines. The optimized sequence is: 3058;; 3059;; lui op1,%highest(op2) 3060;; lui op0,%hi(op2) 3061;; daddiu op1,op1,%higher(op2) 3062;; dsll32 op1,op1,0 3063;; daddu op1,op1,op0 3064(define_peephole2 3065 [(set (match_operand:DI 1 "register_operand") 3066 (high:DI (match_operand:DI 2 "general_symbolic_operand"))) 3067 (match_scratch:DI 0 "d")] 3068 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS" 3069 [(set (match_dup 1) (high:DI (match_dup 3))) 3070 (set (match_dup 0) (high:DI (match_dup 4))) 3071 (set (match_dup 1) (lo_sum:DI (match_dup 1) (match_dup 3))) 3072 (set (match_dup 1) (ashift:DI (match_dup 1) (const_int 32))) 3073 (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 0)))] 3074{ 3075 operands[3] = mips_unspec_address (operands[2], SYMBOL_64_HIGH); 3076 operands[4] = mips_unspec_address (operands[2], SYMBOL_64_LOW); 3077}) 3078 3079;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit 3080;; SYMBOL_GENERAL X will take 6 cycles. This next pattern allows combine 3081;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only 3082;; used once. We can then use the sequence: 3083;; 3084;; lui op0,%highest(op1) 3085;; lui op2,%hi(op1) 3086;; daddiu op0,op0,%higher(op1) 3087;; daddiu op2,op2,%lo(op1) 3088;; dsll32 op0,op0,0 3089;; daddu op0,op0,op2 3090;; 3091;; which takes 4 cycles on most superscalar targets. 3092(define_insn_and_split "*lea64" 3093 [(set (match_operand:DI 0 "register_operand" "=d") 3094 (match_operand:DI 1 "general_symbolic_operand" "")) 3095 (clobber (match_scratch:DI 2 "=&d"))] 3096 "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected" 3097 "#" 3098 "&& reload_completed" 3099 [(set (match_dup 0) (high:DI (match_dup 3))) 3100 (set (match_dup 2) (high:DI (match_dup 4))) 3101 (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3))) 3102 (set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4))) 3103 (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) 3104 (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))] 3105{ 3106 operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH); 3107 operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW); 3108} 3109 [(set_attr "length" "24")]) 3110 3111;; Insns to fetch a global symbol from a big GOT. 3112 3113(define_insn_and_split "*xgot_hi<mode>" 3114 [(set (match_operand:P 0 "register_operand" "=d") 3115 (high:P (match_operand:P 1 "global_got_operand" "")))] 3116 "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" 3117 "#" 3118 "&& reload_completed" 3119 [(set (match_dup 0) (high:P (match_dup 2))) 3120 (set (match_dup 0) (plus:P (match_dup 0) (match_dup 3)))] 3121{ 3122 operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); 3123 operands[3] = pic_offset_table_rtx; 3124} 3125 [(set_attr "got" "xgot_high") 3126 (set_attr "mode" "<MODE>")]) 3127 3128(define_insn_and_split "*xgot_lo<mode>" 3129 [(set (match_operand:P 0 "register_operand" "=d") 3130 (lo_sum:P (match_operand:P 1 "register_operand" "d") 3131 (match_operand:P 2 "global_got_operand" "")))] 3132 "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" 3133 "#" 3134 "&& reload_completed" 3135 [(set (match_dup 0) 3136 (unspec:P [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))] 3137 { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); } 3138 [(set_attr "got" "load") 3139 (set_attr "mode" "<MODE>")]) 3140 3141;; Insns to fetch a global symbol from a normal GOT. 3142 3143(define_insn_and_split "*got_disp<mode>" 3144 [(set (match_operand:P 0 "register_operand" "=d") 3145 (match_operand:P 1 "global_got_operand" ""))] 3146 "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT" 3147 "#" 3148 "&& reload_completed" 3149 [(set (match_dup 0) 3150 (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] 3151{ 3152 operands[2] = pic_offset_table_rtx; 3153 operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); 3154} 3155 [(set_attr "got" "load") 3156 (set_attr "mode" "<MODE>")]) 3157 3158;; Insns for loading the high part of a local symbol. 3159 3160(define_insn_and_split "*got_page<mode>" 3161 [(set (match_operand:P 0 "register_operand" "=d") 3162 (high:P (match_operand:P 1 "local_got_operand" "")))] 3163 "TARGET_EXPLICIT_RELOCS" 3164 "#" 3165 "&& reload_completed" 3166 [(set (match_dup 0) 3167 (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] 3168{ 3169 operands[2] = pic_offset_table_rtx; 3170 operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE); 3171} 3172 [(set_attr "got" "load") 3173 (set_attr "mode" "<MODE>")]) 3174 3175;; Lower-level instructions for loading an address from the GOT. 3176;; We could use MEMs, but an unspec gives more optimization 3177;; opportunities. 3178 3179(define_insn "load_got<mode>" 3180 [(set (match_operand:P 0 "register_operand" "=d") 3181 (unspec:P [(match_operand:P 1 "register_operand" "d") 3182 (match_operand:P 2 "immediate_operand" "")] 3183 UNSPEC_LOAD_GOT))] 3184 "" 3185 "<load>\t%0,%R2(%1)" 3186 [(set_attr "type" "load") 3187 (set_attr "mode" "<MODE>") 3188 (set_attr "length" "4")]) 3189 3190;; Instructions for adding the low 16 bits of an address to a register. 3191;; Operand 2 is the address: print_operand works out which relocation 3192;; should be applied. 3193 3194(define_insn "*low<mode>" 3195 [(set (match_operand:P 0 "register_operand" "=d") 3196 (lo_sum:P (match_operand:P 1 "register_operand" "d") 3197 (match_operand:P 2 "immediate_operand" "")))] 3198 "!TARGET_MIPS16" 3199 "<d>addiu\t%0,%1,%R2" 3200 [(set_attr "type" "arith") 3201 (set_attr "mode" "<MODE>")]) 3202 3203(define_insn "*low<mode>_mips16" 3204 [(set (match_operand:P 0 "register_operand" "=d") 3205 (lo_sum:P (match_operand:P 1 "register_operand" "0") 3206 (match_operand:P 2 "immediate_operand" "")))] 3207 "TARGET_MIPS16" 3208 "<d>addiu\t%0,%R2" 3209 [(set_attr "type" "arith") 3210 (set_attr "mode" "<MODE>") 3211 (set_attr "length" "8")]) 3212 3213;; Allow combine to split complex const_int load sequences, using operand 2 3214;; to store the intermediate results. See move_operand for details. 3215(define_split 3216 [(set (match_operand:GPR 0 "register_operand") 3217 (match_operand:GPR 1 "splittable_const_int_operand")) 3218 (clobber (match_operand:GPR 2 "register_operand"))] 3219 "" 3220 [(const_int 0)] 3221{ 3222 mips_move_integer (operands[0], operands[2], INTVAL (operands[1])); 3223 DONE; 3224}) 3225 3226;; Likewise, for symbolic operands. 3227(define_split 3228 [(set (match_operand:P 0 "register_operand") 3229 (match_operand:P 1 "splittable_symbolic_operand")) 3230 (clobber (match_operand:P 2 "register_operand"))] 3231 "" 3232 [(set (match_dup 0) (match_dup 1))] 3233 { operands[1] = mips_split_symbol (operands[2], operands[1]); }) 3234 3235;; 64-bit integer moves 3236 3237;; Unlike most other insns, the move insns can't be split with 3238;; different predicates, because register spilling and other parts of 3239;; the compiler, have memoized the insn number already. 3240 3241(define_expand "movdi" 3242 [(set (match_operand:DI 0 "") 3243 (match_operand:DI 1 ""))] 3244 "" 3245{ 3246 if (mips_legitimize_move (DImode, operands[0], operands[1])) 3247 DONE; 3248}) 3249 3250;; For mips16, we need a special case to handle storing $31 into 3251;; memory, since we don't have a constraint to match $31. This 3252;; instruction can be generated by save_restore_insns. 3253 3254(define_insn "*mov<mode>_ra" 3255 [(set (match_operand:GPR 0 "stack_operand" "=m") 3256 (reg:GPR 31))] 3257 "TARGET_MIPS16" 3258 "<store>\t$31,%0" 3259 [(set_attr "type" "store") 3260 (set_attr "mode" "<MODE>")]) 3261 3262(define_insn "*movdi_32bit" 3263 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m") 3264 (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))] 3265 "!TARGET_64BIT && !TARGET_MIPS16 3266 && (register_operand (operands[0], DImode) 3267 || reg_or_0_operand (operands[1], DImode))" 3268 { return mips_output_move (operands[0], operands[1]); } 3269 [(set_attr "type" "arith,arith,load,store,mthilo,mfhilo,xfer,load,xfer,store") 3270 (set_attr "mode" "DI") 3271 (set_attr "length" "8,16,*,*,8,8,8,*,8,*")]) 3272 3273(define_insn "*movdi_32bit_mips16" 3274 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") 3275 (match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))] 3276 "!TARGET_64BIT && TARGET_MIPS16 3277 && (register_operand (operands[0], DImode) 3278 || register_operand (operands[1], DImode))" 3279 { return mips_output_move (operands[0], operands[1]); } 3280 [(set_attr "type" "arith,arith,arith,arith,arith,load,store,mfhilo") 3281 (set_attr "mode" "DI") 3282 (set_attr "length" "8,8,8,8,12,*,*,8")]) 3283 3284(define_insn "*movdi_64bit" 3285 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m") 3286 (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))] 3287 "TARGET_64BIT && !TARGET_MIPS16 3288 && (register_operand (operands[0], DImode) 3289 || reg_or_0_operand (operands[1], DImode))" 3290 { return mips_output_move (operands[0], operands[1]); } 3291 [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,mthilo,xfer,load,xfer,store") 3292 (set_attr "mode" "DI") 3293 (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,8,*,8,*")]) 3294 3295(define_insn "*movdi_64bit_mips16" 3296 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") 3297 (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,m,d"))] 3298 "TARGET_64BIT && TARGET_MIPS16 3299 && (register_operand (operands[0], DImode) 3300 || register_operand (operands[1], DImode))" 3301 { return mips_output_move (operands[0], operands[1]); } 3302 [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store") 3303 (set_attr "mode" "DI") 3304 (set_attr_alternative "length" 3305 [(const_int 4) 3306 (const_int 4) 3307 (const_int 4) 3308 (if_then_else (match_operand:VOID 1 "m16_uimm8_1") 3309 (const_int 4) 3310 (const_int 8)) 3311 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") 3312 (const_int 8) 3313 (const_int 12)) 3314 (const_string "*") 3315 (const_string "*") 3316 (const_string "*")])]) 3317 3318 3319;; On the mips16, we can split ld $r,N($r) into an add and a load, 3320;; when the original load is a 4 byte instruction but the add and the 3321;; load are 2 2 byte instructions. 3322 3323(define_split 3324 [(set (match_operand:DI 0 "register_operand") 3325 (mem:DI (plus:DI (match_dup 0) 3326 (match_operand:DI 1 "const_int_operand"))))] 3327 "TARGET_64BIT && TARGET_MIPS16 && reload_completed 3328 && !TARGET_DEBUG_D_MODE 3329 && REG_P (operands[0]) 3330 && M16_REG_P (REGNO (operands[0])) 3331 && GET_CODE (operands[1]) == CONST_INT 3332 && ((INTVAL (operands[1]) < 0 3333 && INTVAL (operands[1]) >= -0x10) 3334 || (INTVAL (operands[1]) >= 32 * 8 3335 && INTVAL (operands[1]) <= 31 * 8 + 0x8) 3336 || (INTVAL (operands[1]) >= 0 3337 && INTVAL (operands[1]) < 32 * 8 3338 && (INTVAL (operands[1]) & 7) != 0))" 3339 [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1))) 3340 (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))] 3341{ 3342 HOST_WIDE_INT val = INTVAL (operands[1]); 3343 3344 if (val < 0) 3345 operands[2] = const0_rtx; 3346 else if (val >= 32 * 8) 3347 { 3348 int off = val & 7; 3349 3350 operands[1] = GEN_INT (0x8 + off); 3351 operands[2] = GEN_INT (val - off - 0x8); 3352 } 3353 else 3354 { 3355 int off = val & 7; 3356 3357 operands[1] = GEN_INT (off); 3358 operands[2] = GEN_INT (val - off); 3359 } 3360}) 3361 3362;; 32-bit Integer moves 3363 3364;; Unlike most other insns, the move insns can't be split with 3365;; different predicates, because register spilling and other parts of 3366;; the compiler, have memoized the insn number already. 3367 3368(define_expand "movsi" 3369 [(set (match_operand:SI 0 "") 3370 (match_operand:SI 1 ""))] 3371 "" 3372{ 3373 if (mips_legitimize_move (SImode, operands[0], operands[1])) 3374 DONE; 3375}) 3376 3377;; The difference between these two is whether or not ints are allowed 3378;; in FP registers (off by default, use -mdebugh to enable). 3379 3380(define_insn "*movsi_internal" 3381 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m") 3382 (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))] 3383 "!TARGET_MIPS16 3384 && (register_operand (operands[0], SImode) 3385 || reg_or_0_operand (operands[1], SImode))" 3386 { return mips_output_move (operands[0], operands[1]); } 3387 [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,mfhilo,xfer,load,xfer,store") 3388 (set_attr "mode" "SI") 3389 (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")]) 3390 3391(define_insn "*movsi_mips16" 3392 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m") 3393 (match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d"))] 3394 "TARGET_MIPS16 3395 && (register_operand (operands[0], SImode) 3396 || register_operand (operands[1], SImode))" 3397 { return mips_output_move (operands[0], operands[1]); } 3398 [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store") 3399 (set_attr "mode" "SI") 3400 (set_attr_alternative "length" 3401 [(const_int 4) 3402 (const_int 4) 3403 (const_int 4) 3404 (if_then_else (match_operand:VOID 1 "m16_uimm8_1") 3405 (const_int 4) 3406 (const_int 8)) 3407 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") 3408 (const_int 8) 3409 (const_int 12)) 3410 (const_string "*") 3411 (const_string "*") 3412 (const_string "*")])]) 3413 3414;; On the mips16, we can split lw $r,N($r) into an add and a load, 3415;; when the original load is a 4 byte instruction but the add and the 3416;; load are 2 2 byte instructions. 3417 3418(define_split 3419 [(set (match_operand:SI 0 "register_operand") 3420 (mem:SI (plus:SI (match_dup 0) 3421 (match_operand:SI 1 "const_int_operand"))))] 3422 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3423 && REG_P (operands[0]) 3424 && M16_REG_P (REGNO (operands[0])) 3425 && GET_CODE (operands[1]) == CONST_INT 3426 && ((INTVAL (operands[1]) < 0 3427 && INTVAL (operands[1]) >= -0x80) 3428 || (INTVAL (operands[1]) >= 32 * 4 3429 && INTVAL (operands[1]) <= 31 * 4 + 0x7c) 3430 || (INTVAL (operands[1]) >= 0 3431 && INTVAL (operands[1]) < 32 * 4 3432 && (INTVAL (operands[1]) & 3) != 0))" 3433 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) 3434 (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))] 3435{ 3436 HOST_WIDE_INT val = INTVAL (operands[1]); 3437 3438 if (val < 0) 3439 operands[2] = const0_rtx; 3440 else if (val >= 32 * 4) 3441 { 3442 int off = val & 3; 3443 3444 operands[1] = GEN_INT (0x7c + off); 3445 operands[2] = GEN_INT (val - off - 0x7c); 3446 } 3447 else 3448 { 3449 int off = val & 3; 3450 3451 operands[1] = GEN_INT (off); 3452 operands[2] = GEN_INT (val - off); 3453 } 3454}) 3455 3456;; On the mips16, we can split a load of certain constants into a load 3457;; and an add. This turns a 4 byte instruction into 2 2 byte 3458;; instructions. 3459 3460(define_split 3461 [(set (match_operand:SI 0 "register_operand") 3462 (match_operand:SI 1 "const_int_operand"))] 3463 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3464 && REG_P (operands[0]) 3465 && M16_REG_P (REGNO (operands[0])) 3466 && GET_CODE (operands[1]) == CONST_INT 3467 && INTVAL (operands[1]) >= 0x100 3468 && INTVAL (operands[1]) <= 0xff + 0x7f" 3469 [(set (match_dup 0) (match_dup 1)) 3470 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] 3471{ 3472 int val = INTVAL (operands[1]); 3473 3474 operands[1] = GEN_INT (0xff); 3475 operands[2] = GEN_INT (val - 0xff); 3476}) 3477 3478;; This insn handles moving CCmode values. It's really just a 3479;; slightly simplified copy of movsi_internal2, with additional cases 3480;; to move a condition register to a general register and to move 3481;; between the general registers and the floating point registers. 3482 3483(define_insn "movcc" 3484 [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m") 3485 (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))] 3486 "ISA_HAS_8CC && TARGET_HARD_FLOAT" 3487 { return mips_output_move (operands[0], operands[1]); } 3488 [(set_attr "type" "xfer,arith,load,store,xfer,xfer,fmove,fpload,fpstore") 3489 (set_attr "mode" "SI") 3490 (set_attr "length" "8,4,*,*,4,4,4,*,*")]) 3491 3492;; Reload condition code registers. reload_incc and reload_outcc 3493;; both handle moves from arbitrary operands into condition code 3494;; registers. reload_incc handles the more common case in which 3495;; a source operand is constrained to be in a condition-code 3496;; register, but has not been allocated to one. 3497;; 3498;; Sometimes, such as in movcc, we have a CCmode destination whose 3499;; constraints do not include 'z'. reload_outcc handles the case 3500;; when such an operand is allocated to a condition-code register. 3501;; 3502;; Note that reloads from a condition code register to some 3503;; other location can be done using ordinary moves. Moving 3504;; into a GPR takes a single movcc, moving elsewhere takes 3505;; two. We can leave these cases to the generic reload code. 3506(define_expand "reload_incc" 3507 [(set (match_operand:CC 0 "fcc_reload_operand" "=z") 3508 (match_operand:CC 1 "general_operand" "")) 3509 (clobber (match_operand:TF 2 "register_operand" "=&f"))] 3510 "ISA_HAS_8CC && TARGET_HARD_FLOAT" 3511{ 3512 mips_emit_fcc_reload (operands[0], operands[1], operands[2]); 3513 DONE; 3514}) 3515 3516(define_expand "reload_outcc" 3517 [(set (match_operand:CC 0 "fcc_reload_operand" "=z") 3518 (match_operand:CC 1 "register_operand" "")) 3519 (clobber (match_operand:TF 2 "register_operand" "=&f"))] 3520 "ISA_HAS_8CC && TARGET_HARD_FLOAT" 3521{ 3522 mips_emit_fcc_reload (operands[0], operands[1], operands[2]); 3523 DONE; 3524}) 3525 3526;; MIPS4 supports loading and storing a floating point register from 3527;; the sum of two general registers. We use two versions for each of 3528;; these four instructions: one where the two general registers are 3529;; SImode, and one where they are DImode. This is because general 3530;; registers will be in SImode when they hold 32 bit values, but, 3531;; since the 32 bit values are always sign extended, the [ls][wd]xc1 3532;; instructions will still work correctly. 3533 3534;; ??? Perhaps it would be better to support these instructions by 3535;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since 3536;; these instructions can only be used to load and store floating 3537;; point registers, that would probably cause trouble in reload. 3538 3539(define_insn "*<ANYF:loadx>_<P:mode>" 3540 [(set (match_operand:ANYF 0 "register_operand" "=f") 3541 (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d") 3542 (match_operand:P 2 "register_operand" "d"))))] 3543 "ISA_HAS_FP4" 3544 "<ANYF:loadx>\t%0,%1(%2)" 3545 [(set_attr "type" "fpidxload") 3546 (set_attr "mode" "<ANYF:UNITMODE>")]) 3547 3548(define_insn "*<ANYF:storex>_<P:mode>" 3549 [(set (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d") 3550 (match_operand:P 2 "register_operand" "d"))) 3551 (match_operand:ANYF 0 "register_operand" "f"))] 3552 "ISA_HAS_FP4" 3553 "<ANYF:storex>\t%0,%1(%2)" 3554 [(set_attr "type" "fpidxstore") 3555 (set_attr "mode" "<ANYF:UNITMODE>")]) 3556 3557;; 16-bit Integer moves 3558 3559;; Unlike most other insns, the move insns can't be split with 3560;; different predicates, because register spilling and other parts of 3561;; the compiler, have memoized the insn number already. 3562;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. 3563 3564(define_expand "movhi" 3565 [(set (match_operand:HI 0 "") 3566 (match_operand:HI 1 ""))] 3567 "" 3568{ 3569 if (mips_legitimize_move (HImode, operands[0], operands[1])) 3570 DONE; 3571}) 3572 3573(define_insn "*movhi_internal" 3574 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x") 3575 (match_operand:HI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))] 3576 "!TARGET_MIPS16 3577 && (register_operand (operands[0], HImode) 3578 || reg_or_0_operand (operands[1], HImode))" 3579 "@ 3580 move\t%0,%1 3581 li\t%0,%1 3582 lhu\t%0,%1 3583 sh\t%z1,%0 3584 mfc1\t%0,%1 3585 mtc1\t%1,%0 3586 mov.s\t%0,%1 3587 mt%0\t%1" 3588 [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo") 3589 (set_attr "mode" "HI") 3590 (set_attr "length" "4,4,*,*,4,4,4,4")]) 3591 3592(define_insn "*movhi_mips16" 3593 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") 3594 (match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d"))] 3595 "TARGET_MIPS16 3596 && (register_operand (operands[0], HImode) 3597 || register_operand (operands[1], HImode))" 3598 "@ 3599 move\t%0,%1 3600 move\t%0,%1 3601 move\t%0,%1 3602 li\t%0,%1 3603 # 3604 lhu\t%0,%1 3605 sh\t%1,%0" 3606 [(set_attr "type" "arith,arith,arith,arith,arith,load,store") 3607 (set_attr "mode" "HI") 3608 (set_attr_alternative "length" 3609 [(const_int 4) 3610 (const_int 4) 3611 (const_int 4) 3612 (if_then_else (match_operand:VOID 1 "m16_uimm8_1") 3613 (const_int 4) 3614 (const_int 8)) 3615 (if_then_else (match_operand:VOID 1 "m16_nuimm8_1") 3616 (const_int 8) 3617 (const_int 12)) 3618 (const_string "*") 3619 (const_string "*")])]) 3620 3621 3622;; On the mips16, we can split lh $r,N($r) into an add and a load, 3623;; when the original load is a 4 byte instruction but the add and the 3624;; load are 2 2 byte instructions. 3625 3626(define_split 3627 [(set (match_operand:HI 0 "register_operand") 3628 (mem:HI (plus:SI (match_dup 0) 3629 (match_operand:SI 1 "const_int_operand"))))] 3630 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3631 && REG_P (operands[0]) 3632 && M16_REG_P (REGNO (operands[0])) 3633 && GET_CODE (operands[1]) == CONST_INT 3634 && ((INTVAL (operands[1]) < 0 3635 && INTVAL (operands[1]) >= -0x80) 3636 || (INTVAL (operands[1]) >= 32 * 2 3637 && INTVAL (operands[1]) <= 31 * 2 + 0x7e) 3638 || (INTVAL (operands[1]) >= 0 3639 && INTVAL (operands[1]) < 32 * 2 3640 && (INTVAL (operands[1]) & 1) != 0))" 3641 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) 3642 (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))] 3643{ 3644 HOST_WIDE_INT val = INTVAL (operands[1]); 3645 3646 if (val < 0) 3647 operands[2] = const0_rtx; 3648 else if (val >= 32 * 2) 3649 { 3650 int off = val & 1; 3651 3652 operands[1] = GEN_INT (0x7e + off); 3653 operands[2] = GEN_INT (val - off - 0x7e); 3654 } 3655 else 3656 { 3657 int off = val & 1; 3658 3659 operands[1] = GEN_INT (off); 3660 operands[2] = GEN_INT (val - off); 3661 } 3662}) 3663 3664;; 8-bit Integer moves 3665 3666;; Unlike most other insns, the move insns can't be split with 3667;; different predicates, because register spilling and other parts of 3668;; the compiler, have memoized the insn number already. 3669;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. 3670 3671(define_expand "movqi" 3672 [(set (match_operand:QI 0 "") 3673 (match_operand:QI 1 ""))] 3674 "" 3675{ 3676 if (mips_legitimize_move (QImode, operands[0], operands[1])) 3677 DONE; 3678}) 3679 3680(define_insn "*movqi_internal" 3681 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x") 3682 (match_operand:QI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))] 3683 "!TARGET_MIPS16 3684 && (register_operand (operands[0], QImode) 3685 || reg_or_0_operand (operands[1], QImode))" 3686 "@ 3687 move\t%0,%1 3688 li\t%0,%1 3689 lbu\t%0,%1 3690 sb\t%z1,%0 3691 mfc1\t%0,%1 3692 mtc1\t%1,%0 3693 mov.s\t%0,%1 3694 mt%0\t%1" 3695 [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo") 3696 (set_attr "mode" "QI") 3697 (set_attr "length" "4,4,*,*,4,4,4,4")]) 3698 3699(define_insn "*movqi_mips16" 3700 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m") 3701 (match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d"))] 3702 "TARGET_MIPS16 3703 && (register_operand (operands[0], QImode) 3704 || register_operand (operands[1], QImode))" 3705 "@ 3706 move\t%0,%1 3707 move\t%0,%1 3708 move\t%0,%1 3709 li\t%0,%1 3710 # 3711 lbu\t%0,%1 3712 sb\t%1,%0" 3713 [(set_attr "type" "arith,arith,arith,arith,arith,load,store") 3714 (set_attr "mode" "QI") 3715 (set_attr "length" "4,4,4,4,8,*,*")]) 3716 3717;; On the mips16, we can split lb $r,N($r) into an add and a load, 3718;; when the original load is a 4 byte instruction but the add and the 3719;; load are 2 2 byte instructions. 3720 3721(define_split 3722 [(set (match_operand:QI 0 "register_operand") 3723 (mem:QI (plus:SI (match_dup 0) 3724 (match_operand:SI 1 "const_int_operand"))))] 3725 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 3726 && REG_P (operands[0]) 3727 && M16_REG_P (REGNO (operands[0])) 3728 && GET_CODE (operands[1]) == CONST_INT 3729 && ((INTVAL (operands[1]) < 0 3730 && INTVAL (operands[1]) >= -0x80) 3731 || (INTVAL (operands[1]) >= 32 3732 && INTVAL (operands[1]) <= 31 + 0x7f))" 3733 [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) 3734 (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))] 3735{ 3736 HOST_WIDE_INT val = INTVAL (operands[1]); 3737 3738 if (val < 0) 3739 operands[2] = const0_rtx; 3740 else 3741 { 3742 operands[1] = GEN_INT (0x7f); 3743 operands[2] = GEN_INT (val - 0x7f); 3744 } 3745}) 3746 3747;; 32-bit floating point moves 3748 3749(define_expand "movsf" 3750 [(set (match_operand:SF 0 "") 3751 (match_operand:SF 1 ""))] 3752 "" 3753{ 3754 if (mips_legitimize_move (SFmode, operands[0], operands[1])) 3755 DONE; 3756}) 3757 3758(define_insn "*movsf_hardfloat" 3759 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3760 (match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))] 3761 "TARGET_HARD_FLOAT 3762 && (register_operand (operands[0], SFmode) 3763 || reg_or_0_operand (operands[1], SFmode))" 3764 { return mips_output_move (operands[0], operands[1]); } 3765 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3766 (set_attr "mode" "SF") 3767 (set_attr "length" "4,4,*,*,*,4,4,4,*,*")]) 3768 3769(define_insn "*movsf_softfloat" 3770 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m") 3771 (match_operand:SF 1 "move_operand" "Gd,m,d"))] 3772 "TARGET_SOFT_FLOAT && !TARGET_MIPS16 3773 && (register_operand (operands[0], SFmode) 3774 || reg_or_0_operand (operands[1], SFmode))" 3775 { return mips_output_move (operands[0], operands[1]); } 3776 [(set_attr "type" "arith,load,store") 3777 (set_attr "mode" "SF") 3778 (set_attr "length" "4,*,*")]) 3779 3780(define_insn "*movsf_mips16" 3781 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,m") 3782 (match_operand:SF 1 "move_operand" "d,d,y,m,d"))] 3783 "TARGET_MIPS16 3784 && (register_operand (operands[0], SFmode) 3785 || register_operand (operands[1], SFmode))" 3786 { return mips_output_move (operands[0], operands[1]); } 3787 [(set_attr "type" "arith,arith,arith,load,store") 3788 (set_attr "mode" "SF") 3789 (set_attr "length" "4,4,4,*,*")]) 3790 3791 3792;; 64-bit floating point moves 3793 3794(define_expand "movdf" 3795 [(set (match_operand:DF 0 "") 3796 (match_operand:DF 1 ""))] 3797 "" 3798{ 3799 if (mips_legitimize_move (DFmode, operands[0], operands[1])) 3800 DONE; 3801}) 3802 3803(define_insn "*movdf_hardfloat_64bit" 3804 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3805 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))] 3806 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_64BIT 3807 && (register_operand (operands[0], DFmode) 3808 || reg_or_0_operand (operands[1], DFmode))" 3809 { return mips_output_move (operands[0], operands[1]); } 3810 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3811 (set_attr "mode" "DF") 3812 (set_attr "length" "4,4,*,*,*,4,4,4,*,*")]) 3813 3814(define_insn "*movdf_hardfloat_32bit" 3815 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3816 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))] 3817 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT 3818 && (register_operand (operands[0], DFmode) 3819 || reg_or_0_operand (operands[1], DFmode))" 3820 { return mips_output_move (operands[0], operands[1]); } 3821 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3822 (set_attr "mode" "DF") 3823 (set_attr "length" "4,8,*,*,*,8,8,8,*,*")]) 3824 3825(define_insn "*movdf_softfloat" 3826 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,m,d,f,f") 3827 (match_operand:DF 1 "move_operand" "dG,m,dG,f,d,f"))] 3828 "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16 3829 && (register_operand (operands[0], DFmode) 3830 || reg_or_0_operand (operands[1], DFmode))" 3831 { return mips_output_move (operands[0], operands[1]); } 3832 [(set_attr "type" "arith,load,store,xfer,xfer,fmove") 3833 (set_attr "mode" "DF") 3834 (set_attr "length" "8,*,*,4,4,4")]) 3835 3836(define_insn "*movdf_mips16" 3837 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,m") 3838 (match_operand:DF 1 "move_operand" "d,d,y,m,d"))] 3839 "TARGET_MIPS16 3840 && (register_operand (operands[0], DFmode) 3841 || register_operand (operands[1], DFmode))" 3842 { return mips_output_move (operands[0], operands[1]); } 3843 [(set_attr "type" "arith,arith,arith,load,store") 3844 (set_attr "mode" "DF") 3845 (set_attr "length" "8,8,8,*,*")]) 3846 3847(define_split 3848 [(set (match_operand:DI 0 "nonimmediate_operand") 3849 (match_operand:DI 1 "move_operand"))] 3850 "reload_completed && !TARGET_64BIT 3851 && mips_split_64bit_move_p (operands[0], operands[1])" 3852 [(const_int 0)] 3853{ 3854 mips_split_64bit_move (operands[0], operands[1]); 3855 DONE; 3856}) 3857 3858(define_split 3859 [(set (match_operand:DF 0 "nonimmediate_operand") 3860 (match_operand:DF 1 "move_operand"))] 3861 "reload_completed && !TARGET_64BIT 3862 && mips_split_64bit_move_p (operands[0], operands[1])" 3863 [(const_int 0)] 3864{ 3865 mips_split_64bit_move (operands[0], operands[1]); 3866 DONE; 3867}) 3868 3869;; When generating mips16 code, split moves of negative constants into 3870;; a positive "li" followed by a negation. 3871(define_split 3872 [(set (match_operand 0 "register_operand") 3873 (match_operand 1 "const_int_operand"))] 3874 "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0" 3875 [(set (match_dup 2) 3876 (match_dup 3)) 3877 (set (match_dup 2) 3878 (neg:SI (match_dup 2)))] 3879{ 3880 operands[2] = gen_lowpart (SImode, operands[0]); 3881 operands[3] = GEN_INT (-INTVAL (operands[1])); 3882}) 3883 3884;; 64-bit paired-single floating point moves 3885 3886(define_expand "movv2sf" 3887 [(set (match_operand:V2SF 0) 3888 (match_operand:V2SF 1))] 3889 "TARGET_PAIRED_SINGLE_FLOAT" 3890{ 3891 if (mips_legitimize_move (V2SFmode, operands[0], operands[1])) 3892 DONE; 3893}) 3894 3895(define_insn "movv2sf_hardfloat_64bit" 3896 [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m") 3897 (match_operand:V2SF 1 "move_operand" "f,YG,m,f,YG,*d,*f,*d*YG,*m,*d"))] 3898 "TARGET_PAIRED_SINGLE_FLOAT 3899 && TARGET_64BIT 3900 && (register_operand (operands[0], V2SFmode) 3901 || reg_or_0_operand (operands[1], V2SFmode))" 3902 { return mips_output_move (operands[0], operands[1]); } 3903 [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store") 3904 (set_attr "mode" "SF") 3905 (set_attr "length" "4,4,*,*,*,4,4,4,*,*")]) 3906 3907;; The HI and LO registers are not truly independent. If we move an mthi 3908;; instruction before an mflo instruction, it will make the result of the 3909;; mflo unpredictable. The same goes for mtlo and mfhi. 3910;; 3911;; We cope with this by making the mflo and mfhi patterns use both HI and LO. 3912;; Operand 1 is the register we want, operand 2 is the other one. 3913;; 3914;; When generating VR4120 or VR4130 code, we use macc{,hi} and 3915;; dmacc{,hi} instead of mfhi and mflo. This avoids both the normal 3916;; MIPS III hi/lo hazards and the errata related to -mfix-vr4130. 3917 3918(define_expand "mfhilo_<mode>" 3919 [(set (match_operand:GPR 0 "register_operand") 3920 (unspec:GPR [(match_operand:GPR 1 "register_operand") 3921 (match_operand:GPR 2 "register_operand")] 3922 UNSPEC_MFHILO))]) 3923 3924(define_insn "*mfhilo_<mode>" 3925 [(set (match_operand:GPR 0 "register_operand" "=d,d") 3926 (unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l") 3927 (match_operand:GPR 2 "register_operand" "l,h")] 3928 UNSPEC_MFHILO))] 3929 "!ISA_HAS_MACCHI" 3930 "mf%1\t%0" 3931 [(set_attr "type" "mfhilo") 3932 (set_attr "mode" "<MODE>")]) 3933 3934(define_insn "*mfhilo_<mode>_macc" 3935 [(set (match_operand:GPR 0 "register_operand" "=d,d") 3936 (unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l") 3937 (match_operand:GPR 2 "register_operand" "l,h")] 3938 UNSPEC_MFHILO))] 3939 "ISA_HAS_MACCHI" 3940{ 3941 if (REGNO (operands[1]) == HI_REGNUM) 3942 return "<d>macchi\t%0,%.,%."; 3943 else 3944 return "<d>macc\t%0,%.,%."; 3945} 3946 [(set_attr "type" "mfhilo") 3947 (set_attr "mode" "<MODE>")]) 3948 3949;; Patterns for loading or storing part of a paired floating point 3950;; register. We need them because odd-numbered floating-point registers 3951;; are not fully independent: see mips_split_64bit_move. 3952 3953;; Load the low word of operand 0 with operand 1. 3954(define_insn "load_df_low" 3955 [(set (match_operand:DF 0 "register_operand" "=f,f") 3956 (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")] 3957 UNSPEC_LOAD_DF_LOW))] 3958 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" 3959{ 3960 operands[0] = mips_subword (operands[0], 0); 3961 return mips_output_move (operands[0], operands[1]); 3962} 3963 [(set_attr "type" "xfer,fpload") 3964 (set_attr "mode" "SF")]) 3965 3966;; Load the high word of operand 0 from operand 1, preserving the value 3967;; in the low word. 3968(define_insn "load_df_high" 3969 [(set (match_operand:DF 0 "register_operand" "=f,f") 3970 (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m") 3971 (match_operand:DF 2 "register_operand" "0,0")] 3972 UNSPEC_LOAD_DF_HIGH))] 3973 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" 3974{ 3975 operands[0] = mips_subword (operands[0], 1); 3976 return mips_output_move (operands[0], operands[1]); 3977} 3978 [(set_attr "type" "xfer,fpload") 3979 (set_attr "mode" "SF")]) 3980 3981;; Store the high word of operand 1 in operand 0. The corresponding 3982;; low-word move is done in the normal way. 3983(define_insn "store_df_high" 3984 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m") 3985 (unspec:SI [(match_operand:DF 1 "register_operand" "f,f")] 3986 UNSPEC_STORE_DF_HIGH))] 3987 "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT" 3988{ 3989 operands[1] = mips_subword (operands[1], 1); 3990 return mips_output_move (operands[0], operands[1]); 3991} 3992 [(set_attr "type" "xfer,fpstore") 3993 (set_attr "mode" "SF")]) 3994 3995;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset 3996;; of _gp from the start of this function. Operand 1 is the incoming 3997;; function address. 3998(define_insn_and_split "loadgp" 3999 [(unspec_volatile [(match_operand 0 "" "") 4000 (match_operand 1 "register_operand" "")] UNSPEC_LOADGP)] 4001 "mips_current_loadgp_style () == LOADGP_NEWABI" 4002 "#" 4003 "" 4004 [(set (match_dup 2) (match_dup 3)) 4005 (set (match_dup 2) (match_dup 4)) 4006 (set (match_dup 2) (match_dup 5))] 4007{ 4008 operands[2] = pic_offset_table_rtx; 4009 operands[3] = gen_rtx_HIGH (Pmode, operands[0]); 4010 operands[4] = gen_rtx_PLUS (Pmode, operands[2], operands[1]); 4011 operands[5] = gen_rtx_LO_SUM (Pmode, operands[2], operands[0]); 4012} 4013 [(set_attr "length" "12")]) 4014 4015;; Likewise, for -mno-shared code. Operand 0 is the __gnu_local_gp symbol. 4016(define_insn_and_split "loadgp_noshared" 4017 [(unspec_volatile [(match_operand 0 "" "")] UNSPEC_LOADGP)] 4018 "mips_current_loadgp_style () == LOADGP_ABSOLUTE" 4019 "#" 4020 "" 4021 [(const_int 0)] 4022{ 4023 emit_move_insn (pic_offset_table_rtx, operands[0]); 4024 DONE; 4025} 4026 [(set_attr "length" "8")]) 4027 4028;; The use of gp is hidden when not using explicit relocations. 4029;; This blockage instruction prevents the gp load from being 4030;; scheduled after an implicit use of gp. It also prevents 4031;; the load from being deleted as dead. 4032(define_insn "loadgp_blockage" 4033 [(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)] 4034 "" 4035 "" 4036 [(set_attr "type" "unknown") 4037 (set_attr "mode" "none") 4038 (set_attr "length" "0")]) 4039 4040;; Emit a .cprestore directive, which normally expands to a single store 4041;; instruction. Note that we continue to use .cprestore for explicit reloc 4042;; code so that jals inside inline asms will work correctly. 4043(define_insn "cprestore" 4044 [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")] 4045 UNSPEC_CPRESTORE)] 4046 "" 4047{ 4048 if (set_nomacro && which_alternative == 1) 4049 return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro"; 4050 else 4051 return ".cprestore\t%0"; 4052} 4053 [(set_attr "type" "store") 4054 (set_attr "length" "4,12")]) 4055 4056;; Block moves, see mips.c for more details. 4057;; Argument 0 is the destination 4058;; Argument 1 is the source 4059;; Argument 2 is the length 4060;; Argument 3 is the alignment 4061 4062(define_expand "movmemsi" 4063 [(parallel [(set (match_operand:BLK 0 "general_operand") 4064 (match_operand:BLK 1 "general_operand")) 4065 (use (match_operand:SI 2 "")) 4066 (use (match_operand:SI 3 "const_int_operand"))])] 4067 "!TARGET_MIPS16 && !TARGET_MEMCPY" 4068{ 4069 if (mips_expand_block_move (operands[0], operands[1], operands[2])) 4070 DONE; 4071 else 4072 FAIL; 4073}) 4074 4075;; 4076;; .................... 4077;; 4078;; SHIFTS 4079;; 4080;; .................... 4081 4082(define_expand "<optab><mode>3" 4083 [(set (match_operand:GPR 0 "register_operand") 4084 (any_shift:GPR (match_operand:GPR 1 "register_operand") 4085 (match_operand:SI 2 "arith_operand")))] 4086 "" 4087{ 4088 /* On the mips16, a shift of more than 8 is a four byte instruction, 4089 so, for a shift between 8 and 16, it is just as fast to do two 4090 shifts of 8 or less. If there is a lot of shifting going on, we 4091 may win in CSE. Otherwise combine will put the shifts back 4092 together again. This can be called by function_arg, so we must 4093 be careful not to allocate a new register if we've reached the 4094 reload pass. */ 4095 if (TARGET_MIPS16 4096 && optimize 4097 && GET_CODE (operands[2]) == CONST_INT 4098 && INTVAL (operands[2]) > 8 4099 && INTVAL (operands[2]) <= 16 4100 && !reload_in_progress 4101 && !reload_completed) 4102 { 4103 rtx temp = gen_reg_rtx (<MODE>mode); 4104 4105 emit_insn (gen_<optab><mode>3 (temp, operands[1], GEN_INT (8))); 4106 emit_insn (gen_<optab><mode>3 (operands[0], temp, 4107 GEN_INT (INTVAL (operands[2]) - 8))); 4108 DONE; 4109 } 4110}) 4111 4112(define_insn "*<optab><mode>3" 4113 [(set (match_operand:GPR 0 "register_operand" "=d") 4114 (any_shift:GPR (match_operand:GPR 1 "register_operand" "d") 4115 (match_operand:SI 2 "arith_operand" "dI")))] 4116 "!TARGET_MIPS16" 4117{ 4118 if (GET_CODE (operands[2]) == CONST_INT) 4119 operands[2] = GEN_INT (INTVAL (operands[2]) 4120 & (GET_MODE_BITSIZE (<MODE>mode) - 1)); 4121 4122 return "<d><insn>\t%0,%1,%2"; 4123} 4124 [(set_attr "type" "shift") 4125 (set_attr "mode" "<MODE>")]) 4126 4127(define_insn "*<optab>si3_extend" 4128 [(set (match_operand:DI 0 "register_operand" "=d") 4129 (sign_extend:DI 4130 (any_shift:SI (match_operand:SI 1 "register_operand" "d") 4131 (match_operand:SI 2 "arith_operand" "dI"))))] 4132 "TARGET_64BIT && !TARGET_MIPS16" 4133{ 4134 if (GET_CODE (operands[2]) == CONST_INT) 4135 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 4136 4137 return "<insn>\t%0,%1,%2"; 4138} 4139 [(set_attr "type" "shift") 4140 (set_attr "mode" "SI")]) 4141 4142(define_insn "*<optab>si3_mips16" 4143 [(set (match_operand:SI 0 "register_operand" "=d,d") 4144 (any_shift:SI (match_operand:SI 1 "register_operand" "0,d") 4145 (match_operand:SI 2 "arith_operand" "d,I")))] 4146 "TARGET_MIPS16" 4147{ 4148 if (which_alternative == 0) 4149 return "<insn>\t%0,%2"; 4150 4151 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 4152 return "<insn>\t%0,%1,%2"; 4153} 4154 [(set_attr "type" "shift") 4155 (set_attr "mode" "SI") 4156 (set_attr_alternative "length" 4157 [(const_int 4) 4158 (if_then_else (match_operand 2 "m16_uimm3_b") 4159 (const_int 4) 4160 (const_int 8))])]) 4161 4162;; We need separate DImode MIPS16 patterns because of the irregularity 4163;; of right shifts. 4164(define_insn "*ashldi3_mips16" 4165 [(set (match_operand:DI 0 "register_operand" "=d,d") 4166 (ashift:DI (match_operand:DI 1 "register_operand" "0,d") 4167 (match_operand:SI 2 "arith_operand" "d,I")))] 4168 "TARGET_64BIT && TARGET_MIPS16" 4169{ 4170 if (which_alternative == 0) 4171 return "dsll\t%0,%2"; 4172 4173 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); 4174 return "dsll\t%0,%1,%2"; 4175} 4176 [(set_attr "type" "shift") 4177 (set_attr "mode" "DI") 4178 (set_attr_alternative "length" 4179 [(const_int 4) 4180 (if_then_else (match_operand 2 "m16_uimm3_b") 4181 (const_int 4) 4182 (const_int 8))])]) 4183 4184(define_insn "*ashrdi3_mips16" 4185 [(set (match_operand:DI 0 "register_operand" "=d,d") 4186 (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0") 4187 (match_operand:SI 2 "arith_operand" "d,I")))] 4188 "TARGET_64BIT && TARGET_MIPS16" 4189{ 4190 if (GET_CODE (operands[2]) == CONST_INT) 4191 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); 4192 4193 return "dsra\t%0,%2"; 4194} 4195 [(set_attr "type" "shift") 4196 (set_attr "mode" "DI") 4197 (set_attr_alternative "length" 4198 [(const_int 4) 4199 (if_then_else (match_operand 2 "m16_uimm3_b") 4200 (const_int 4) 4201 (const_int 8))])]) 4202 4203(define_insn "*lshrdi3_mips16" 4204 [(set (match_operand:DI 0 "register_operand" "=d,d") 4205 (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0") 4206 (match_operand:SI 2 "arith_operand" "d,I")))] 4207 "TARGET_64BIT && TARGET_MIPS16" 4208{ 4209 if (GET_CODE (operands[2]) == CONST_INT) 4210 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f); 4211 4212 return "dsrl\t%0,%2"; 4213} 4214 [(set_attr "type" "shift") 4215 (set_attr "mode" "DI") 4216 (set_attr_alternative "length" 4217 [(const_int 4) 4218 (if_then_else (match_operand 2 "m16_uimm3_b") 4219 (const_int 4) 4220 (const_int 8))])]) 4221 4222;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts. 4223 4224(define_split 4225 [(set (match_operand:GPR 0 "register_operand") 4226 (any_shift:GPR (match_operand:GPR 1 "register_operand") 4227 (match_operand:GPR 2 "const_int_operand")))] 4228 "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE 4229 && GET_CODE (operands[2]) == CONST_INT 4230 && INTVAL (operands[2]) > 8 4231 && INTVAL (operands[2]) <= 16" 4232 [(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8))) 4233 (set (match_dup 0) (any_shift:GPR (match_dup 0) (match_dup 2)))] 4234 { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) 4235 4236;; If we load a byte on the mips16 as a bitfield, the resulting 4237;; sequence of instructions is too complicated for combine, because it 4238;; involves four instructions: a load, a shift, a constant load into a 4239;; register, and an and (the key problem here is that the mips16 does 4240;; not have and immediate). We recognize a shift of a load in order 4241;; to make it simple enough for combine to understand. 4242;; 4243;; The length here is the worst case: the length of the split version 4244;; will be more accurate. 4245(define_insn_and_split "" 4246 [(set (match_operand:SI 0 "register_operand" "=d") 4247 (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") 4248 (match_operand:SI 2 "immediate_operand" "I")))] 4249 "TARGET_MIPS16" 4250 "#" 4251 "" 4252 [(set (match_dup 0) (match_dup 1)) 4253 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))] 4254 "" 4255 [(set_attr "type" "load") 4256 (set_attr "mode" "SI") 4257 (set_attr "length" "16")]) 4258 4259(define_insn "rotr<mode>3" 4260 [(set (match_operand:GPR 0 "register_operand" "=d") 4261 (rotatert:GPR (match_operand:GPR 1 "register_operand" "d") 4262 (match_operand:SI 2 "arith_operand" "dI")))] 4263 "ISA_HAS_ROTR_<MODE>" 4264{ 4265 if (GET_CODE (operands[2]) == CONST_INT) 4266 gcc_assert (INTVAL (operands[2]) >= 0 4267 && INTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)); 4268 4269 return "<d>ror\t%0,%1,%2"; 4270} 4271 [(set_attr "type" "shift") 4272 (set_attr "mode" "<MODE>")]) 4273 4274;; 4275;; .................... 4276;; 4277;; COMPARISONS 4278;; 4279;; .................... 4280 4281;; Flow here is rather complex: 4282;; 4283;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments 4284;; into cmp_operands[] but generates no RTL. 4285;; 4286;; 2) The appropriate branch define_expand is called, which then 4287;; creates the appropriate RTL for the comparison and branch. 4288;; Different CC modes are used, based on what type of branch is 4289;; done, so that we can constrain things appropriately. There 4290;; are assumptions in the rest of GCC that break if we fold the 4291;; operands into the branches for integer operations, and use cc0 4292;; for floating point, so we use the fp status register instead. 4293;; If needed, an appropriate temporary is created to hold the 4294;; of the integer compare. 4295 4296(define_expand "cmp<mode>" 4297 [(set (cc0) 4298 (compare:CC (match_operand:GPR 0 "register_operand") 4299 (match_operand:GPR 1 "nonmemory_operand")))] 4300 "" 4301{ 4302 cmp_operands[0] = operands[0]; 4303 cmp_operands[1] = operands[1]; 4304 DONE; 4305}) 4306 4307(define_expand "cmp<mode>" 4308 [(set (cc0) 4309 (compare:CC (match_operand:SCALARF 0 "register_operand") 4310 (match_operand:SCALARF 1 "register_operand")))] 4311 "" 4312{ 4313 cmp_operands[0] = operands[0]; 4314 cmp_operands[1] = operands[1]; 4315 DONE; 4316}) 4317 4318;; 4319;; .................... 4320;; 4321;; CONDITIONAL BRANCHES 4322;; 4323;; .................... 4324 4325;; Conditional branches on floating-point equality tests. 4326 4327(define_insn "*branch_fp" 4328 [(set (pc) 4329 (if_then_else 4330 (match_operator 0 "equality_operator" 4331 [(match_operand:CC 2 "register_operand" "z") 4332 (const_int 0)]) 4333 (label_ref (match_operand 1 "" "")) 4334 (pc)))] 4335 "TARGET_HARD_FLOAT" 4336{ 4337 return mips_output_conditional_branch (insn, operands, 4338 MIPS_BRANCH ("b%F0", "%Z2%1"), 4339 MIPS_BRANCH ("b%W0", "%Z2%1")); 4340} 4341 [(set_attr "type" "branch") 4342 (set_attr "mode" "none")]) 4343 4344(define_insn "*branch_fp_inverted" 4345 [(set (pc) 4346 (if_then_else 4347 (match_operator 0 "equality_operator" 4348 [(match_operand:CC 2 "register_operand" "z") 4349 (const_int 0)]) 4350 (pc) 4351 (label_ref (match_operand 1 "" ""))))] 4352 "TARGET_HARD_FLOAT" 4353{ 4354 return mips_output_conditional_branch (insn, operands, 4355 MIPS_BRANCH ("b%W0", "%Z2%1"), 4356 MIPS_BRANCH ("b%F0", "%Z2%1")); 4357} 4358 [(set_attr "type" "branch") 4359 (set_attr "mode" "none")]) 4360 4361;; Conditional branches on ordered comparisons with zero. 4362 4363(define_insn "*branch_order<mode>" 4364 [(set (pc) 4365 (if_then_else 4366 (match_operator 0 "order_operator" 4367 [(match_operand:GPR 2 "register_operand" "d") 4368 (const_int 0)]) 4369 (label_ref (match_operand 1 "" "")) 4370 (pc)))] 4371 "!TARGET_MIPS16" 4372 { return mips_output_order_conditional_branch (insn, operands, false); } 4373 [(set_attr "type" "branch") 4374 (set_attr "mode" "none")]) 4375 4376(define_insn "*branch_order<mode>_inverted" 4377 [(set (pc) 4378 (if_then_else 4379 (match_operator 0 "order_operator" 4380 [(match_operand:GPR 2 "register_operand" "d") 4381 (const_int 0)]) 4382 (pc) 4383 (label_ref (match_operand 1 "" ""))))] 4384 "!TARGET_MIPS16" 4385 { return mips_output_order_conditional_branch (insn, operands, true); } 4386 [(set_attr "type" "branch") 4387 (set_attr "mode" "none")]) 4388 4389;; Conditional branch on equality comparison. 4390 4391(define_insn "*branch_equality<mode>" 4392 [(set (pc) 4393 (if_then_else 4394 (match_operator 0 "equality_operator" 4395 [(match_operand:GPR 2 "register_operand" "d") 4396 (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) 4397 (label_ref (match_operand 1 "" "")) 4398 (pc)))] 4399 "!TARGET_MIPS16" 4400{ 4401 return mips_output_conditional_branch (insn, operands, 4402 MIPS_BRANCH ("b%C0", "%2,%z3,%1"), 4403 MIPS_BRANCH ("b%N0", "%2,%z3,%1")); 4404} 4405 [(set_attr "type" "branch") 4406 (set_attr "mode" "none")]) 4407 4408(define_insn "*branch_equality<mode>_inverted" 4409 [(set (pc) 4410 (if_then_else 4411 (match_operator 0 "equality_operator" 4412 [(match_operand:GPR 2 "register_operand" "d") 4413 (match_operand:GPR 3 "reg_or_0_operand" "dJ")]) 4414 (pc) 4415 (label_ref (match_operand 1 "" ""))))] 4416 "!TARGET_MIPS16" 4417{ 4418 return mips_output_conditional_branch (insn, operands, 4419 MIPS_BRANCH ("b%N0", "%2,%z3,%1"), 4420 MIPS_BRANCH ("b%C0", "%2,%z3,%1")); 4421} 4422 [(set_attr "type" "branch") 4423 (set_attr "mode" "none")]) 4424 4425;; MIPS16 branches 4426 4427(define_insn "*branch_equality<mode>_mips16" 4428 [(set (pc) 4429 (if_then_else 4430 (match_operator 0 "equality_operator" 4431 [(match_operand:GPR 1 "register_operand" "d,t") 4432 (const_int 0)]) 4433 (match_operand 2 "pc_or_label_operand" "") 4434 (match_operand 3 "pc_or_label_operand" "")))] 4435 "TARGET_MIPS16" 4436{ 4437 if (operands[2] != pc_rtx) 4438 { 4439 if (which_alternative == 0) 4440 return "b%C0z\t%1,%2"; 4441 else 4442 return "bt%C0z\t%2"; 4443 } 4444 else 4445 { 4446 if (which_alternative == 0) 4447 return "b%N0z\t%1,%3"; 4448 else 4449 return "bt%N0z\t%3"; 4450 } 4451} 4452 [(set_attr "type" "branch") 4453 (set_attr "mode" "none") 4454 (set_attr "length" "8")]) 4455 4456(define_expand "b<code>" 4457 [(set (pc) 4458 (if_then_else (any_cond:CC (cc0) 4459 (const_int 0)) 4460 (label_ref (match_operand 0 "")) 4461 (pc)))] 4462 "" 4463{ 4464 gen_conditional_branch (operands, <CODE>); 4465 DONE; 4466}) 4467 4468;; Used to implement built-in functions. 4469(define_expand "condjump" 4470 [(set (pc) 4471 (if_then_else (match_operand 0) 4472 (label_ref (match_operand 1)) 4473 (pc)))]) 4474 4475;; 4476;; .................... 4477;; 4478;; SETTING A REGISTER FROM A COMPARISON 4479;; 4480;; .................... 4481 4482(define_expand "seq" 4483 [(set (match_operand:SI 0 "register_operand") 4484 (eq:SI (match_dup 1) 4485 (match_dup 2)))] 4486 "" 4487 { if (mips_emit_scc (EQ, operands[0])) DONE; else FAIL; }) 4488 4489(define_insn "*seq_<mode>" 4490 [(set (match_operand:GPR 0 "register_operand" "=d") 4491 (eq:GPR (match_operand:GPR 1 "register_operand" "d") 4492 (const_int 0)))] 4493 "!TARGET_MIPS16" 4494 "sltu\t%0,%1,1" 4495 [(set_attr "type" "slt") 4496 (set_attr "mode" "<MODE>")]) 4497 4498(define_insn "*seq_<mode>_mips16" 4499 [(set (match_operand:GPR 0 "register_operand" "=t") 4500 (eq:GPR (match_operand:GPR 1 "register_operand" "d") 4501 (const_int 0)))] 4502 "TARGET_MIPS16" 4503 "sltu\t%1,1" 4504 [(set_attr "type" "slt") 4505 (set_attr "mode" "<MODE>")]) 4506 4507;; "sne" uses sltu instructions in which the first operand is $0. 4508;; This isn't possible in mips16 code. 4509 4510(define_expand "sne" 4511 [(set (match_operand:SI 0 "register_operand") 4512 (ne:SI (match_dup 1) 4513 (match_dup 2)))] 4514 "!TARGET_MIPS16" 4515 { if (mips_emit_scc (NE, operands[0])) DONE; else FAIL; }) 4516 4517(define_insn "*sne_<mode>" 4518 [(set (match_operand:GPR 0 "register_operand" "=d") 4519 (ne:GPR (match_operand:GPR 1 "register_operand" "d") 4520 (const_int 0)))] 4521 "!TARGET_MIPS16" 4522 "sltu\t%0,%.,%1" 4523 [(set_attr "type" "slt") 4524 (set_attr "mode" "<MODE>")]) 4525 4526(define_expand "sgt" 4527 [(set (match_operand:SI 0 "register_operand") 4528 (gt:SI (match_dup 1) 4529 (match_dup 2)))] 4530 "" 4531 { if (mips_emit_scc (GT, operands[0])) DONE; else FAIL; }) 4532 4533(define_insn "*sgt_<mode>" 4534 [(set (match_operand:GPR 0 "register_operand" "=d") 4535 (gt:GPR (match_operand:GPR 1 "register_operand" "d") 4536 (match_operand:GPR 2 "reg_or_0_operand" "dJ")))] 4537 "!TARGET_MIPS16" 4538 "slt\t%0,%z2,%1" 4539 [(set_attr "type" "slt") 4540 (set_attr "mode" "<MODE>")]) 4541 4542(define_insn "*sgt_<mode>_mips16" 4543 [(set (match_operand:GPR 0 "register_operand" "=t") 4544 (gt:GPR (match_operand:GPR 1 "register_operand" "d") 4545 (match_operand:GPR 2 "register_operand" "d")))] 4546 "TARGET_MIPS16" 4547 "slt\t%2,%1" 4548 [(set_attr "type" "slt") 4549 (set_attr "mode" "<MODE>")]) 4550 4551(define_expand "sge" 4552 [(set (match_operand:SI 0 "register_operand") 4553 (ge:SI (match_dup 1) 4554 (match_dup 2)))] 4555 "" 4556 { if (mips_emit_scc (GE, operands[0])) DONE; else FAIL; }) 4557 4558(define_insn "*sge_<mode>" 4559 [(set (match_operand:GPR 0 "register_operand" "=d") 4560 (ge:GPR (match_operand:GPR 1 "register_operand" "d") 4561 (const_int 1)))] 4562 "!TARGET_MIPS16" 4563 "slt\t%0,%.,%1" 4564 [(set_attr "type" "slt") 4565 (set_attr "mode" "<MODE>")]) 4566 4567(define_expand "slt" 4568 [(set (match_operand:SI 0 "register_operand") 4569 (lt:SI (match_dup 1) 4570 (match_dup 2)))] 4571 "" 4572 { if (mips_emit_scc (LT, operands[0])) DONE; else FAIL; }) 4573 4574(define_insn "*slt_<mode>" 4575 [(set (match_operand:GPR 0 "register_operand" "=d") 4576 (lt:GPR (match_operand:GPR 1 "register_operand" "d") 4577 (match_operand:GPR 2 "arith_operand" "dI")))] 4578 "!TARGET_MIPS16" 4579 "slt\t%0,%1,%2" 4580 [(set_attr "type" "slt") 4581 (set_attr "mode" "<MODE>")]) 4582 4583(define_insn "*slt_<mode>_mips16" 4584 [(set (match_operand:GPR 0 "register_operand" "=t,t") 4585 (lt:GPR (match_operand:GPR 1 "register_operand" "d,d") 4586 (match_operand:GPR 2 "arith_operand" "d,I")))] 4587 "TARGET_MIPS16" 4588 "slt\t%1,%2" 4589 [(set_attr "type" "slt") 4590 (set_attr "mode" "<MODE>") 4591 (set_attr_alternative "length" 4592 [(const_int 4) 4593 (if_then_else (match_operand 2 "m16_uimm8_1") 4594 (const_int 4) 4595 (const_int 8))])]) 4596 4597(define_expand "sle" 4598 [(set (match_operand:SI 0 "register_operand") 4599 (le:SI (match_dup 1) 4600 (match_dup 2)))] 4601 "" 4602 { if (mips_emit_scc (LE, operands[0])) DONE; else FAIL; }) 4603 4604(define_insn "*sle_<mode>" 4605 [(set (match_operand:GPR 0 "register_operand" "=d") 4606 (le:GPR (match_operand:GPR 1 "register_operand" "d") 4607 (match_operand:GPR 2 "sle_operand" "")))] 4608 "!TARGET_MIPS16" 4609{ 4610 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4611 return "slt\t%0,%1,%2"; 4612} 4613 [(set_attr "type" "slt") 4614 (set_attr "mode" "<MODE>")]) 4615 4616(define_insn "*sle_<mode>_mips16" 4617 [(set (match_operand:GPR 0 "register_operand" "=t") 4618 (le:GPR (match_operand:GPR 1 "register_operand" "d") 4619 (match_operand:GPR 2 "sle_operand" "")))] 4620 "TARGET_MIPS16" 4621{ 4622 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4623 return "slt\t%1,%2"; 4624} 4625 [(set_attr "type" "slt") 4626 (set_attr "mode" "<MODE>") 4627 (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1") 4628 (const_int 4) 4629 (const_int 8)))]) 4630 4631(define_expand "sgtu" 4632 [(set (match_operand:SI 0 "register_operand") 4633 (gtu:SI (match_dup 1) 4634 (match_dup 2)))] 4635 "" 4636 { if (mips_emit_scc (GTU, operands[0])) DONE; else FAIL; }) 4637 4638(define_insn "*sgtu_<mode>" 4639 [(set (match_operand:GPR 0 "register_operand" "=d") 4640 (gtu:GPR (match_operand:GPR 1 "register_operand" "d") 4641 (match_operand:GPR 2 "reg_or_0_operand" "dJ")))] 4642 "!TARGET_MIPS16" 4643 "sltu\t%0,%z2,%1" 4644 [(set_attr "type" "slt") 4645 (set_attr "mode" "<MODE>")]) 4646 4647(define_insn "*sgtu_<mode>_mips16" 4648 [(set (match_operand:GPR 0 "register_operand" "=t") 4649 (gtu:GPR (match_operand:GPR 1 "register_operand" "d") 4650 (match_operand:GPR 2 "register_operand" "d")))] 4651 "TARGET_MIPS16" 4652 "sltu\t%2,%1" 4653 [(set_attr "type" "slt") 4654 (set_attr "mode" "<MODE>")]) 4655 4656(define_expand "sgeu" 4657 [(set (match_operand:SI 0 "register_operand") 4658 (geu:SI (match_dup 1) 4659 (match_dup 2)))] 4660 "" 4661 { if (mips_emit_scc (GEU, operands[0])) DONE; else FAIL; }) 4662 4663(define_insn "*sge_<mode>" 4664 [(set (match_operand:GPR 0 "register_operand" "=d") 4665 (geu:GPR (match_operand:GPR 1 "register_operand" "d") 4666 (const_int 1)))] 4667 "!TARGET_MIPS16" 4668 "sltu\t%0,%.,%1" 4669 [(set_attr "type" "slt") 4670 (set_attr "mode" "<MODE>")]) 4671 4672(define_expand "sltu" 4673 [(set (match_operand:SI 0 "register_operand") 4674 (ltu:SI (match_dup 1) 4675 (match_dup 2)))] 4676 "" 4677 { if (mips_emit_scc (LTU, operands[0])) DONE; else FAIL; }) 4678 4679(define_insn "*sltu_<mode>" 4680 [(set (match_operand:GPR 0 "register_operand" "=d") 4681 (ltu:GPR (match_operand:GPR 1 "register_operand" "d") 4682 (match_operand:GPR 2 "arith_operand" "dI")))] 4683 "!TARGET_MIPS16" 4684 "sltu\t%0,%1,%2" 4685 [(set_attr "type" "slt") 4686 (set_attr "mode" "<MODE>")]) 4687 4688(define_insn "*sltu_<mode>_mips16" 4689 [(set (match_operand:GPR 0 "register_operand" "=t,t") 4690 (ltu:GPR (match_operand:GPR 1 "register_operand" "d,d") 4691 (match_operand:GPR 2 "arith_operand" "d,I")))] 4692 "TARGET_MIPS16" 4693 "sltu\t%1,%2" 4694 [(set_attr "type" "slt") 4695 (set_attr "mode" "<MODE>") 4696 (set_attr_alternative "length" 4697 [(const_int 4) 4698 (if_then_else (match_operand 2 "m16_uimm8_1") 4699 (const_int 4) 4700 (const_int 8))])]) 4701 4702(define_expand "sleu" 4703 [(set (match_operand:SI 0 "register_operand") 4704 (leu:SI (match_dup 1) 4705 (match_dup 2)))] 4706 "" 4707 { if (mips_emit_scc (LEU, operands[0])) DONE; else FAIL; }) 4708 4709(define_insn "*sleu_<mode>" 4710 [(set (match_operand:GPR 0 "register_operand" "=d") 4711 (leu:GPR (match_operand:GPR 1 "register_operand" "d") 4712 (match_operand:GPR 2 "sleu_operand" "")))] 4713 "!TARGET_MIPS16" 4714{ 4715 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4716 return "sltu\t%0,%1,%2"; 4717} 4718 [(set_attr "type" "slt") 4719 (set_attr "mode" "<MODE>")]) 4720 4721(define_insn "*sleu_<mode>_mips16" 4722 [(set (match_operand:GPR 0 "register_operand" "=t") 4723 (leu:GPR (match_operand:GPR 1 "register_operand" "d") 4724 (match_operand:GPR 2 "sleu_operand" "")))] 4725 "TARGET_MIPS16" 4726{ 4727 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 4728 return "sltu\t%1,%2"; 4729} 4730 [(set_attr "type" "slt") 4731 (set_attr "mode" "<MODE>") 4732 (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1") 4733 (const_int 4) 4734 (const_int 8)))]) 4735 4736;; 4737;; .................... 4738;; 4739;; FLOATING POINT COMPARISONS 4740;; 4741;; .................... 4742 4743(define_insn "s<code>_<mode>" 4744 [(set (match_operand:CC 0 "register_operand" "=z") 4745 (fcond:CC (match_operand:SCALARF 1 "register_operand" "f") 4746 (match_operand:SCALARF 2 "register_operand" "f")))] 4747 "" 4748 "c.<fcond>.<fmt>\t%Z0%1,%2" 4749 [(set_attr "type" "fcmp") 4750 (set_attr "mode" "FPSW")]) 4751 4752(define_insn "s<code>_<mode>" 4753 [(set (match_operand:CC 0 "register_operand" "=z") 4754 (swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f") 4755 (match_operand:SCALARF 2 "register_operand" "f")))] 4756 "" 4757 "c.<swapped_fcond>.<fmt>\t%Z0%2,%1" 4758 [(set_attr "type" "fcmp") 4759 (set_attr "mode" "FPSW")]) 4760 4761;; 4762;; .................... 4763;; 4764;; UNCONDITIONAL BRANCHES 4765;; 4766;; .................... 4767 4768;; Unconditional branches. 4769 4770(define_insn "jump" 4771 [(set (pc) 4772 (label_ref (match_operand 0 "" "")))] 4773 "!TARGET_MIPS16" 4774{ 4775 if (flag_pic) 4776 { 4777 if (get_attr_length (insn) <= 8) 4778 return "%*b\t%l0%/"; 4779 else 4780 { 4781 output_asm_insn (mips_output_load_label (), operands); 4782 return "%*jr\t%@%/%]"; 4783 } 4784 } 4785 else 4786 return "%*j\t%l0%/"; 4787} 4788 [(set_attr "type" "jump") 4789 (set_attr "mode" "none") 4790 (set (attr "length") 4791 ;; We can't use `j' when emitting PIC. Emit a branch if it's 4792 ;; in range, otherwise load the address of the branch target into 4793 ;; $at and then jump to it. 4794 (if_then_else 4795 (ior (eq (symbol_ref "flag_pic") (const_int 0)) 4796 (lt (abs (minus (match_dup 0) 4797 (plus (pc) (const_int 4)))) 4798 (const_int 131072))) 4799 (const_int 4) (const_int 16)))]) 4800 4801;; We need a different insn for the mips16, because a mips16 branch 4802;; does not have a delay slot. 4803 4804(define_insn "" 4805 [(set (pc) 4806 (label_ref (match_operand 0 "" "")))] 4807 "TARGET_MIPS16" 4808 "b\t%l0" 4809 [(set_attr "type" "branch") 4810 (set_attr "mode" "none") 4811 (set_attr "length" "8")]) 4812 4813(define_expand "indirect_jump" 4814 [(set (pc) (match_operand 0 "register_operand"))] 4815 "" 4816{ 4817 operands[0] = force_reg (Pmode, operands[0]); 4818 if (Pmode == SImode) 4819 emit_jump_insn (gen_indirect_jumpsi (operands[0])); 4820 else 4821 emit_jump_insn (gen_indirect_jumpdi (operands[0])); 4822 DONE; 4823}) 4824 4825(define_insn "indirect_jump<mode>" 4826 [(set (pc) (match_operand:P 0 "register_operand" "d"))] 4827 "" 4828 "%*j\t%0%/" 4829 [(set_attr "type" "jump") 4830 (set_attr "mode" "none")]) 4831 4832(define_expand "tablejump" 4833 [(set (pc) 4834 (match_operand 0 "register_operand")) 4835 (use (label_ref (match_operand 1 "")))] 4836 "" 4837{ 4838 if (TARGET_MIPS16) 4839 operands[0] = expand_binop (Pmode, add_optab, 4840 convert_to_mode (Pmode, operands[0], false), 4841 gen_rtx_LABEL_REF (Pmode, operands[1]), 4842 0, 0, OPTAB_WIDEN); 4843 else if (TARGET_GPWORD) 4844 operands[0] = expand_binop (Pmode, add_optab, operands[0], 4845 pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); 4846 4847 if (Pmode == SImode) 4848 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); 4849 else 4850 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); 4851 DONE; 4852}) 4853 4854(define_insn "tablejump<mode>" 4855 [(set (pc) 4856 (match_operand:P 0 "register_operand" "d")) 4857 (use (label_ref (match_operand 1 "" "")))] 4858 "" 4859 "%*j\t%0%/" 4860 [(set_attr "type" "jump") 4861 (set_attr "mode" "none")]) 4862 4863;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well. 4864;; While it is possible to either pull it off the stack (in the 4865;; o32 case) or recalculate it given t9 and our target label, 4866;; it takes 3 or 4 insns to do so. 4867 4868(define_expand "builtin_setjmp_setup" 4869 [(use (match_operand 0 "register_operand"))] 4870 "TARGET_ABICALLS" 4871{ 4872 rtx addr; 4873 4874 addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3); 4875 emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx); 4876 DONE; 4877}) 4878 4879;; Restore the gp that we saved above. Despite the earlier comment, it seems 4880;; that older code did recalculate the gp from $25. Continue to jump through 4881;; $25 for compatibility (we lose nothing by doing so). 4882 4883(define_expand "builtin_longjmp" 4884 [(use (match_operand 0 "register_operand"))] 4885 "TARGET_ABICALLS" 4886{ 4887 /* The elements of the buffer are, in order: */ 4888 int W = GET_MODE_SIZE (Pmode); 4889 rtx fp = gen_rtx_MEM (Pmode, operands[0]); 4890 rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); 4891 rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); 4892 rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); 4893 rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM); 4894 /* Use gen_raw_REG to avoid being given pic_offset_table_rtx. 4895 The target is bound to be using $28 as the global pointer 4896 but the current function might not be. */ 4897 rtx gp = gen_raw_REG (Pmode, GLOBAL_POINTER_REGNUM); 4898 4899 /* This bit is similar to expand_builtin_longjmp except that it 4900 restores $gp as well. */ 4901 emit_move_insn (hard_frame_pointer_rtx, fp); 4902 emit_move_insn (pv, lab); 4903 emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); 4904 emit_move_insn (gp, gpv); 4905 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 4906 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx)); 4907 emit_insn (gen_rtx_USE (VOIDmode, gp)); 4908 emit_indirect_jump (pv); 4909 DONE; 4910}) 4911 4912;; 4913;; .................... 4914;; 4915;; Function prologue/epilogue 4916;; 4917;; .................... 4918;; 4919 4920(define_expand "prologue" 4921 [(const_int 1)] 4922 "" 4923{ 4924 mips_expand_prologue (); 4925 DONE; 4926}) 4927 4928;; Block any insns from being moved before this point, since the 4929;; profiling call to mcount can use various registers that aren't 4930;; saved or used to pass arguments. 4931 4932(define_insn "blockage" 4933 [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] 4934 "" 4935 "" 4936 [(set_attr "type" "unknown") 4937 (set_attr "mode" "none") 4938 (set_attr "length" "0")]) 4939 4940(define_expand "epilogue" 4941 [(const_int 2)] 4942 "" 4943{ 4944 mips_expand_epilogue (false); 4945 DONE; 4946}) 4947 4948(define_expand "sibcall_epilogue" 4949 [(const_int 2)] 4950 "" 4951{ 4952 mips_expand_epilogue (true); 4953 DONE; 4954}) 4955 4956;; Trivial return. Make it look like a normal return insn as that 4957;; allows jump optimizations to work better. 4958 4959(define_insn "return" 4960 [(return)] 4961 "mips_can_use_return_insn ()" 4962 "%*j\t$31%/" 4963 [(set_attr "type" "jump") 4964 (set_attr "mode" "none")]) 4965 4966;; Normal return. 4967 4968(define_insn "return_internal" 4969 [(return) 4970 (use (match_operand 0 "pmode_register_operand" ""))] 4971 "" 4972 "%*j\t%0%/" 4973 [(set_attr "type" "jump") 4974 (set_attr "mode" "none")]) 4975 4976;; This is used in compiling the unwind routines. 4977(define_expand "eh_return" 4978 [(use (match_operand 0 "general_operand"))] 4979 "" 4980{ 4981 enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode; 4982 4983 if (GET_MODE (operands[0]) != gpr_mode) 4984 operands[0] = convert_to_mode (gpr_mode, operands[0], 0); 4985 if (TARGET_64BIT) 4986 emit_insn (gen_eh_set_lr_di (operands[0])); 4987 else 4988 emit_insn (gen_eh_set_lr_si (operands[0])); 4989 4990 DONE; 4991}) 4992 4993;; Clobber the return address on the stack. We can't expand this 4994;; until we know where it will be put in the stack frame. 4995 4996(define_insn "eh_set_lr_si" 4997 [(unspec [(match_operand:SI 0 "register_operand" "d")] UNSPEC_EH_RETURN) 4998 (clobber (match_scratch:SI 1 "=&d"))] 4999 "! TARGET_64BIT" 5000 "#") 5001 5002(define_insn "eh_set_lr_di" 5003 [(unspec [(match_operand:DI 0 "register_operand" "d")] UNSPEC_EH_RETURN) 5004 (clobber (match_scratch:DI 1 "=&d"))] 5005 "TARGET_64BIT" 5006 "#") 5007 5008(define_split 5009 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) 5010 (clobber (match_scratch 1))] 5011 "reload_completed && !TARGET_DEBUG_D_MODE" 5012 [(const_int 0)] 5013{ 5014 mips_set_return_address (operands[0], operands[1]); 5015 DONE; 5016}) 5017 5018(define_insn_and_split "exception_receiver" 5019 [(set (reg:SI 28) 5020 (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))] 5021 "TARGET_ABICALLS && TARGET_OLDABI" 5022 "#" 5023 "&& reload_completed" 5024 [(const_int 0)] 5025{ 5026 mips_restore_gp (); 5027 DONE; 5028} 5029 [(set_attr "type" "load") 5030 (set_attr "length" "12")]) 5031 5032;; 5033;; .................... 5034;; 5035;; FUNCTION CALLS 5036;; 5037;; .................... 5038 5039;; Instructions to load a call address from the GOT. The address might 5040;; point to a function or to a lazy binding stub. In the latter case, 5041;; the stub will use the dynamic linker to resolve the function, which 5042;; in turn will change the GOT entry to point to the function's real 5043;; address. 5044;; 5045;; This means that every call, even pure and constant ones, can 5046;; potentially modify the GOT entry. And once a stub has been called, 5047;; we must not call it again. 5048;; 5049;; We represent this restriction using an imaginary fixed register that 5050;; acts like a GOT version number. By making the register call-clobbered, 5051;; we tell the target-independent code that the address could be changed 5052;; by any call insn. 5053(define_insn "load_call<mode>" 5054 [(set (match_operand:P 0 "register_operand" "=c") 5055 (unspec:P [(match_operand:P 1 "register_operand" "r") 5056 (match_operand:P 2 "immediate_operand" "") 5057 (reg:P FAKE_CALL_REGNO)] 5058 UNSPEC_LOAD_CALL))] 5059 "TARGET_ABICALLS" 5060 "<load>\t%0,%R2(%1)" 5061 [(set_attr "type" "load") 5062 (set_attr "mode" "<MODE>") 5063 (set_attr "length" "4")]) 5064 5065;; Sibling calls. All these patterns use jump instructions. 5066 5067;; If TARGET_SIBCALLS, call_insn_operand will only accept constant 5068;; addresses if a direct jump is acceptable. Since the 'S' constraint 5069;; is defined in terms of call_insn_operand, the same is true of the 5070;; constraints. 5071 5072;; When we use an indirect jump, we need a register that will be 5073;; preserved by the epilogue. Since TARGET_ABICALLS forces us to 5074;; use $25 for this purpose -- and $25 is never clobbered by the 5075;; epilogue -- we might as well use it for !TARGET_ABICALLS as well. 5076 5077(define_expand "sibcall" 5078 [(parallel [(call (match_operand 0 "") 5079 (match_operand 1 "")) 5080 (use (match_operand 2 "")) ;; next_arg_reg 5081 (use (match_operand 3 ""))])] ;; struct_value_size_rtx 5082 "TARGET_SIBCALLS" 5083{ 5084 mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], true); 5085 DONE; 5086}) 5087 5088(define_insn "sibcall_internal" 5089 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S")) 5090 (match_operand 1 "" ""))] 5091 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" 5092 { return MIPS_CALL ("j", operands, 0); } 5093 [(set_attr "type" "call")]) 5094 5095(define_expand "sibcall_value" 5096 [(parallel [(set (match_operand 0 "") 5097 (call (match_operand 1 "") 5098 (match_operand 2 ""))) 5099 (use (match_operand 3 ""))])] ;; next_arg_reg 5100 "TARGET_SIBCALLS" 5101{ 5102 mips_expand_call (operands[0], XEXP (operands[1], 0), 5103 operands[2], operands[3], true); 5104 DONE; 5105}) 5106 5107(define_insn "sibcall_value_internal" 5108 [(set (match_operand 0 "register_operand" "=df,df") 5109 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) 5110 (match_operand 2 "" "")))] 5111 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" 5112 { return MIPS_CALL ("j", operands, 1); } 5113 [(set_attr "type" "call")]) 5114 5115(define_insn "sibcall_value_multiple_internal" 5116 [(set (match_operand 0 "register_operand" "=df,df") 5117 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) 5118 (match_operand 2 "" ""))) 5119 (set (match_operand 3 "register_operand" "=df,df") 5120 (call (mem:SI (match_dup 1)) 5121 (match_dup 2)))] 5122 "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" 5123 { return MIPS_CALL ("j", operands, 1); } 5124 [(set_attr "type" "call")]) 5125 5126(define_expand "call" 5127 [(parallel [(call (match_operand 0 "") 5128 (match_operand 1 "")) 5129 (use (match_operand 2 "")) ;; next_arg_reg 5130 (use (match_operand 3 ""))])] ;; struct_value_size_rtx 5131 "" 5132{ 5133 mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], false); 5134 DONE; 5135}) 5136 5137;; This instruction directly corresponds to an assembly-language "jal". 5138;; There are four cases: 5139;; 5140;; - -mno-abicalls: 5141;; Both symbolic and register destinations are OK. The pattern 5142;; always expands to a single mips instruction. 5143;; 5144;; - -mabicalls/-mno-explicit-relocs: 5145;; Again, both symbolic and register destinations are OK. 5146;; The call is treated as a multi-instruction black box. 5147;; 5148;; - -mabicalls/-mexplicit-relocs with n32 or n64: 5149;; Only "jal $25" is allowed. This expands to a single "jalr $25" 5150;; instruction. 5151;; 5152;; - -mabicalls/-mexplicit-relocs with o32 or o64: 5153;; Only "jal $25" is allowed. The call is actually two instructions: 5154;; "jalr $25" followed by an insn to reload $gp. 5155;; 5156;; In the last case, we can generate the individual instructions with 5157;; a define_split. There are several things to be wary of: 5158;; 5159;; - We can't expose the load of $gp before reload. If we did, 5160;; it might get removed as dead, but reload can introduce new 5161;; uses of $gp by rematerializing constants. 5162;; 5163;; - We shouldn't restore $gp after calls that never return. 5164;; It isn't valid to insert instructions between a noreturn 5165;; call and the following barrier. 5166;; 5167;; - The splitter deliberately changes the liveness of $gp. The unsplit 5168;; instruction preserves $gp and so have no effect on its liveness. 5169;; But once we generate the separate insns, it becomes obvious that 5170;; $gp is not live on entry to the call. 5171;; 5172;; ??? The operands[2] = insn check is a hack to make the original insn 5173;; available to the splitter. 5174(define_insn_and_split "call_internal" 5175 [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S")) 5176 (match_operand 1 "" "")) 5177 (clobber (reg:SI 31))] 5178 "" 5179 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); } 5180 "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)" 5181 [(const_int 0)] 5182{ 5183 emit_call_insn (gen_call_split (operands[0], operands[1])); 5184 if (!find_reg_note (operands[2], REG_NORETURN, 0)) 5185 mips_restore_gp (); 5186 DONE; 5187} 5188 [(set_attr "jal" "indirect,direct") 5189 (set_attr "extended_mips16" "no,yes")]) 5190 5191(define_insn "call_split" 5192 [(call (mem:SI (match_operand 0 "call_insn_operand" "cS")) 5193 (match_operand 1 "" "")) 5194 (clobber (reg:SI 31)) 5195 (clobber (reg:SI 28))] 5196 "TARGET_SPLIT_CALLS" 5197 { return MIPS_CALL ("jal", operands, 0); } 5198 [(set_attr "type" "call")]) 5199 5200(define_expand "call_value" 5201 [(parallel [(set (match_operand 0 "") 5202 (call (match_operand 1 "") 5203 (match_operand 2 ""))) 5204 (use (match_operand 3 ""))])] ;; next_arg_reg 5205 "" 5206{ 5207 mips_expand_call (operands[0], XEXP (operands[1], 0), 5208 operands[2], operands[3], false); 5209 DONE; 5210}) 5211 5212;; See comment for call_internal. 5213(define_insn_and_split "call_value_internal" 5214 [(set (match_operand 0 "register_operand" "=df,df") 5215 (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) 5216 (match_operand 2 "" ""))) 5217 (clobber (reg:SI 31))] 5218 "" 5219 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } 5220 "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)" 5221 [(const_int 0)] 5222{ 5223 emit_call_insn (gen_call_value_split (operands[0], operands[1], 5224 operands[2])); 5225 if (!find_reg_note (operands[3], REG_NORETURN, 0)) 5226 mips_restore_gp (); 5227 DONE; 5228} 5229 [(set_attr "jal" "indirect,direct") 5230 (set_attr "extended_mips16" "no,yes")]) 5231 5232(define_insn "call_value_split" 5233 [(set (match_operand 0 "register_operand" "=df") 5234 (call (mem:SI (match_operand 1 "call_insn_operand" "cS")) 5235 (match_operand 2 "" ""))) 5236 (clobber (reg:SI 31)) 5237 (clobber (reg:SI 28))] 5238 "TARGET_SPLIT_CALLS" 5239 { return MIPS_CALL ("jal", operands, 1); } 5240 [(set_attr "type" "call")]) 5241 5242;; See comment for call_internal. 5243(define_insn_and_split "call_value_multiple_internal" 5244 [(set (match_operand 0 "register_operand" "=df,df") 5245 (call (mem:SI (match_operand 1 "call_insn_operand" "c,S")) 5246 (match_operand 2 "" ""))) 5247 (set (match_operand 3 "register_operand" "=df,df") 5248 (call (mem:SI (match_dup 1)) 5249 (match_dup 2))) 5250 (clobber (reg:SI 31))] 5251 "" 5252 { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); } 5253 "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)" 5254 [(const_int 0)] 5255{ 5256 emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1], 5257 operands[2], operands[3])); 5258 if (!find_reg_note (operands[4], REG_NORETURN, 0)) 5259 mips_restore_gp (); 5260 DONE; 5261} 5262 [(set_attr "jal" "indirect,direct") 5263 (set_attr "extended_mips16" "no,yes")]) 5264 5265(define_insn "call_value_multiple_split" 5266 [(set (match_operand 0 "register_operand" "=df") 5267 (call (mem:SI (match_operand 1 "call_insn_operand" "cS")) 5268 (match_operand 2 "" ""))) 5269 (set (match_operand 3 "register_operand" "=df") 5270 (call (mem:SI (match_dup 1)) 5271 (match_dup 2))) 5272 (clobber (reg:SI 31)) 5273 (clobber (reg:SI 28))] 5274 "TARGET_SPLIT_CALLS" 5275 { return MIPS_CALL ("jal", operands, 1); } 5276 [(set_attr "type" "call")]) 5277 5278;; Call subroutine returning any type. 5279 5280(define_expand "untyped_call" 5281 [(parallel [(call (match_operand 0 "") 5282 (const_int 0)) 5283 (match_operand 1 "") 5284 (match_operand 2 "")])] 5285 "" 5286{ 5287 int i; 5288 5289 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); 5290 5291 for (i = 0; i < XVECLEN (operands[2], 0); i++) 5292 { 5293 rtx set = XVECEXP (operands[2], 0, i); 5294 emit_move_insn (SET_DEST (set), SET_SRC (set)); 5295 } 5296 5297 emit_insn (gen_blockage ()); 5298 DONE; 5299}) 5300 5301;; 5302;; .................... 5303;; 5304;; MISC. 5305;; 5306;; .................... 5307;; 5308 5309 5310(define_insn "prefetch" 5311 [(prefetch (match_operand:QI 0 "address_operand" "p") 5312 (match_operand 1 "const_int_operand" "n") 5313 (match_operand 2 "const_int_operand" "n"))] 5314 "ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS" 5315{ 5316 operands[1] = mips_prefetch_cookie (operands[1], operands[2]); 5317 return "pref\t%1,%a0"; 5318} 5319 [(set_attr "type" "prefetch")]) 5320 5321(define_insn "*prefetch_indexed_<mode>" 5322 [(prefetch (plus:P (match_operand:P 0 "register_operand" "d") 5323 (match_operand:P 1 "register_operand" "d")) 5324 (match_operand 2 "const_int_operand" "n") 5325 (match_operand 3 "const_int_operand" "n"))] 5326 "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" 5327{ 5328 operands[2] = mips_prefetch_cookie (operands[2], operands[3]); 5329 return "prefx\t%2,%1(%0)"; 5330} 5331 [(set_attr "type" "prefetchx")]) 5332 5333(define_insn "nop" 5334 [(const_int 0)] 5335 "" 5336 "%(nop%)" 5337 [(set_attr "type" "nop") 5338 (set_attr "mode" "none")]) 5339 5340;; Like nop, but commented out when outside a .set noreorder block. 5341(define_insn "hazard_nop" 5342 [(const_int 1)] 5343 "" 5344 { 5345 if (set_noreorder) 5346 return "nop"; 5347 else 5348 return "#nop"; 5349 } 5350 [(set_attr "type" "nop")]) 5351 5352;; MIPS4 Conditional move instructions. 5353 5354(define_insn "*mov<GPR:mode>_on_<MOVECC:mode>" 5355 [(set (match_operand:GPR 0 "register_operand" "=d,d") 5356 (if_then_else:GPR 5357 (match_operator:MOVECC 4 "equality_operator" 5358 [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>") 5359 (const_int 0)]) 5360 (match_operand:GPR 2 "reg_or_0_operand" "dJ,0") 5361 (match_operand:GPR 3 "reg_or_0_operand" "0,dJ")))] 5362 "ISA_HAS_CONDMOVE" 5363 "@ 5364 mov%T4\t%0,%z2,%1 5365 mov%t4\t%0,%z3,%1" 5366 [(set_attr "type" "condmove") 5367 (set_attr "mode" "<GPR:MODE>")]) 5368 5369(define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>" 5370 [(set (match_operand:SCALARF 0 "register_operand" "=f,f") 5371 (if_then_else:SCALARF 5372 (match_operator:MOVECC 4 "equality_operator" 5373 [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>") 5374 (const_int 0)]) 5375 (match_operand:SCALARF 2 "register_operand" "f,0") 5376 (match_operand:SCALARF 3 "register_operand" "0,f")))] 5377 "ISA_HAS_CONDMOVE" 5378 "@ 5379 mov%T4.<fmt>\t%0,%2,%1 5380 mov%t4.<fmt>\t%0,%3,%1" 5381 [(set_attr "type" "condmove") 5382 (set_attr "mode" "<SCALARF:MODE>")]) 5383 5384;; These are the main define_expand's used to make conditional moves. 5385 5386(define_expand "mov<mode>cc" 5387 [(set (match_dup 4) (match_operand 1 "comparison_operator")) 5388 (set (match_operand:GPR 0 "register_operand") 5389 (if_then_else:GPR (match_dup 5) 5390 (match_operand:GPR 2 "reg_or_0_operand") 5391 (match_operand:GPR 3 "reg_or_0_operand")))] 5392 "ISA_HAS_CONDMOVE" 5393{ 5394 gen_conditional_move (operands); 5395 DONE; 5396}) 5397 5398(define_expand "mov<mode>cc" 5399 [(set (match_dup 4) (match_operand 1 "comparison_operator")) 5400 (set (match_operand:SCALARF 0 "register_operand") 5401 (if_then_else:SCALARF (match_dup 5) 5402 (match_operand:SCALARF 2 "register_operand") 5403 (match_operand:SCALARF 3 "register_operand")))] 5404 "ISA_HAS_CONDMOVE" 5405{ 5406 gen_conditional_move (operands); 5407 DONE; 5408}) 5409 5410;; 5411;; .................... 5412;; 5413;; mips16 inline constant tables 5414;; 5415;; .................... 5416;; 5417 5418(define_insn "consttable_int" 5419 [(unspec_volatile [(match_operand 0 "consttable_operand" "") 5420 (match_operand 1 "const_int_operand" "")] 5421 UNSPEC_CONSTTABLE_INT)] 5422 "TARGET_MIPS16" 5423{ 5424 assemble_integer (operands[0], INTVAL (operands[1]), 5425 BITS_PER_UNIT * INTVAL (operands[1]), 1); 5426 return ""; 5427} 5428 [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))]) 5429 5430(define_insn "consttable_float" 5431 [(unspec_volatile [(match_operand 0 "consttable_operand" "")] 5432 UNSPEC_CONSTTABLE_FLOAT)] 5433 "TARGET_MIPS16" 5434{ 5435 REAL_VALUE_TYPE d; 5436 5437 gcc_assert (GET_CODE (operands[0]) == CONST_DOUBLE); 5438 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]); 5439 assemble_real (d, GET_MODE (operands[0]), 5440 GET_MODE_BITSIZE (GET_MODE (operands[0]))); 5441 return ""; 5442} 5443 [(set (attr "length") 5444 (symbol_ref "GET_MODE_SIZE (GET_MODE (operands[0]))"))]) 5445 5446(define_insn "align" 5447 [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPEC_ALIGN)] 5448 "" 5449 ".align\t%0" 5450 [(set (attr "length") (symbol_ref "(1 << INTVAL (operands[0])) - 1"))]) 5451 5452(define_split 5453 [(match_operand 0 "small_data_pattern")] 5454 "reload_completed" 5455 [(match_dup 0)] 5456 { operands[0] = mips_rewrite_small_data (operands[0]); }) 5457 5458; Thread-Local Storage 5459 5460; The TLS base pointer is accessed via "rdhwr $v1, $29". No current 5461; MIPS architecture defines this register, and no current 5462; implementation provides it; instead, any OS which supports TLS is 5463; expected to trap and emulate this instruction. rdhwr is part of the 5464; MIPS 32r2 specification, but we use it on any architecture because 5465; we expect it to be emulated. Use .set to force the assembler to 5466; accept it. 5467 5468(define_insn "tls_get_tp_<mode>" 5469 [(set (match_operand:P 0 "register_operand" "=v") 5470 (unspec:P [(const_int 0)] 5471 UNSPEC_TLS_GET_TP))] 5472 "HAVE_AS_TLS && !TARGET_MIPS16" 5473 ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop" 5474 [(set_attr "type" "unknown") 5475 ; Since rdhwr always generates a trap for now, putting it in a delay 5476 ; slot would make the kernel's emulation of it much slower. 5477 (set_attr "can_delay" "no") 5478 (set_attr "mode" "<MODE>")]) 5479 5480; The MIPS Paired-Single Floating Point and MIPS-3D Instructions. 5481 5482(include "mips-ps-3d.md") 5483 5484; The MIPS DSP Instructions. 5485 5486(include "mips-dsp.md")
|