1;; Machine description of Andes NDS32 cpu for GNU compiler 2;; Copyright (C) 2012-2020 Free Software Foundation, Inc. 3;; Contributed by Andes Technology Corporation. 4;; 5;; This file is part of GCC. 6;; 7;; GCC is free software; you can redistribute it and/or modify it 8;; under the terms of the GNU General Public License as published 9;; by the Free Software Foundation; either version 3, or (at your 10;; option) any later version. 11;; 12;; GCC is distributed in the hope that it will be useful, but WITHOUT 13;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15;; License for more details. 16;; 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21;;SFmode moves 22 23(define_expand "movsf" 24 [(set (match_operand:SF 0 "general_operand" "") 25 (match_operand:SF 1 "general_operand" ""))] 26 "" 27{ 28 /* Need to force register if mem <- !reg. */ 29 if (MEM_P (operands[0]) && !REG_P (operands[1])) 30 operands[1] = force_reg (SFmode, operands[1]); 31 if (CONST_DOUBLE_P (operands[1]) 32 && !satisfies_constraint_Cs20 (operands[1])) 33 { 34 const REAL_VALUE_TYPE *r; 35 unsigned long l; 36 37 r = CONST_DOUBLE_REAL_VALUE (operands[1]); 38 REAL_VALUE_TO_TARGET_SINGLE (*r, l); 39 40 emit_move_insn (operands[0], gen_rtx_HIGH (SFmode, operands[1])); 41 42 if ((l & 0xFFF) != 0) 43 emit_insn (gen_movsf_lo (operands[0], operands[0], operands[1])); 44 DONE; 45 } 46}) 47 48(define_insn "movsf_lo" 49 [(set (match_operand:SF 0 "register_operand" "=r") 50 (lo_sum:SF (match_operand:SF 1 "register_operand" "r") 51 (match_operand:SF 2 "immediate_operand" "i")))] 52 "" 53 "ori\t%0, %1, lo12(%2)" 54 [(set_attr "type" "alu") 55 (set_attr "length" "4")] 56) 57 58(define_insn "*movsf" 59 [(set (match_operand:SF 0 "nonimmediate_operand" "=r, r, U45, U33, U37, U45, m, l, l, l, d, r, f, *f, *r, f, Q, r, r, r") 60 (match_operand:SF 1 "general_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45, m, f, *r, *f, Q, f,Cs05,Cs20, Chig"))] 61 "(register_operand(operands[0], SFmode) 62 || register_operand(operands[1], SFmode))" 63{ 64 switch (which_alternative) 65 { 66 case 0: 67 return "mov55\t%0, %1"; 68 case 1: 69 return "ori\t%0, %1, 0"; 70 case 2: 71 case 3: 72 case 4: 73 case 5: 74 return nds32_output_16bit_store (operands, 4); 75 case 6: 76 return nds32_output_32bit_store (operands, 4); 77 case 7: 78 case 8: 79 case 9: 80 case 10: 81 return nds32_output_16bit_load (operands, 4); 82 case 11: 83 return nds32_output_32bit_load (operands, 4); 84 case 12: 85 if (TARGET_FPU_SINGLE) 86 return "fcpyss\t%0, %1, %1"; 87 else 88 return "#"; 89 case 13: 90 return "fmtsr\t%1, %0"; 91 case 14: 92 return "fmfsr\t%0, %1"; 93 case 15: 94 return nds32_output_float_load (operands); 95 case 16: 96 return nds32_output_float_store (operands); 97 case 17: 98 return "movi55\t%0, %1"; 99 case 18: 100 return "movi\t%0, %1"; 101 case 19: 102 return "sethi\t%0, %1"; 103 default: 104 gcc_unreachable (); 105 } 106} 107 [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,fcpy,fmtsr,fmfsr,fload,fstore,alu,alu,alu") 108 (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 2, 4, 4") 109 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu, v1, v1, v1")]) 110 111;; Conditional Move Instructions 112 113(define_expand "mov<mode>cc" 114 [(set (match_operand:ANYF 0 "register_operand" "") 115 (if_then_else:ANYF (match_operand 1 "nds32_float_comparison_operator" "") 116 (match_operand:ANYF 2 "register_operand" "") 117 (match_operand:ANYF 3 "register_operand" "")))] 118 "" 119{ 120 if (nds32_cond_move_p (operands[1])) 121 { 122 /* Operands[1] condition code is UNORDERED or ORDERED, and 123 sub-operands[1] MODE isn't SFmode or SFmode, return FAIL 124 for gcc, because we don't using slt compare instruction 125 to generate UNORDERED and ORDERED condition. */ 126 FAIL; 127 } 128 else 129 nds32_expand_float_movcc (operands); 130}) 131 132(define_insn "fcmov<mode>_eq" 133 [(set (match_operand:ANYF 0 "register_operand" "=f, f") 134 (if_then_else:ANYF (eq (match_operand:SI 1 "register_operand" "f, f") 135 (const_int 0)) 136 (match_operand:ANYF 2 "register_operand" "f, 0") 137 (match_operand:ANYF 3 "register_operand" "0, f")))] 138 "" 139 "@ 140 fcmovz<size>\t%0,%2,%1 141 fcmovn<size>\t%0,%3,%1" 142 [(set_attr "type" "fcmov") 143 (set_attr "length" "4")] 144) 145 146(define_insn "fcmov<mode>_ne" 147 [(set (match_operand:ANYF 0 "register_operand" "=f, f") 148 (if_then_else:ANYF (ne (match_operand:SI 1 "register_operand" "f, f") 149 (const_int 0)) 150 (match_operand:ANYF 2 "register_operand" "f, 0") 151 (match_operand:ANYF 3 "register_operand" "0, f")))] 152 "" 153 "@ 154 fcmovn<size>\t%0,%2,%1 155 fcmovz<size>\t%0,%3,%1" 156 [(set_attr "type" "fcmov") 157 (set_attr "length" "4")] 158) 159 160;; Arithmetic instructions. 161 162(define_insn "add<mode>3" 163 [(set (match_operand:ANYF 0 "register_operand" "=f") 164 (plus:ANYF (match_operand:ANYF 1 "register_operand" "f") 165 (match_operand:ANYF 2 "register_operand" "f")))] 166 "" 167 "fadd<size>\t %0, %1, %2" 168 [(set_attr "type" "falu") 169 (set_attr "length" "4")] 170) 171 172(define_insn "sub<mode>3" 173 [(set (match_operand:ANYF 0 "register_operand" "=f") 174 (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") 175 (match_operand:ANYF 2 "register_operand" "f")))] 176 "" 177 "fsub<size>\t %0, %1, %2" 178 [(set_attr "type" "falu") 179 (set_attr "length" "4")] 180) 181 182;; Multiplication insns. 183 184(define_insn "mul<mode>3" 185 [(set (match_operand:ANYF 0 "register_operand" "=f") 186 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 187 (match_operand:ANYF 2 "register_operand" "f")))] 188 "" 189 "fmul<size>\t %0, %1, %2" 190 [(set_attr "type" "fmul<size>") 191 (set_attr "length" "4")] 192) 193 194(define_insn "fma<mode>4" 195 [(set (match_operand:ANYF 0 "register_operand" "=f") 196 (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") 197 (match_operand:ANYF 2 "register_operand" "f") 198 (match_operand:ANYF 3 "register_operand" "0")))] 199 "TARGET_EXT_FPU_FMA" 200 "fmadd<size>\t%0, %1, %2" 201 [(set_attr "type" "fmac<size>") 202 (set_attr "length" "4")] 203) 204 205(define_insn "fnma<mode>4" 206 [(set (match_operand:ANYF 0 "register_operand" "=f") 207 (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 208 (match_operand:ANYF 2 "register_operand" "f") 209 (match_operand:ANYF 3 "register_operand" "0")))] 210 "TARGET_EXT_FPU_FMA" 211 "fmsub<size>\t%0, %1, %2" 212 [(set_attr "type" "fmac<size>") 213 (set_attr "length" "4")] 214) 215 216(define_insn "fms<mode>4" 217 [(set (match_operand:ANYF 0 "register_operand" "=f") 218 (fma:ANYF (match_operand:ANYF 1 "register_operand" "f") 219 (match_operand:ANYF 2 "register_operand" "f") 220 (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))] 221 "TARGET_EXT_FPU_FMA" 222 "fnmsub<size>\t%0, %1, %2" 223 [(set_attr "type" "fmac<size>") 224 (set_attr "length" "4")] 225) 226 227(define_insn "fnms<mode>4" 228 [(set (match_operand:ANYF 0 "register_operand" "=f") 229 (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 230 (match_operand:ANYF 2 "register_operand" "f") 231 (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))] 232 "TARGET_EXT_FPU_FMA" 233 "fnmadd<size>\t%0, %1, %2" 234 [(set_attr "type" "fmac<size>") 235 (set_attr "length" "4")] 236) 237 238;; Div Instructions. 239 240(define_insn "div<mode>3" 241 [(set (match_operand:ANYF 0 "register_operand" "=f") 242 (div:ANYF (match_operand:ANYF 1 "register_operand" "f") 243 (match_operand:ANYF 2 "register_operand" "f")))] 244 "" 245 "fdiv<size>\t %0, %1, %2" 246 [(set_attr "type" "fdiv<size>") 247 (set_attr "length" "4")] 248) 249 250(define_insn "sqrt<mode>2" 251 [(set (match_operand:ANYF 0 "register_operand" "=f") 252 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 253 "" 254 "fsqrt<size>\t %0, %1" 255 [(set_attr "type" "fsqrt<size>") 256 (set_attr "length" "4")] 257) 258 259;; Conditional Branch patterns 260 261(define_expand "cstore<mode>4" 262 [(set (match_operand:SI 0 "register_operand" "") 263 (match_operator:SI 1 "nds32_float_comparison_operator" 264 [(match_operand:ANYF 2 "register_operand" "") 265 (match_operand:ANYF 3 "register_operand" "")]))] 266 "" 267{ 268 nds32_expand_float_cstore (operands); 269 DONE; 270}) 271 272(define_expand "cbranch<mode>4" 273 [(set (pc) 274 (if_then_else (match_operator 0 "nds32_float_comparison_operator" 275 [(match_operand:ANYF 1 "register_operand" "") 276 (match_operand:ANYF 2 "register_operand" "")]) 277 (label_ref (match_operand 3 "" "")) 278 (pc)))] 279 "" 280{ 281 nds32_expand_float_cbranch (operands); 282 DONE; 283}) 284 285;; Copysign Instructions. 286 287(define_insn "copysignsf3" 288 [(set (match_operand:SF 0 "register_operand" "=f") 289 (unspec:SF [(match_operand:SF 1 "register_operand" "f") 290 (match_operand:SF 2 "register_operand" "f")] 291 UNSPEC_COPYSIGN))] 292 "TARGET_FPU_SINGLE" 293 "fcpyss\t%0,%1,%2" 294 [(set_attr "type" "fcpy") 295 (set_attr "length" "4")] 296) 297 298(define_insn "copysigndf3" 299 [(set (match_operand:DF 0 "register_operand" "=f") 300 (unspec:DF [(match_operand:DF 1 "register_operand" "f") 301 (match_operand:DF 2 "register_operand" "f")] 302 UNSPEC_COPYSIGN))] 303 "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE" 304 "fcpysd\t%0,%1,%2" 305 [(set_attr "type" "fcpy") 306 (set_attr "length" "4")] 307) 308 309(define_insn "*ncopysign<mode>3" 310 [(set (match_operand:ANYF 0 "register_operand" "=f") 311 (neg:ANYF (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") 312 (match_operand:ANYF 2 "register_operand" "f")] 313 UNSPEC_COPYSIGN)))] 314 "" 315 "fcpyns<size>\t%0,%1,%2" 316 [(set_attr "type" "fcpy") 317 (set_attr "length" "4")] 318) 319 320;; Absolute Instructions 321 322(define_insn "abssf2" 323 [(set (match_operand:SF 0 "register_operand" "=f, r") 324 (abs:SF (match_operand:SF 1 "register_operand" "f, r")))] 325 "TARGET_FPU_SINGLE || TARGET_EXT_PERF" 326 "@ 327 fabss\t%0, %1 328 bclr\t%0, %1, 31" 329 [(set_attr "type" "fabs,alu") 330 (set_attr "length" "4") 331 (set_attr "feature" "fpu,pe1")] 332) 333 334(define_insn "absdf2" 335 [(set (match_operand:DF 0 "register_operand" "=f") 336 (abs:DF (match_operand:DF 1 "register_operand" "f")))] 337 "TARGET_FPU_DOUBLE" 338 "fabsd\t%0, %1" 339 [(set_attr "type" "fabs") 340 (set_attr "length" "4")] 341) 342 343;; Negation Instructions 344 345(define_insn "*negsf2" 346 [(set (match_operand:SF 0 "register_operand" "=f, r") 347 (neg:SF (match_operand:SF 1 "register_operand" "f, r")))] 348 "TARGET_FPU_SINGLE || TARGET_EXT_PERF" 349 "@ 350 fcpynss\t%0, %1, %1 351 btgl\t%0, %1, 31" 352 [(set_attr "type" "fcpy,alu") 353 (set_attr "length" "4") 354 (set_attr "feature" "fpu,pe1")] 355) 356 357(define_insn "*negdf2" 358 [(set (match_operand:DF 0 "register_operand" "=f") 359 (neg:DF (match_operand:DF 1 "register_operand" "f")))] 360 "TARGET_FPU_DOUBLE" 361 "fcpynsd\t%0, %1, %1" 362 [(set_attr "type" "fcpy") 363 (set_attr "length" "4")] 364) 365 366;; Data Format Conversion Instructions 367 368(define_insn "floatunssi<mode>2" 369 [(set (match_operand:ANYF 0 "register_operand" "=f") 370 (unsigned_float:ANYF (match_operand:SI 1 "register_operand" "f")))] 371 "" 372 "fui2<size>\t %0, %1" 373 [(set_attr "type" "falu") 374 (set_attr "length" "4")] 375) 376 377(define_insn "floatsi<mode>2" 378 [(set (match_operand:ANYF 0 "register_operand" "=f") 379 (float:ANYF (match_operand:SI 1 "register_operand" "f")))] 380 "" 381 "fsi2<size>\t %0, %1" 382 [(set_attr "type" "falu") 383 (set_attr "length" "4")] 384) 385 386(define_insn "fixuns_trunc<mode>si2" 387 [(set (match_operand:SI 0 "register_operand" "=f") 388 (unsigned_fix:SI (fix:ANYF (match_operand:ANYF 1 "register_operand" "f"))))] 389 "" 390 "f<size>2ui.z\t %0, %1" 391 [(set_attr "type" "falu") 392 (set_attr "length" "4")] 393) 394 395(define_insn "fix_trunc<mode>si2" 396 [(set (match_operand:SI 0 "register_operand" "=f") 397 (fix:SI (fix:ANYF (match_operand:ANYF 1 "register_operand" "f"))))] 398 "" 399 "f<size>2si.z\t %0, %1" 400 [(set_attr "type" "falu") 401 (set_attr "length" "4")] 402) 403 404(define_insn "extendsfdf2" 405 [(set (match_operand:DF 0 "register_operand" "=f") 406 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] 407 "TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE" 408 "fs2d\t%0, %1" 409 [(set_attr "type" "falu") 410 (set_attr "length" "4")] 411) 412 413(define_insn "truncdfsf2" 414 [(set (match_operand:SF 0 "register_operand" "=f") 415 (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] 416 "TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE" 417 "fd2s\t%0, %1" 418 [(set_attr "type" "falu") 419 (set_attr "length" "4")] 420) 421 422;; Compare Instructions 423 424(define_insn "cmp<mode>_eq" 425 [(set (match_operand:SI 0 "register_operand" "=f") 426 (eq:SI (match_operand:ANYF 1 "register_operand" "f") 427 (match_operand:ANYF 2 "register_operand" "f")))] 428 "" 429 { 430 if (NDS32_EXT_FPU_DOT_E) 431 return "fcmpeq<size>.e %0, %1, %2"; 432 else 433 return "fcmpeq<size>\t%0, %1, %2"; 434 } 435 [(set_attr "type" "fcmp") 436 (set_attr "length" "4")] 437) 438 439(define_insn "cmp<mode>_lt" 440 [(set (match_operand:SI 0 "register_operand" "=f") 441 (lt:SI (match_operand:ANYF 1 "register_operand" "f") 442 (match_operand:ANYF 2 "register_operand" "f")))] 443 "" 444{ 445 if (NDS32_EXT_FPU_DOT_E) 446 return "fcmplt<size>.e %0, %1, %2"; 447 else 448 return "fcmplt<size>\t%0, %1, %2"; 449} 450 [(set_attr "type" "fcmp") 451 (set_attr "length" "4")] 452) 453 454(define_insn "cmp<mode>_le" 455 [(set (match_operand:SI 0 "register_operand" "=f") 456 (le:SI (match_operand:ANYF 1 "register_operand" "f") 457 (match_operand:ANYF 2 "register_operand" "f")))] 458 "" 459{ 460 if (NDS32_EXT_FPU_DOT_E) 461 return "fcmple<size>.e %0, %1, %2"; 462 else 463 return "fcmple<size>\t%0, %1, %2"; 464} 465 [(set_attr "type" "fcmp") 466 (set_attr "length" "4")] 467) 468 469(define_insn "cmp<mode>_un" 470 [(set (match_operand:SI 0 "register_operand" "=f") 471 (unordered:SI (match_operand:ANYF 1 "register_operand" "f") 472 (match_operand:ANYF 2 "register_operand" "f")))] 473 "" 474{ 475 if (NDS32_EXT_FPU_DOT_E) 476 return "fcmpun<size>.e %0, %1, %2"; 477 else 478 return "fcmpun<size>\t%0, %1, %2"; 479} 480 [(set_attr "type" "fcmp") 481 (set_attr "length" "4")] 482) 483 484(define_split 485 [(set (match_operand:SF 0 "register_operand" "") 486 (match_operand:SF 1 "register_operand" ""))] 487 "!TARGET_FPU_SINGLE 488 && NDS32_IS_FPR_REGNUM (REGNO (operands[0])) 489 && NDS32_IS_FPR_REGNUM (REGNO (operands[1]))" 490 [(set (match_dup 2) (match_dup 1)) 491 (set (match_dup 0) (match_dup 2))] 492{ 493 operands[2] = gen_rtx_REG (SFmode, TA_REGNUM); 494}) 495 496(define_split 497 [(set (match_operand:SF 0 "register_operand" "") 498 (match_operand:SF 1 "const_double_operand" ""))] 499 "!satisfies_constraint_Cs20 (operands[1]) 500 && !satisfies_constraint_Chig (operands[1])" 501 [(set (match_dup 0) (high:SF (match_dup 1))) 502 (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))]) 503;; ---------------------------------------------------------------------------- 504