1;; Machine description of Andes NDS32 cpu for GNU compiler 2;; Copyright (C) 2012-2021 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;; See file "rtl.def" for documentation on define_insn, match_*, et. al. 22 23;; Include predicates definition. 24(include "predicates.md") 25 26;; Include constraints definition. 27(include "constraints.md") 28 29;; Include iterators definition. 30(include "iterators.md") 31 32;; Include pipelines definition. 33(include "pipelines.md") 34 35 36;; Include constants definition. 37(include "constants.md") 38 39 40;; Include intrinsic functions definition. 41(include "nds32-intrinsic.md") 42 43;; Include block move for nds32 multiple load/store behavior. 44(include "nds32-multiple.md") 45 46;; Include DImode/DFmode operations. 47(include "nds32-doubleword.md") 48 49;; Include floating-point patterns. 50(include "nds32-fpu.md") 51 52;; Include peephole patterns. 53(include "nds32-peephole2.md") 54 55 56;; ------------------------------------------------------------------------ 57 58;; CPU pipeline model. 59(define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,simple" 60 (const 61 (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7") 62 (match_test "nds32_cpu_option == CPU_E8") (const_string "e8") 63 (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8") 64 (match_test "nds32_cpu_option == CPU_N9") (const_string "n9") 65 (match_test "nds32_cpu_option == CPU_N10") (const_string "n10") 66 (match_test "nds32_cpu_option == CPU_GRAYWOLF") (const_string "graywolf") 67 (match_test "nds32_cpu_option == CPU_N12") (const_string "n13") 68 (match_test "nds32_cpu_option == CPU_N13") (const_string "n13") 69 (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")] 70 (const_string "n9")))) 71 72;; Insn type, it is used to default other attribute values. 73(define_attr "type" 74 "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\ 75 falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore,\ 76 dalu,dalu64,daluround,dcmp,dclip,dmul,dmac,dinsb,dpack,dbpick,dwext" 77 (const_string "unknown")) 78 79;; Insn sub-type 80(define_attr "subtype" 81 "simple,shift,saturation" 82 (const_string "simple")) 83 84;; Length, in bytes, default is 4-bytes. 85(define_attr "length" "" (const_int 4)) 86 87;; Indicate the amount of micro instructions. 88(define_attr "combo" 89 "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25" 90 (const_string "1")) 91 92;; Insn in which feature set, it is used to enable/disable insn alternatives. 93;; v1 : Baseline Instructions 94;; v2 : Baseline Version 2 Instructions 95;; v3m : Baseline Version 3m Instructions 96;; v3 : Baseline Version 3 Instructions 97;; pe1 : Performance Extension Instructions 98;; pe2 : Performance Extension Version 2 Instructions 99;; se : String Extension instructions 100(define_attr "feature" 101 "v1,v2,v3m,v3,pe1,pe2,se,fpu" 102 (const_string "v1")) 103 104;; Enabled, which is used to enable/disable insn alternatives. 105;; Note that we use length and TARGET_16_BIT here as criteria. 106;; If the instruction pattern already check TARGET_16_BIT to determine 107;; the length by itself, its enabled attribute should be customized to 108;; avoid the conflict between length attribute and this default setting. 109(define_attr "enabled" "no,yes" 110 (if_then_else 111 (and (eq_attr "length" "2") 112 (match_test "!TARGET_16_BIT")) 113 (const_string "no") 114 (cond [(eq_attr "feature" "v1") (const_string "yes") 115 (eq_attr "feature" "v2") (if_then_else (match_test "TARGET_ISA_V2 || TARGET_ISA_V3 || TARGET_ISA_V3M") 116 (const_string "yes") 117 (const_string "no")) 118 (eq_attr "feature" "v3") (if_then_else (match_test "TARGET_ISA_V3") 119 (const_string "yes") 120 (const_string "no")) 121 (eq_attr "feature" "v3m") (if_then_else (match_test "TARGET_ISA_V3 || TARGET_ISA_V3M") 122 (const_string "yes") 123 (const_string "no")) 124 (eq_attr "feature" "pe1") (if_then_else (match_test "TARGET_EXT_PERF") 125 (const_string "yes") 126 (const_string "no")) 127 (eq_attr "feature" "pe2") (if_then_else (match_test "TARGET_EXT_PERF2") 128 (const_string "yes") 129 (const_string "no")) 130 (eq_attr "feature" "se") (if_then_else (match_test "TARGET_EXT_STRING") 131 (const_string "yes") 132 (const_string "no")) 133 (eq_attr "feature" "fpu") (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE") 134 (const_string "yes") 135 (const_string "no"))] 136 (const_string "yes")))) 137 138 139;; ---------------------------------------------------------------------------- 140 141(include "nds32-dspext.md") 142 143;; Move instructions. 144 145;; For QImode and HImode, the immediate value can be fit in imm20s. 146;; So there is no need to split rtx for QI and HI patterns. 147 148(define_expand "mov<mode>" 149 [(set (match_operand:QIHI 0 "general_operand" "") 150 (match_operand:QIHI 1 "general_operand" ""))] 151 "" 152{ 153 /* Need to force register if mem <- !reg. */ 154 if (MEM_P (operands[0]) && !REG_P (operands[1])) 155 operands[1] = force_reg (<MODE>mode, operands[1]); 156 157 if (MEM_P (operands[1]) && optimize > 0) 158 { 159 rtx reg = gen_reg_rtx (SImode); 160 161 emit_insn (gen_zero_extend<mode>si2 (reg, operands[1])); 162 operands[1] = gen_lowpart (<MODE>mode, reg); 163 } 164}) 165 166(define_expand "movmisalign<mode>" 167 [(set (match_operand:SIDI 0 "general_operand" "") 168 (match_operand:SIDI 1 "general_operand" ""))] 169 "" 170{ 171 rtx addr; 172 if (MEM_P (operands[0]) && !REG_P (operands[1])) 173 operands[1] = force_reg (<MODE>mode, operands[1]); 174 175 if (MEM_P (operands[0])) 176 { 177 addr = force_reg (Pmode, XEXP (operands[0], 0)); 178 emit_insn (gen_unaligned_store<mode> (addr, operands[1])); 179 } 180 else 181 { 182 addr = force_reg (Pmode, XEXP (operands[1], 0)); 183 emit_insn (gen_unaligned_load<mode> (operands[0], addr)); 184 } 185 DONE; 186}) 187 188(define_expand "movsi" 189 [(set (match_operand:SI 0 "general_operand" "") 190 (match_operand:SI 1 "general_operand" ""))] 191 "" 192{ 193 /* Need to force register if mem <- !reg. */ 194 if (MEM_P (operands[0]) && !REG_P (operands[1])) 195 operands[1] = force_reg (SImode, operands[1]); 196 197 /* If operands[1] is a large constant and cannot be performed 198 by a single instruction, we need to split it. */ 199 if (CONST_INT_P (operands[1]) 200 && !satisfies_constraint_Is20 (operands[1]) 201 && !satisfies_constraint_Ihig (operands[1])) 202 { 203 rtx high20_rtx; 204 HOST_WIDE_INT low12_int; 205 rtx tmp_rtx; 206 207 tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 208 209 high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode); 210 low12_int = INTVAL (operands[1]) & 0xfff; 211 212 emit_move_insn (tmp_rtx, high20_rtx); 213 emit_move_insn (operands[0], plus_constant (SImode, 214 tmp_rtx, 215 low12_int)); 216 DONE; 217 } 218 219 if ((REG_P (operands[0]) || GET_CODE (operands[0]) == SUBREG) 220 && SYMBOLIC_CONST_P (operands[1])) 221 { 222 if (TARGET_ICT_MODEL_LARGE 223 && nds32_indirect_call_referenced_p (operands[1])) 224 { 225 nds32_expand_ict_move (operands); 226 DONE; 227 } 228 else if (nds32_tls_referenced_p (operands [1])) 229 { 230 nds32_expand_tls_move (operands); 231 DONE; 232 } 233 else if (flag_pic) 234 { 235 nds32_expand_pic_move (operands); 236 DONE; 237 } 238 } 239}) 240 241(define_insn "*mov<mode>" 242 [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r,U45,U33,U37,U45, m, l, l, l, d, d, r, d, r, r, r, *f, *f, r, *f, Q") 243 (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r,U45,U33,U37,U45,Ufe, m,Ip05, Is05, Is20, Ihig, *f, r, *f, Q, *f"))] 244 "register_operand(operands[0], <MODE>mode) 245 || register_operand(operands[1], <MODE>mode)" 246{ 247 switch (which_alternative) 248 { 249 case 0: 250 return "mov55\t%0, %1"; 251 case 1: 252 return "ori\t%0, %1, 0"; 253 case 2: 254 case 3: 255 case 4: 256 case 5: 257 return nds32_output_16bit_store (operands, <byte>); 258 case 6: 259 return nds32_output_32bit_store (operands, <byte>); 260 case 7: 261 case 8: 262 case 9: 263 case 10: 264 case 11: 265 return nds32_output_16bit_load (operands, <byte>); 266 case 12: 267 return nds32_output_32bit_load (operands, <byte>); 268 case 13: 269 return "movpi45\t%0, %1"; 270 case 14: 271 return "movi55\t%0, %1"; 272 case 15: 273 return "movi\t%0, %1"; 274 case 16: 275 return "sethi\t%0, hi20(%1)"; 276 case 17: 277 if (TARGET_FPU_SINGLE) 278 return "fcpyss\t%0, %1, %1"; 279 else 280 return "#"; 281 case 18: 282 return "fmtsr\t%1, %0"; 283 case 19: 284 return "fmfsr\t%0, %1"; 285 case 20: 286 return nds32_output_float_load (operands); 287 case 21: 288 return nds32_output_float_store (operands); 289 default: 290 gcc_unreachable (); 291 } 292} 293 [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,load,alu,alu,alu,alu,fcpy,fmtsr,fmfsr,fload,fstore") 294 (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4") 295 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v3m, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")]) 296 297 298;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF 299;; are able to match such instruction template. 300(define_insn "move_addr" 301 [(set (match_operand:SI 0 "nds32_general_register_operand" "=l, r") 302 (match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))] 303 "" 304 "la\t%0, %1" 305 [(set_attr "type" "alu") 306 (set_attr "length" "8")]) 307 308 309(define_insn "sethi" 310 [(set (match_operand:SI 0 "register_operand" "=r") 311 (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))] 312 "" 313 "sethi\t%0, hi20(%1)" 314 [(set_attr "type" "alu") 315 (set_attr "length" "4")]) 316 317 318(define_insn "lo_sum" 319 [(set (match_operand:SI 0 "register_operand" "=r") 320 (lo_sum:SI (match_operand:SI 1 "register_operand" " r") 321 (match_operand:SI 2 "nds32_symbolic_operand" " i")))] 322 "" 323 "ori\t%0, %1, lo12(%2)" 324 [(set_attr "type" "alu") 325 (set_attr "length" "4")]) 326 327 328;; ---------------------------------------------------------------------------- 329 330;; Zero extension instructions. 331 332(define_insn "zero_extend<mode>si2" 333 [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r") 334 (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33, m")))] 335 "" 336{ 337 switch (which_alternative) 338 { 339 case 0: 340 return "ze<size>33\t%0, %1"; 341 case 1: 342 return "ze<size>\t%0, %1"; 343 case 2: 344 return nds32_output_16bit_load (operands, <byte>); 345 case 3: 346 return nds32_output_32bit_load (operands, <byte>); 347 348 default: 349 gcc_unreachable (); 350 } 351} 352 [(set_attr "type" "alu,alu,load,load") 353 (set_attr "length" " 2, 4, 2, 4")]) 354 355 356;; Sign extension instructions. 357 358(define_insn "extend<mode>si2" 359 [(set (match_operand:SI 0 "register_operand" "=l, r, r") 360 (sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))] 361 "" 362{ 363 switch (which_alternative) 364 { 365 case 0: 366 return "se<size>33\t%0, %1"; 367 case 1: 368 return "se<size>\t%0, %1"; 369 case 2: 370 return nds32_output_32bit_load_s (operands, <byte>); 371 372 default: 373 gcc_unreachable (); 374 } 375} 376 [(set_attr "type" "alu,alu,load") 377 (set_attr "length" " 2, 4, 4")]) 378 379 380;; ---------------------------------------------------------------------------- 381(define_expand "extv" 382 [(set (match_operand 0 "register_operand" "") 383 (sign_extract (match_operand 1 "nonimmediate_operand" "") 384 (match_operand 2 "const_int_operand" "") 385 (match_operand 3 "const_int_operand" "")))] 386 "" 387{ 388 enum nds32_expand_result_type result = nds32_expand_extv (operands); 389 switch (result) 390 { 391 case EXPAND_DONE: 392 DONE; 393 break; 394 case EXPAND_FAIL: 395 FAIL; 396 break; 397 case EXPAND_CREATE_TEMPLATE: 398 break; 399 default: 400 gcc_unreachable (); 401 } 402}) 403 404(define_expand "insv" 405 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "") 406 (match_operand 1 "const_int_operand" "") 407 (match_operand 2 "const_int_operand" "")) 408 (match_operand 3 "register_operand" ""))] 409 "" 410{ 411 enum nds32_expand_result_type result = nds32_expand_insv (operands); 412 switch (result) 413 { 414 case EXPAND_DONE: 415 DONE; 416 break; 417 case EXPAND_FAIL: 418 FAIL; 419 break; 420 case EXPAND_CREATE_TEMPLATE: 421 break; 422 default: 423 gcc_unreachable (); 424 } 425}) 426 427;; Arithmetic instructions. 428 429(define_insn "addsi3" 430 [(set (match_operand:SI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r") 431 (plus:SI (match_operand:SI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r") 432 (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))] 433 "" 434{ 435 switch (which_alternative) 436 { 437 case 0: 438 /* addi Rt4,Rt4,-x ==> subi45 Rt4,x 439 where 0 <= x <= 31 */ 440 operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode); 441 return "subi45\t%0, %2"; 442 case 1: 443 /* addi Rt3,Ra3,-x ==> subi333 Rt3,Ra3,x 444 where 0 <= x <= 7 */ 445 operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode); 446 return "subi333\t%0, %1, %2"; 447 case 2: 448 return "addi45\t%0, %2"; 449 case 3: 450 return "addi333\t%0, %1, %2"; 451 case 4: 452 return "add45\t%0, %2"; 453 case 5: 454 return "add333\t%0, %1, %2"; 455 case 6: 456 return "addi10.sp\t%2"; 457 case 7: 458 return "addri36.sp\t%0, %2"; 459 case 8: 460 return "addi\t%0, %1, %2"; 461 case 9: 462 return "add\t%0, %1, %2"; 463 464 default: 465 gcc_unreachable (); 466 } 467} 468 [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") 469 (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4") 470 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v2, v1, v1, v1")]) 471 472(define_insn "subsi3" 473 [(set (match_operand:SI 0 "register_operand" "=d, l, r, r") 474 (minus:SI (match_operand:SI 1 "nds32_rimm15s_operand" " 0, l, Is15, r") 475 (match_operand:SI 2 "register_operand" " r, l, r, r")))] 476 "" 477 "@ 478 sub45\t%0, %2 479 sub333\t%0, %1, %2 480 subri\t%0, %2, %1 481 sub\t%0, %1, %2" 482 [(set_attr "type" "alu,alu,alu,alu") 483 (set_attr "length" " 2, 2, 4, 4")]) 484 485 486;; GCC intends to simplify (plus (ashift ...) (reg)) 487;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult' 488;; and needs to ensure it is exact_log2 value. 489(define_insn "*add_slli" 490 [(set (match_operand:SI 0 "register_operand" "=r") 491 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") 492 (match_operand:SI 2 "immediate_operand" " i")) 493 (match_operand:SI 3 "register_operand" " r")))] 494 "TARGET_ISA_V3 && optimize_size 495 && (exact_log2 (INTVAL (operands[2])) != -1) 496 && (exact_log2 (INTVAL (operands[2])) <= 31)" 497{ 498 /* Get floor_log2 of the immediate value 499 so that we can generate 'add_slli' instruction. */ 500 operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2]))); 501 502 return "add_slli\t%0, %3, %1, %2"; 503} 504 [(set_attr "type" "alu_shift") 505 (set_attr "combo" "2") 506 (set_attr "length" "4")]) 507 508(define_insn "*add_srli" 509 [(set (match_operand:SI 0 "register_operand" "= r") 510 (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") 511 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 512 (match_operand:SI 3 "register_operand" " r")))] 513 "TARGET_ISA_V3 && optimize_size" 514 "add_srli\t%0, %3, %1, %2" 515 [(set_attr "type" "alu_shift") 516 (set_attr "combo" "2") 517 (set_attr "length" "4")]) 518 519 520;; GCC intends to simplify (minus (reg) (ashift ...)) 521;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult' 522;; and needs to ensure it is exact_log2 value. 523(define_insn "*sub_slli" 524 [(set (match_operand:SI 0 "register_operand" "=r") 525 (minus:SI (match_operand:SI 1 "register_operand" " r") 526 (mult:SI (match_operand:SI 2 "register_operand" " r") 527 (match_operand:SI 3 "immediate_operand" " i"))))] 528 "TARGET_ISA_V3 && optimize_size 529 && (exact_log2 (INTVAL (operands[3])) != -1) 530 && (exact_log2 (INTVAL (operands[3])) <= 31)" 531{ 532 /* Get floor_log2 of the immediate value 533 so that we can generate 'sub_slli' instruction. */ 534 operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3]))); 535 536 return "sub_slli\t%0, %1, %2, %3"; 537} 538 [(set_attr "type" "alu_shift") 539 (set_attr "combo" "2") 540 (set_attr "length" "4")]) 541 542(define_insn "*sub_srli" 543 [(set (match_operand:SI 0 "register_operand" "= r") 544 (minus:SI (match_operand:SI 1 "register_operand" " r") 545 (lshiftrt:SI (match_operand:SI 2 "register_operand" " r") 546 (match_operand:SI 3 "nds32_imm5u_operand" " Iu05"))))] 547 "TARGET_ISA_V3 && optimize_size" 548 "sub_srli\t%0, %1, %2, %3" 549 [(set_attr "type" "alu_shift") 550 (set_attr "combo" "2") 551 (set_attr "length" "4")]) 552 553 554;; Multiplication instructions. 555 556(define_insn "mulsi3" 557 [(set (match_operand:SI 0 "register_operand" "=w, r") 558 (mult:SI (match_operand:SI 1 "register_operand" "%0, r") 559 (match_operand:SI 2 "register_operand" " w, r")))] 560 "" 561 "@ 562 mul33\t%0, %2 563 mul\t%0, %1, %2" 564 [(set_attr "type" "mul,mul") 565 (set_attr "length" " 2, 4") 566 (set_attr "feature" "v3m, v1")]) 567 568(define_insn "mulsidi3" 569 [(set (match_operand:DI 0 "register_operand" "=r") 570 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) 571 (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))] 572 "TARGET_ISA_V2 || TARGET_ISA_V3" 573 "mulsr64\t%0, %1, %2" 574 [(set_attr "type" "mul") 575 (set_attr "length" "4")]) 576 577(define_insn "umulsidi3" 578 [(set (match_operand:DI 0 "register_operand" "=r") 579 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r")) 580 (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))] 581 "TARGET_ISA_V2 || TARGET_ISA_V3" 582 "mulr64\t%0, %1, %2" 583 [(set_attr "type" "mul") 584 (set_attr "length" "4")]) 585 586 587;; Multiply-accumulate instructions. 588 589(define_insn "*maddr32_0" 590 [(set (match_operand:SI 0 "register_operand" "=r") 591 (plus:SI (match_operand:SI 3 "register_operand" " 0") 592 (mult:SI (match_operand:SI 1 "register_operand" " r") 593 (match_operand:SI 2 "register_operand" " r"))))] 594 "" 595 "maddr32\t%0, %1, %2" 596 [(set_attr "type" "mac") 597 (set_attr "length" "4")]) 598 599(define_insn "*maddr32_1" 600 [(set (match_operand:SI 0 "register_operand" "=r") 601 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") 602 (match_operand:SI 2 "register_operand" " r")) 603 (match_operand:SI 3 "register_operand" " 0")))] 604 "" 605 "maddr32\t%0, %1, %2" 606 [(set_attr "type" "mac") 607 (set_attr "length" "4")]) 608 609(define_insn "*msubr32" 610 [(set (match_operand:SI 0 "register_operand" "=r") 611 (minus:SI (match_operand:SI 3 "register_operand" " 0") 612 (mult:SI (match_operand:SI 1 "register_operand" " r") 613 (match_operand:SI 2 "register_operand" " r"))))] 614 "" 615 "msubr32\t%0, %1, %2" 616 [(set_attr "type" "mac") 617 (set_attr "length" "4")]) 618 619 620;; Div Instructions. 621 622(define_insn "divmodsi4" 623 [(set (match_operand:SI 0 "register_operand" "=r") 624 (div:SI (match_operand:SI 1 "register_operand" " r") 625 (match_operand:SI 2 "register_operand" " r"))) 626 (set (match_operand:SI 3 "register_operand" "=r") 627 (mod:SI (match_dup 1) (match_dup 2)))] 628 "" 629 "divsr\t%0, %3, %1, %2" 630 [(set_attr "type" "div") 631 (set_attr "length" "4")]) 632 633(define_insn "udivmodsi4" 634 [(set (match_operand:SI 0 "register_operand" "=r") 635 (udiv:SI (match_operand:SI 1 "register_operand" " r") 636 (match_operand:SI 2 "register_operand" " r"))) 637 (set (match_operand:SI 3 "register_operand" "=r") 638 (umod:SI (match_dup 1) (match_dup 2)))] 639 "" 640 "divr\t%0, %3, %1, %2" 641 [(set_attr "type" "div") 642 (set_attr "length" "4")]) 643 644;; divsr/divr will keep quotient only when quotient and remainder is the same 645;; register in our ISA spec, it's can reduce 1 register presure if we don't 646;; want remainder. 647(define_insn "divsi4" 648 [(set (match_operand:SI 0 "register_operand" "=r") 649 (div:SI (match_operand:SI 1 "register_operand" " r") 650 (match_operand:SI 2 "register_operand" " r")))] 651 "" 652 "divsr\t%0, %0, %1, %2" 653 [(set_attr "type" "div") 654 (set_attr "length" "4")]) 655 656(define_insn "udivsi4" 657 [(set (match_operand:SI 0 "register_operand" "=r") 658 (udiv:SI (match_operand:SI 1 "register_operand" " r") 659 (match_operand:SI 2 "register_operand" " r")))] 660 "" 661 "divr\t%0, %0, %1, %2" 662 [(set_attr "type" "div") 663 (set_attr "length" "4")]) 664 665;; ---------------------------------------------------------------------------- 666 667;; Boolean instructions. 668;; Note: We define the DImode versions in nds32-doubleword.md. 669 670;; ---------------------------------------------------------------------------- 671;; 'AND' operation 672;; ---------------------------------------------------------------------------- 673 674(define_insn "bitc" 675 [(set (match_operand:SI 0 "register_operand" "=r") 676 (and:SI (not:SI (match_operand:SI 1 "register_operand" " r")) 677 (match_operand:SI 2 "register_operand" " r")))] 678 "TARGET_ISA_V3" 679 "bitc\t%0, %2, %1" 680 [(set_attr "type" "alu") 681 (set_attr "length" "4")] 682) 683 684(define_expand "andsi3" 685 [(set (match_operand:SI 0 "register_operand" "") 686 (and:SI (match_operand:SI 1 "register_operand" "") 687 (match_operand:SI 2 "nds32_reg_constant_operand" "")))] 688 "" 689{ 690 if (CONST_INT_P (operands[2]) 691 && !nds32_and_operand (operands[2], SImode)) 692 { 693 nds32_expand_constant (SImode, INTVAL (operands[2]), 694 operands[0], operands[1]); 695 DONE; 696 } 697}) 698 699(define_insn "*andsi3" 700 [(set (match_operand:SI 0 "register_operand" "=l, r, l, l, l, l, l, l, r, r, r, r, r") 701 (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r") 702 (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))] 703 "" 704{ 705 HOST_WIDE_INT mask = INTVAL (operands[2]); 706 707 /* 16-bit andi instructions: 708 andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3 709 andi Rt3,Ra3,0xffff -> zeh33 Rt3,Ra3 710 andi Rt3,Ra3,0x01 -> xlsb33 Rt3,Ra3 711 andi Rt3,Ra3,0x7ff -> x11b33 Rt3,Ra3 712 andi Rt3,Rt3,2^imm3u -> bmski33 Rt3,imm3u 713 andi Rt3,Rt3,(2^(imm3u+1))-1 -> fexti33 Rt3,imm3u. */ 714 715 switch (which_alternative) 716 { 717 case 0: 718 return "and33\t%0, %2"; 719 case 1: 720 return "and\t%0, %1, %2"; 721 case 2: 722 return "zeb33\t%0, %1"; 723 case 3: 724 return "zeh33\t%0, %1"; 725 case 4: 726 return "xlsb33\t%0, %1"; 727 case 5: 728 return "x11b33\t%0, %1"; 729 case 6: 730 return "bmski33\t%0, %B2"; 731 case 7: 732 operands[2] = GEN_INT (floor_log2 (mask + 1) - 1); 733 return "fexti33\t%0, %2"; 734 case 8: 735 return "zeb\t%0, %1"; 736 case 9: 737 return "zeh\t%0, %1"; 738 case 10: 739 return "andi\t%0, %1, %2"; 740 case 11: 741 operands[2] = GEN_INT (~mask); 742 return "bitci\t%0, %1, %2"; 743 case 12: 744 return "bclr\t%0, %1, %b2"; 745 746 default: 747 gcc_unreachable (); 748 } 749} 750 [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") 751 (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4") 752 (set_attr "feature" "v3m, v1, v1, v1, v1, v1,v3m,v3m, v1, v1, v1, v3,pe1")]) 753 754(define_insn "*and_slli" 755 [(set (match_operand:SI 0 "register_operand" "= r") 756 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") 757 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 758 (match_operand:SI 3 "register_operand" " r")))] 759 "TARGET_ISA_V3 && optimize_size" 760 "and_slli\t%0, %3, %1, %2" 761 [(set_attr "type" "alu_shift") 762 (set_attr "length" "4")]) 763 764(define_insn "*and_srli" 765 [(set (match_operand:SI 0 "register_operand" "= r") 766 (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") 767 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 768 (match_operand:SI 3 "register_operand" " r")))] 769 "TARGET_ISA_V3 && optimize_size" 770 "and_srli\t%0, %3, %1, %2" 771 [(set_attr "type" "alu_shift") 772 (set_attr "length" "4")]) 773 774 775;; ---------------------------------------------------------------------------- 776;; 'OR' operation 777;; ---------------------------------------------------------------------------- 778 779;; For V3/V3M ISA, we have 'or33' instruction. 780;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2. 781 782(define_expand "iorsi3" 783 [(set (match_operand:SI 0 "register_operand" "") 784 (ior:SI (match_operand:SI 1 "register_operand" "") 785 (match_operand:SI 2 "general_operand" "")))] 786 "" 787{ 788 if (!nds32_ior_operand (operands[2], SImode)) 789 operands[2] = force_reg (SImode, operands[2]); 790}) 791 792(define_insn "*iorsi3" 793 [(set (match_operand:SI 0 "register_operand" "=l, r, r, r") 794 (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") 795 (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))] 796 "" 797 "@ 798 or33\t%0, %2 799 or\t%0, %1, %2 800 ori\t%0, %1, %2 801 bset\t%0, %1, %B2" 802 [(set_attr "type" "alu,alu,alu,alu") 803 (set_attr "length" " 2, 4, 4, 4") 804 (set_attr "feature" "v3m, v1, v1,pe1")]) 805 806(define_insn "*or_slli" 807 [(set (match_operand:SI 0 "register_operand" "= r") 808 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") 809 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 810 (match_operand:SI 3 "register_operand" " r")))] 811 "TARGET_ISA_V3 && optimize_size" 812 "or_slli\t%0, %3, %1, %2" 813 [(set_attr "type" "alu_shift") 814 (set_attr "length" "4")]) 815 816(define_insn "*or_srli" 817 [(set (match_operand:SI 0 "register_operand" "= r") 818 (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") 819 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 820 (match_operand:SI 3 "register_operand" " r")))] 821 "TARGET_ISA_V3 && optimize_size" 822 "or_srli\t%0, %3, %1, %2" 823 [(set_attr "type" "alu_shift") 824 (set_attr "length" "4")]) 825 826 827;; ---------------------------------------------------------------------------- 828;; 'XOR' operation 829;; ---------------------------------------------------------------------------- 830 831;; For V3/V3M ISA, we have 'xor33' instruction. 832;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2. 833 834(define_expand "xorsi3" 835 [(set (match_operand:SI 0 "register_operand" "") 836 (xor:SI (match_operand:SI 1 "register_operand" "") 837 (match_operand:SI 2 "general_operand" "")))] 838 "" 839{ 840 if (!nds32_xor_operand (operands[2], SImode)) 841 operands[2] = force_reg (SImode, operands[2]); 842}) 843 844(define_insn "*xorsi3" 845 [(set (match_operand:SI 0 "register_operand" "=l, r, r, r") 846 (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") 847 (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))] 848 "" 849 "@ 850 xor33\t%0, %2 851 xor\t%0, %1, %2 852 xori\t%0, %1, %2 853 btgl\t%0, %1, %B2" 854 [(set_attr "type" "alu,alu,alu,alu") 855 (set_attr "length" " 2, 4, 4, 4") 856 (set_attr "feature" "v3m, v1, v1,pe1")]) 857 858(define_insn "*xor_slli" 859 [(set (match_operand:SI 0 "register_operand" "= r") 860 (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") 861 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 862 (match_operand:SI 3 "register_operand" " r")))] 863 "TARGET_ISA_V3 && optimize_size" 864 "xor_slli\t%0, %3, %1, %2" 865 [(set_attr "type" "alu_shift") 866 (set_attr "length" "4")]) 867 868(define_insn "*xor_srli" 869 [(set (match_operand:SI 0 "register_operand" "= r") 870 (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") 871 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) 872 (match_operand:SI 3 "register_operand" " r")))] 873 "TARGET_ISA_V3 && optimize_size" 874 "xor_srli\t%0, %3, %1, %2" 875 [(set_attr "type" "alu_shift") 876 (set_attr "length" "4")]) 877 878;; Rotate Right Instructions. 879 880(define_insn "*rotrsi3" 881 [(set (match_operand:SI 0 "register_operand" "= r, r") 882 (rotatert:SI (match_operand:SI 1 "register_operand" " r, r") 883 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))] 884 "" 885 "@ 886 rotri\t%0, %1, %2 887 rotr\t%0, %1, %2" 888 [(set_attr "type" " alu, alu") 889 (set_attr "subtype" "shift,shift") 890 (set_attr "length" " 4, 4")]) 891 892 893;; ---------------------------------------------------------------------------- 894;; 'NEG' operation 895;; ---------------------------------------------------------------------------- 896 897;; For V3/V3M ISA, we have 'neg33' instruction. 898;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2. 899;; And for V2 ISA, there is NO 'neg33' instruction. 900;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B'). 901(define_insn "negsi2" 902 [(set (match_operand:SI 0 "register_operand" "=l, r") 903 (neg:SI (match_operand:SI 1 "register_operand" " l, r")))] 904 "" 905 "@ 906 neg33\t%0, %1 907 subri\t%0, %1, 0" 908 [(set_attr "type" "alu,alu") 909 (set_attr "length" " 2, 4") 910 (set_attr "feature" "v3m, v1")]) 911 912(define_expand "negsf2" 913 [(set (match_operand:SF 0 "register_operand" "") 914 (neg:SF (match_operand:SF 1 "register_operand" "")))] 915 "" 916{ 917 if (!TARGET_FPU_SINGLE && !TARGET_EXT_PERF) 918 { 919 rtx new_dst = simplify_gen_subreg (SImode, operands[0], SFmode, 0); 920 rtx new_src = simplify_gen_subreg (SImode, operands[1], SFmode, 0); 921 922 emit_insn (gen_xorsi3 (new_dst, 923 new_src, 924 gen_int_mode (0x80000000, SImode))); 925 926 DONE; 927 } 928}) 929 930(define_expand "negdf2" 931 [(set (match_operand:DF 0 "register_operand" "") 932 (neg:DF (match_operand:DF 1 "register_operand" "")))] 933 "" 934{ 935}) 936 937(define_insn_and_split "soft_negdf2" 938 [(set (match_operand:DF 0 "register_operand" "") 939 (neg:DF (match_operand:DF 1 "register_operand" "")))] 940 "!TARGET_FPU_DOUBLE" 941 "#" 942 "!TARGET_FPU_DOUBLE" 943 [(const_int 1)] 944{ 945 rtx src = operands[1]; 946 rtx dst = operands[0]; 947 rtx ori_dst = operands[0]; 948 949 bool need_extra_move_for_dst_p; 950 /* FPU register can't change mode to SI directly, so we need create a 951 tmp register to handle it, and FPU register can't do `xor` or btgl. */ 952 if (HARD_REGISTER_P (src) 953 && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (src))) 954 { 955 rtx tmp = gen_reg_rtx (DFmode); 956 emit_move_insn (tmp, src); 957 src = tmp; 958 } 959 960 if (HARD_REGISTER_P (dst) 961 && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (dst))) 962 { 963 need_extra_move_for_dst_p = true; 964 rtx tmp = gen_reg_rtx (DFmode); 965 dst = tmp; 966 } 967 968 rtx dst_high_part = simplify_gen_subreg ( 969 SImode, dst, 970 DFmode, subreg_highpart_offset (SImode, DFmode)); 971 rtx dst_low_part = simplify_gen_subreg ( 972 SImode, dst, 973 DFmode, subreg_lowpart_offset (SImode, DFmode)); 974 rtx src_high_part = simplify_gen_subreg ( 975 SImode, src, 976 DFmode, subreg_highpart_offset (SImode, DFmode)); 977 rtx src_low_part = simplify_gen_subreg ( 978 SImode, src, 979 DFmode, subreg_lowpart_offset (SImode, DFmode)); 980 981 emit_insn (gen_xorsi3 (dst_high_part, 982 src_high_part, 983 gen_int_mode (0x80000000, SImode))); 984 emit_move_insn (dst_low_part, src_low_part); 985 986 if (need_extra_move_for_dst_p) 987 emit_move_insn (ori_dst, dst); 988 989 DONE; 990}) 991 992 993;; ---------------------------------------------------------------------------- 994;; 'ONE_COMPLIMENT' operation 995;; ---------------------------------------------------------------------------- 996 997;; For V3/V3M ISA, we have 'not33' instruction. 998;; So we can identify 'not Rt3,Ra3' case and set its length to be 2. 999(define_insn "one_cmplsi2" 1000 [(set (match_operand:SI 0 "register_operand" "=w, r") 1001 (not:SI (match_operand:SI 1 "register_operand" " w, r")))] 1002 "" 1003 "@ 1004 not33\t%0, %1 1005 nor\t%0, %1, %1" 1006 [(set_attr "type" "alu,alu") 1007 (set_attr "length" " 2, 4") 1008 (set_attr "feature" "v3m, v1")]) 1009 1010 1011;; ---------------------------------------------------------------------------- 1012 1013;; Shift instructions. 1014 1015(define_expand "<shift>si3" 1016 [(set (match_operand:SI 0 "register_operand" "") 1017 (shift_rotate:SI (match_operand:SI 1 "register_operand" "") 1018 (match_operand:SI 2 "nds32_rimm5u_operand" "")))] 1019 "" 1020{ 1021 if (operands[2] == const0_rtx) 1022 { 1023 emit_move_insn (operands[0], operands[1]); 1024 DONE; 1025 } 1026}) 1027 1028(define_insn "*ashlsi3" 1029 [(set (match_operand:SI 0 "register_operand" "= l, r, r") 1030 (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r") 1031 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))] 1032 "" 1033 "@ 1034 slli333\t%0, %1, %2 1035 slli\t%0, %1, %2 1036 sll\t%0, %1, %2" 1037 [(set_attr "type" " alu, alu, alu") 1038 (set_attr "subtype" "shift,shift,shift") 1039 (set_attr "length" " 2, 4, 4")]) 1040 1041(define_insn "*ashrsi3" 1042 [(set (match_operand:SI 0 "register_operand" "= d, r, r") 1043 (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") 1044 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))] 1045 "" 1046 "@ 1047 srai45\t%0, %2 1048 srai\t%0, %1, %2 1049 sra\t%0, %1, %2" 1050 [(set_attr "type" " alu, alu, alu") 1051 (set_attr "subtype" "shift,shift,shift") 1052 (set_attr "length" " 2, 4, 4")]) 1053 1054(define_insn "*lshrsi3" 1055 [(set (match_operand:SI 0 "register_operand" "= d, r, r") 1056 (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") 1057 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))] 1058 "" 1059 "@ 1060 srli45\t%0, %2 1061 srli\t%0, %1, %2 1062 srl\t%0, %1, %2" 1063 [(set_attr "type" " alu, alu, alu") 1064 (set_attr "subtype" "shift,shift,shift") 1065 (set_attr "length" " 2, 4, 4")]) 1066 1067 1068;; ---------------------------------------------------------------------------- 1069 1070;; ---------------------------------------------------------------------------- 1071;; Conditional Move patterns 1072;; ---------------------------------------------------------------------------- 1073 1074(define_expand "mov<mode>cc" 1075 [(set (match_operand:QIHISI 0 "register_operand" "") 1076 (if_then_else:QIHISI (match_operand 1 "nds32_movecc_comparison_operator" "") 1077 (match_operand:QIHISI 2 "register_operand" "") 1078 (match_operand:QIHISI 3 "register_operand" "")))] 1079 "TARGET_CMOV && !optimize_size" 1080{ 1081 enum nds32_expand_result_type result = nds32_expand_movcc (operands); 1082 switch (result) 1083 { 1084 case EXPAND_DONE: 1085 DONE; 1086 break; 1087 case EXPAND_FAIL: 1088 FAIL; 1089 break; 1090 case EXPAND_CREATE_TEMPLATE: 1091 break; 1092 default: 1093 gcc_unreachable (); 1094 } 1095}) 1096 1097(define_insn "cmovz<mode>" 1098 [(set (match_operand:QIHISI 0 "register_operand" "=r, r") 1099 (if_then_else:QIHISI (eq (match_operand:SI 1 "register_operand" " r, r") 1100 (const_int 0)) 1101 (match_operand:QIHISI 2 "register_operand" " r, 0") 1102 (match_operand:QIHISI 3 "register_operand" " 0, r")))] 1103 "TARGET_CMOV" 1104 "@ 1105 cmovz\t%0, %2, %1 1106 cmovn\t%0, %3, %1" 1107 [(set_attr "type" "alu") 1108 (set_attr "length" "4")]) 1109 1110(define_insn "cmovn<mode>" 1111 [(set (match_operand:QIHISI 0 "register_operand" "=r, r") 1112 (if_then_else:QIHISI (ne (match_operand:SI 1 "register_operand" " r, r") 1113 (const_int 0)) 1114 (match_operand:QIHISI 2 "register_operand" " r, 0") 1115 (match_operand:QIHISI 3 "register_operand" " 0, r")))] 1116 "TARGET_CMOV" 1117 "@ 1118 cmovn\t%0, %2, %1 1119 cmovz\t%0, %3, %1" 1120 [(set_attr "type" "alu") 1121 (set_attr "length" "4")]) 1122 1123;; A hotfix to help RTL combiner to merge a cmovn insn and a zero_extend insn. 1124;; It should be removed once after we change the expansion form of the cmovn. 1125(define_insn "*cmovn_simplified_<mode>" 1126 [(set (match_operand:QIHISI 0 "register_operand" "=r") 1127 (if_then_else:QIHISI (match_operand:SI 1 "register_operand" "r") 1128 (match_operand:QIHISI 2 "register_operand" "r") 1129 (match_operand:QIHISI 3 "register_operand" "0")))] 1130 "" 1131 "cmovn\t%0, %2, %1" 1132 [(set_attr "type" "alu")]) 1133 1134;; ---------------------------------------------------------------------------- 1135;; Conditional Branch patterns 1136;; ---------------------------------------------------------------------------- 1137 1138(define_expand "cbranchsi4" 1139 [(set (pc) 1140 (if_then_else (match_operator 0 "comparison_operator" 1141 [(match_operand:SI 1 "register_operand" "") 1142 (match_operand:SI 2 "nds32_reg_constant_operand" "")]) 1143 (label_ref (match_operand 3 "" "")) 1144 (pc)))] 1145 "" 1146{ 1147 enum nds32_expand_result_type result = nds32_expand_cbranch (operands); 1148 switch (result) 1149 { 1150 case EXPAND_DONE: 1151 DONE; 1152 break; 1153 case EXPAND_FAIL: 1154 FAIL; 1155 break; 1156 case EXPAND_CREATE_TEMPLATE: 1157 break; 1158 default: 1159 gcc_unreachable (); 1160 } 1161}) 1162 1163 1164(define_insn "cbranchsi4_equality_zero" 1165 [(set (pc) 1166 (if_then_else (match_operator 0 "nds32_equality_comparison_operator" 1167 [(match_operand:SI 1 "register_operand" "t,l, r") 1168 (const_int 0)]) 1169 (label_ref (match_operand 2 "" "")) 1170 (pc)))] 1171 "" 1172{ 1173 return nds32_output_cbranchsi4_equality_zero (insn, operands); 1174} 1175 [(set_attr "type" "branch") 1176 (set_attr_alternative "enabled" 1177 [ 1178 ;; Alternative 0 1179 (if_then_else (match_test "TARGET_16_BIT") 1180 (const_string "yes") 1181 (const_string "no")) 1182 ;; Alternative 1 1183 (if_then_else (match_test "TARGET_16_BIT") 1184 (const_string "yes") 1185 (const_string "no")) 1186 ;; Alternative 2 1187 (const_string "yes") 1188 ]) 1189 (set_attr_alternative "length" 1190 [ 1191 ;; Alternative 0 1192 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1193 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 1194 (le (minus (match_dup 2) (pc)) (const_int 250))) 1195 (if_then_else (match_test "TARGET_16_BIT") 1196 (const_int 2) 1197 (const_int 4)) 1198 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) 1199 (le (minus (match_dup 2) (pc)) (const_int 65500))) 1200 (const_int 4) 1201 (if_then_else (match_test "TARGET_16_BIT") 1202 (const_int 8) 1203 (const_int 10)))) 1204 (const_int 10)) 1205 ;; Alternative 1 1206 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1207 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 1208 (le (minus (match_dup 2) (pc)) (const_int 250))) 1209 (if_then_else (match_test "TARGET_16_BIT") 1210 (const_int 2) 1211 (const_int 4)) 1212 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) 1213 (le (minus (match_dup 2) (pc)) (const_int 65500))) 1214 (const_int 4) 1215 (if_then_else (match_test "TARGET_16_BIT") 1216 (const_int 8) 1217 (const_int 10)))) 1218 (const_int 10)) 1219 ;; Alternative 2 1220 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1221 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) 1222 (le (minus (match_dup 2) (pc)) (const_int 65500))) 1223 (const_int 4) 1224 (const_int 10)) 1225 (const_int 10)) 1226 ])]) 1227 1228 1229;; This pattern is dedicated to V2 ISA, 1230;; because V2 DOES NOT HAVE beqc/bnec instruction. 1231(define_insn "cbranchsi4_equality_reg" 1232 [(set (pc) 1233 (if_then_else (match_operator 0 "nds32_equality_comparison_operator" 1234 [(match_operand:SI 1 "register_operand" "v, r") 1235 (match_operand:SI 2 "register_operand" "l, r")]) 1236 (label_ref (match_operand 3 "" "")) 1237 (pc)))] 1238 "TARGET_ISA_V2" 1239{ 1240 return nds32_output_cbranchsi4_equality_reg (insn, operands); 1241} 1242 [(set_attr "type" "branch") 1243 (set_attr_alternative "enabled" 1244 [ 1245 ;; Alternative 0 1246 (if_then_else (match_test "TARGET_16_BIT") 1247 (const_string "yes") 1248 (const_string "no")) 1249 ;; Alternative 1 1250 (const_string "yes") 1251 ]) 1252 (set_attr_alternative "length" 1253 [ 1254 ;; Alternative 0 1255 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1256 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1257 (le (minus (match_dup 3) (pc)) (const_int 250))) 1258 (const_int 2) 1259 (if_then_else (and (ge (minus (match_dup 3) (pc)) 1260 (const_int -16350)) 1261 (le (minus (match_dup 3) (pc)) 1262 (const_int 16350))) 1263 (const_int 4) 1264 (const_int 8))) 1265 (const_int 8)) 1266 ;; Alternative 1 1267 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1268 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) 1269 (le (minus (match_dup 3) (pc)) (const_int 16350))) 1270 (const_int 4) 1271 (const_int 10)) 1272 (const_int 10)) 1273 ])]) 1274 1275 1276;; This pattern is dedicated to V3/V3M, 1277;; because V3/V3M DO HAVE beqc/bnec instruction. 1278(define_insn "cbranchsi4_equality_reg_or_const_int" 1279 [(set (pc) 1280 (if_then_else (match_operator 0 "nds32_equality_comparison_operator" 1281 [(match_operand:SI 1 "register_operand" "v, r, r") 1282 (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")]) 1283 (label_ref (match_operand 3 "" "")) 1284 (pc)))] 1285 "TARGET_ISA_V3 || TARGET_ISA_V3M" 1286{ 1287 return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands); 1288} 1289 [(set_attr "type" "branch") 1290 (set_attr_alternative "enabled" 1291 [ 1292 ;; Alternative 0 1293 (if_then_else (match_test "TARGET_16_BIT") 1294 (const_string "yes") 1295 (const_string "no")) 1296 ;; Alternative 1 1297 (const_string "yes") 1298 ;; Alternative 2 1299 (const_string "yes") 1300 ]) 1301 (set_attr_alternative "length" 1302 [ 1303 ;; Alternative 0 1304 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1305 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1306 (le (minus (match_dup 3) (pc)) (const_int 250))) 1307 (const_int 2) 1308 (if_then_else (and (ge (minus (match_dup 3) (pc)) 1309 (const_int -16350)) 1310 (le (minus (match_dup 3) (pc)) 1311 (const_int 16350))) 1312 (const_int 4) 1313 (const_int 8))) 1314 (const_int 8)) 1315 ;; Alternative 1 1316 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1317 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) 1318 (le (minus (match_dup 3) (pc)) (const_int 16350))) 1319 (const_int 4) 1320 (const_int 10)) 1321 (const_int 10)) 1322 ;; Alternative 2 1323 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1324 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1325 (le (minus (match_dup 3) (pc)) (const_int 250))) 1326 (const_int 4) 1327 (const_int 10)) 1328 (const_int 10)) 1329 ])]) 1330 1331 1332(define_insn "*cbranchsi4_greater_less_zero" 1333 [(set (pc) 1334 (if_then_else (match_operator 0 "nds32_greater_less_comparison_operator" 1335 [(match_operand:SI 1 "register_operand" "r") 1336 (const_int 0)]) 1337 (label_ref (match_operand 2 "" "")) 1338 (pc)))] 1339 "" 1340{ 1341 return nds32_output_cbranchsi4_greater_less_zero (insn, operands); 1342} 1343 [(set_attr "type" "branch") 1344 (set (attr "length") 1345 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1346 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) 1347 (le (minus (match_dup 2) (pc)) (const_int 65500))) 1348 (const_int 4) 1349 (const_int 10)) 1350 (const_int 10)))]) 1351 1352 1353(define_expand "cstoresi4" 1354 [(set (match_operand:SI 0 "register_operand" "") 1355 (match_operator:SI 1 "comparison_operator" 1356 [(match_operand:SI 2 "register_operand" "") 1357 (match_operand:SI 3 "nonmemory_operand" "")]))] 1358 "" 1359{ 1360 enum nds32_expand_result_type result = nds32_expand_cstore (operands); 1361 switch (result) 1362 { 1363 case EXPAND_DONE: 1364 DONE; 1365 break; 1366 case EXPAND_FAIL: 1367 FAIL; 1368 break; 1369 case EXPAND_CREATE_TEMPLATE: 1370 break; 1371 default: 1372 gcc_unreachable (); 1373 } 1374}) 1375 1376 1377(define_expand "slts_compare" 1378 [(set (match_operand:SI 0 "register_operand" "") 1379 (lt:SI (match_operand:SI 1 "general_operand" "") 1380 (match_operand:SI 2 "general_operand" "")))] 1381 "" 1382{ 1383 if (!REG_P (operands[1])) 1384 operands[1] = force_reg (SImode, operands[1]); 1385 1386 if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2])) 1387 operands[2] = force_reg (SImode, operands[2]); 1388}) 1389 1390(define_insn "slts_compare_impl" 1391 [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") 1392 (lt:SI (match_operand:SI 1 "register_operand" " d, d, r, r") 1393 (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))] 1394 "" 1395 "@ 1396 slts45\t%1, %2 1397 sltsi45\t%1, %2 1398 slts\t%0, %1, %2 1399 sltsi\t%0, %1, %2" 1400 [(set_attr "type" "alu, alu, alu, alu") 1401 (set_attr "length" " 2, 2, 4, 4")]) 1402 1403(define_insn "slt_eq0" 1404 [(set (match_operand:SI 0 "register_operand" "=t, r") 1405 (eq:SI (match_operand:SI 1 "register_operand" " d, r") 1406 (const_int 0)))] 1407 "" 1408 "@ 1409 slti45\t%1, 1 1410 slti\t%0, %1, 1" 1411 [(set_attr "type" "alu, alu") 1412 (set_attr "length" " 2, 4")]) 1413 1414(define_expand "slt_compare" 1415 [(set (match_operand:SI 0 "register_operand" "") 1416 (ltu:SI (match_operand:SI 1 "general_operand" "") 1417 (match_operand:SI 2 "general_operand" "")))] 1418 "" 1419{ 1420 if (!REG_P (operands[1])) 1421 operands[1] = force_reg (SImode, operands[1]); 1422 1423 if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2])) 1424 operands[2] = force_reg (SImode, operands[2]); 1425}) 1426 1427(define_insn "slt_compare_impl" 1428 [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") 1429 (ltu:SI (match_operand:SI 1 "register_operand" " d, d, r, r") 1430 (match_operand:SI 2 "nds32_rimm15s_operand" " r, Iu05, r, Is15")))] 1431 "" 1432 "@ 1433 slt45\t%1, %2 1434 slti45\t%1, %2 1435 slt\t%0, %1, %2 1436 slti\t%0, %1, %2" 1437 [(set_attr "type" "alu, alu, alu, alu") 1438 (set_attr "length" " 2, 2, 4, 4")]) 1439 1440 1441;; ---------------------------------------------------------------------------- 1442 1443;; Unconditional and other jump instructions. 1444 1445(define_insn "jump" 1446 [(set (pc) (label_ref (match_operand 0 "" "")))] 1447 "" 1448{ 1449 /* This unconditional jump has two forms: 1450 32-bit instruction => j imm24s << 1 1451 16-bit instruction => j8 imm8s << 1 1452 1453 For 32-bit case, 1454 we assume it is always reachable. 1455 For 16-bit case, 1456 it must satisfy { 255 >= (label - pc) >= -256 } condition. 1457 However, since the $pc for nds32 is at the beginning of the instruction, 1458 we should leave some length space for current insn. 1459 So we use range -250 ~ 250. */ 1460 switch (get_attr_length (insn)) 1461 { 1462 case 2: 1463 return "j8\t%0"; 1464 case 4: 1465 return "j\t%0"; 1466 default: 1467 gcc_unreachable (); 1468 } 1469} 1470 [(set_attr "type" "branch") 1471 (set_attr "enabled" "yes") 1472 (set (attr "length") 1473 (if_then_else (match_test "!CROSSING_JUMP_P (insn)") 1474 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250)) 1475 (le (minus (match_dup 0) (pc)) (const_int 250))) 1476 (if_then_else (match_test "TARGET_16_BIT") 1477 (const_int 2) 1478 (const_int 4)) 1479 (const_int 4)) 1480 (const_int 4)))]) 1481 1482(define_insn "indirect_jump" 1483 [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))] 1484 "" 1485 "@ 1486 jr5\t%0 1487 jr\t%0" 1488 [(set_attr "type" "branch,branch") 1489 (set_attr "length" " 2, 4")]) 1490 1491;; Subroutine call instruction returning no value. 1492;; operands[0]: It should be a mem RTX whose address is 1493;; the address of the function. 1494;; operands[1]: It is the number of bytes of arguments pushed as a const_int. 1495;; operands[2]: It is the number of registers used as operands. 1496 1497(define_expand "call" 1498 [(parallel [(call (match_operand 0 "memory_operand" "") 1499 (match_operand 1)) 1500 (clobber (reg:SI LP_REGNUM)) 1501 (clobber (reg:SI TA_REGNUM))])] 1502 "" 1503 { 1504 rtx insn; 1505 rtx sym = XEXP (operands[0], 0); 1506 1507 if (TARGET_ICT_MODEL_LARGE 1508 && nds32_indirect_call_referenced_p (sym)) 1509 { 1510 rtx reg = gen_reg_rtx (Pmode); 1511 emit_move_insn (reg, sym); 1512 operands[0] = gen_const_mem (Pmode, reg); 1513 } 1514 1515 if (flag_pic) 1516 { 1517 insn = emit_call_insn (gen_call_internal 1518 (XEXP (operands[0], 0), GEN_INT (0))); 1519 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); 1520 DONE; 1521 } 1522 } 1523) 1524 1525(define_insn "call_internal" 1526 [(parallel [(call (mem:SI (match_operand:SI 0 "nds32_call_address_operand" "r, S")) 1527 (match_operand 1)) 1528 (clobber (reg:SI LP_REGNUM)) 1529 (clobber (reg:SI TA_REGNUM))])] 1530 "" 1531{ 1532 rtx_insn *next_insn = next_active_insn (insn); 1533 bool align_p = (!(next_insn && get_attr_length (next_insn) == 2)) 1534 && NDS32_ALIGN_P (); 1535 switch (which_alternative) 1536 { 1537 case 0: 1538 if (TARGET_16_BIT) 1539 { 1540 if (align_p) 1541 return "jral5\t%0\;.align 2"; 1542 else 1543 return "jral5\t%0"; 1544 } 1545 else 1546 { 1547 if (align_p) 1548 return "jral\t%0\;.align 2"; 1549 else 1550 return "jral\t%0"; 1551 } 1552 case 1: 1553 return nds32_output_call (insn, operands, operands[0], 1554 "bal\t%0", "jal\t%0", align_p); 1555 default: 1556 gcc_unreachable (); 1557 } 1558} 1559 [(set_attr "enabled" "yes") 1560 (set_attr "type" "branch") 1561 (set_attr_alternative "length" 1562 [ 1563 ;; Alternative 0 1564 (if_then_else (match_test "TARGET_16_BIT") 1565 (const_int 2) 1566 (const_int 4)) 1567 ;; Alternative 1 1568 (if_then_else (match_test "flag_pic") 1569 (const_int 16) 1570 (if_then_else (match_test "nds32_long_call_p (operands[0])") 1571 (const_int 12) 1572 (const_int 4))) 1573 ])] 1574) 1575 1576;; Subroutine call instruction returning a value. 1577;; operands[0]: It is the hard regiser in which the value is returned. 1578;; The rest three operands are the same as the 1579;; three operands of the 'call' instruction. 1580;; (but with numbers increased by one) 1581 1582(define_expand "call_value" 1583 [(parallel [(set (match_operand 0) 1584 (call (match_operand 1 "memory_operand" "") 1585 (match_operand 2))) 1586 (clobber (reg:SI LP_REGNUM)) 1587 (clobber (reg:SI TA_REGNUM))])] 1588 "" 1589 { 1590 rtx insn; 1591 rtx sym = XEXP (operands[1], 0); 1592 1593 if (TARGET_ICT_MODEL_LARGE 1594 && nds32_indirect_call_referenced_p (sym)) 1595 { 1596 rtx reg = gen_reg_rtx (Pmode); 1597 emit_move_insn (reg, sym); 1598 operands[1] = gen_const_mem (Pmode, reg); 1599 } 1600 1601 if (flag_pic) 1602 { 1603 insn = 1604 emit_call_insn (gen_call_value_internal 1605 (operands[0], XEXP (operands[1], 0), GEN_INT (0))); 1606 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); 1607 DONE; 1608 } 1609 } 1610) 1611 1612(define_insn "call_value_internal" 1613 [(parallel [(set (match_operand 0) 1614 (call (mem:SI (match_operand:SI 1 "nds32_call_address_operand" "r, S")) 1615 (match_operand 2))) 1616 (clobber (reg:SI LP_REGNUM)) 1617 (clobber (reg:SI TA_REGNUM))])] 1618 "" 1619{ 1620 rtx_insn *next_insn = next_active_insn (insn); 1621 bool align_p = (!(next_insn && get_attr_length (next_insn) == 2)) 1622 && NDS32_ALIGN_P (); 1623 switch (which_alternative) 1624 { 1625 case 0: 1626 if (TARGET_16_BIT) 1627 { 1628 if (align_p) 1629 return "jral5\t%1\;.align 2"; 1630 else 1631 return "jral5\t%1"; 1632 } 1633 else 1634 { 1635 if (align_p) 1636 return "jral\t%1\;.align 2"; 1637 else 1638 return "jral\t%1"; 1639 } 1640 case 1: 1641 return nds32_output_call (insn, operands, operands[1], 1642 "bal\t%1", "jal\t%1", align_p); 1643 default: 1644 gcc_unreachable (); 1645 } 1646} 1647 [(set_attr "enabled" "yes") 1648 (set_attr "type" "branch") 1649 (set_attr_alternative "length" 1650 [ 1651 ;; Alternative 0 1652 (if_then_else (match_test "TARGET_16_BIT") 1653 (const_int 2) 1654 (const_int 4)) 1655 ;; Alternative 1 1656 (if_then_else (match_test "flag_pic") 1657 (const_int 16) 1658 (if_then_else (match_test "nds32_long_call_p (operands[1])") 1659 (const_int 12) 1660 (const_int 4))) 1661 ])] 1662) 1663 1664;; Call subroutine returning any type. 1665 1666(define_expand "untyped_call" 1667 [(parallel [(call (match_operand 0 "" "") 1668 (const_int 0)) 1669 (match_operand 1 "" "") 1670 (match_operand 2 "" "")])] 1671 "" 1672{ 1673 int i; 1674 1675 emit_call_insn (gen_call (operands[0], const0_rtx)); 1676 1677 for (i = 0; i < XVECLEN (operands[2], 0); i++) 1678 { 1679 rtx set = XVECEXP (operands[2], 0, i); 1680 emit_move_insn (SET_DEST (set), SET_SRC (set)); 1681 } 1682 1683 /* The optimizer does not know that the call sets the function value 1684 registers we stored in the result block. We avoid problems by 1685 claiming that all hard registers are used and clobbered at this 1686 point. */ 1687 emit_insn (gen_blockage ()); 1688 DONE; 1689}) 1690 1691;; ---------------------------------------------------------------------------- 1692 1693;; The sibcall patterns. 1694 1695;; sibcall 1696;; sibcall_internal 1697 1698(define_expand "sibcall" 1699 [(parallel [(call (match_operand 0 "memory_operand" "") 1700 (const_int 0)) 1701 (clobber (reg:SI TA_REGNUM)) 1702 (return)])] 1703 "" 1704{ 1705 rtx sym = XEXP (operands[0], 0); 1706 1707 if (TARGET_ICT_MODEL_LARGE 1708 && nds32_indirect_call_referenced_p (sym)) 1709 { 1710 rtx reg = gen_reg_rtx (Pmode); 1711 emit_move_insn (reg, sym); 1712 operands[0] = gen_const_mem (Pmode, reg); 1713 } 1714}) 1715 1716(define_insn "sibcall_internal" 1717 [(parallel [(call (mem:SI (match_operand:SI 0 "nds32_call_address_operand" "r, S")) 1718 (match_operand 1)) 1719 (clobber (reg:SI TA_REGNUM)) 1720 (return)])] 1721 "" 1722{ 1723 switch (which_alternative) 1724 { 1725 case 0: 1726 if (TARGET_16_BIT) 1727 return "jr5\t%0"; 1728 else 1729 return "jr\t%0"; 1730 case 1: 1731 if (nds32_long_call_p (operands[0])) 1732 return "b\t%0"; 1733 else 1734 return "j\t%0"; 1735 default: 1736 gcc_unreachable (); 1737 } 1738} 1739 [(set_attr "enabled" "yes") 1740 (set_attr "type" "branch") 1741 (set_attr_alternative "length" 1742 [ 1743 ;; Alternative 0 1744 (if_then_else (match_test "TARGET_16_BIT") 1745 (const_int 2) 1746 (const_int 4)) 1747 ;; Alternative 1 1748 (if_then_else (match_test "flag_pic") 1749 (const_int 16) 1750 (if_then_else (match_test "nds32_long_call_p (operands[0])") 1751 (const_int 12) 1752 (const_int 4))) 1753 ])] 1754) 1755 1756;; sibcall_value 1757;; sibcall_value_internal 1758;; sibcall_value_immediate 1759 1760(define_expand "sibcall_value" 1761 [(parallel [(set (match_operand 0) 1762 (call (match_operand 1 "memory_operand" "") 1763 (const_int 0))) 1764 (clobber (reg:SI TA_REGNUM)) 1765 (return)])] 1766 "" 1767{ 1768 rtx sym = XEXP (operands[1], 0); 1769 1770 if (TARGET_ICT_MODEL_LARGE 1771 && nds32_indirect_call_referenced_p (sym)) 1772 { 1773 rtx reg = gen_reg_rtx (Pmode); 1774 emit_move_insn (reg, sym); 1775 operands[1] = gen_const_mem (Pmode, reg); 1776 } 1777}) 1778 1779(define_insn "sibcall_value_internal" 1780 [(parallel [(set (match_operand 0) 1781 (call (mem:SI (match_operand:SI 1 "nds32_call_address_operand" "r, S")) 1782 (match_operand 2))) 1783 (clobber (reg:SI TA_REGNUM)) 1784 (return)])] 1785 "" 1786{ 1787 switch (which_alternative) 1788 { 1789 case 0: 1790 if (TARGET_16_BIT) 1791 return "jr5\t%1"; 1792 else 1793 return "jr\t%1"; 1794 case 1: 1795 if (nds32_long_call_p (operands[1])) 1796 return "b\t%1"; 1797 else 1798 return "j\t%1"; 1799 default: 1800 gcc_unreachable (); 1801 } 1802} 1803 [(set_attr "enabled" "yes") 1804 (set_attr "type" "branch") 1805 (set_attr_alternative "length" 1806 [ 1807 ;; Alternative 0 1808 (if_then_else (match_test "TARGET_16_BIT") 1809 (const_int 2) 1810 (const_int 4)) 1811 ;; Alternative 1 1812 (if_then_else (match_test "flag_pic") 1813 (const_int 16) 1814 (if_then_else (match_test "nds32_long_call_p (operands[1])") 1815 (const_int 12) 1816 (const_int 4))) 1817 ])] 1818) 1819 1820;; ---------------------------------------------------------------------------- 1821 1822;; prologue and epilogue. 1823 1824(define_expand "prologue" [(const_int 0)] 1825 "" 1826{ 1827 /* Note that only under V3/V3M ISA, we could use v3push prologue. 1828 In addition, we need to check if v3push is indeed available. */ 1829 if (NDS32_V3PUSH_AVAILABLE_P) 1830 nds32_expand_prologue_v3push (); 1831 else 1832 nds32_expand_prologue (); 1833 1834 /* If cfun->machine->fp_as_gp_p is true, we can generate special 1835 directive to guide linker doing fp-as-gp optimization. 1836 However, for a naked function, which means 1837 it should not have prologue/epilogue, 1838 using fp-as-gp still requires saving $fp by push/pop behavior and 1839 there is no benefit to use fp-as-gp on such small function. 1840 So we need to make sure this function is NOT naked as well. */ 1841 if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p) 1842 emit_insn (gen_omit_fp_begin (gen_rtx_REG (SImode, FP_REGNUM))); 1843 1844 DONE; 1845}) 1846 1847(define_expand "epilogue" [(const_int 0)] 1848 "" 1849{ 1850 /* If cfun->machine->fp_as_gp_p is true, we can generate special 1851 directive to guide linker doing fp-as-gp optimization. 1852 However, for a naked function, which means 1853 it should not have prologue/epilogue, 1854 using fp-as-gp still requires saving $fp by push/pop behavior and 1855 there is no benefit to use fp-as-gp on such small function. 1856 So we need to make sure this function is NOT naked as well. */ 1857 if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p) 1858 emit_insn (gen_omit_fp_end (gen_rtx_REG (SImode, FP_REGNUM))); 1859 1860 /* Note that only under V3/V3M ISA, we could use v3pop epilogue. 1861 In addition, we need to check if v3push is indeed available. */ 1862 if (NDS32_V3PUSH_AVAILABLE_P) 1863 nds32_expand_epilogue_v3pop (false); 1864 else 1865 nds32_expand_epilogue (false); 1866 DONE; 1867}) 1868 1869(define_expand "sibcall_epilogue" [(const_int 0)] 1870 "" 1871{ 1872 /* Pass true to indicate that this is sibcall epilogue and 1873 exit from a function without the final branch back to the 1874 calling function. */ 1875 nds32_expand_epilogue (true); 1876 1877 DONE; 1878}) 1879 1880 1881;; nop instruction. 1882 1883(define_insn "nop" 1884 [(const_int 0)] 1885 "" 1886{ 1887 if (TARGET_16_BIT) 1888 return "nop16"; 1889 else 1890 return "nop"; 1891} 1892 [(set_attr "type" "misc") 1893 (set_attr "enabled" "yes") 1894 (set (attr "length") 1895 (if_then_else (match_test "TARGET_16_BIT") 1896 (const_int 2) 1897 (const_int 4)))]) 1898 1899 1900;; ---------------------------------------------------------------------------- 1901;; Stack push/pop operations 1902;; ---------------------------------------------------------------------------- 1903 1904;; The pattern for stack push. 1905;; Both stack_push_multiple and stack_v3push use the following pattern. 1906;; So we need to use TARGET_V3PUSH to determine the instruction length. 1907(define_insn "*stack_push" 1908 [(match_parallel 0 "nds32_stack_push_operation" 1909 [(set (mem:SI (plus:SI (reg:SI SP_REGNUM) 1910 (match_operand:SI 1 "const_int_operand" ""))) 1911 (match_operand:SI 2 "register_operand" "")) 1912 ])] 1913 "" 1914{ 1915 return nds32_output_stack_push (operands[0]); 1916} 1917 [(set_attr "type" "store_multiple") 1918 (set_attr "combo" "12") 1919 (set_attr "enabled" "yes") 1920 (set (attr "length") 1921 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P") 1922 (const_int 2) 1923 (const_int 4)))]) 1924 1925 1926;; The pattern for stack pop. 1927;; Both stack_pop_multiple and stack_v3pop use the following pattern. 1928;; So we need to use TARGET_V3PUSH to determine the instruction length. 1929(define_insn "*stack_pop" 1930 [(match_parallel 0 "nds32_stack_pop_operation" 1931 [(set (match_operand:SI 1 "register_operand" "") 1932 (mem:SI (reg:SI SP_REGNUM))) 1933 ])] 1934 "" 1935{ 1936 return nds32_output_stack_pop (operands[0]); 1937} 1938 [(set_attr "type" "load_multiple") 1939 (set_attr "combo" "12") 1940 (set_attr "enabled" "yes") 1941 (set (attr "length") 1942 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P") 1943 (const_int 2) 1944 (const_int 4)))]) 1945 1946 1947;; ---------------------------------------------------------------------------- 1948;; Return operation patterns 1949;; ---------------------------------------------------------------------------- 1950 1951;; Use this pattern to expand a return instruction 1952;; with simple_return rtx if no epilogue is required. 1953(define_expand "return" 1954 [(parallel [(return) 1955 (clobber (reg:SI FP_REGNUM))])] 1956 "nds32_can_use_return_insn ()" 1957{ 1958 /* Emit as the simple return. */ 1959 if (!cfun->machine->fp_as_gp_p 1960 && cfun->machine->naked_p 1961 && (cfun->machine->va_args_size == 0)) 1962 { 1963 emit_jump_insn (gen_return_internal ()); 1964 DONE; 1965 } 1966}) 1967 1968;; This pattern is expanded only by the shrink-wrapping optimization 1969;; on paths where the function prologue has not been executed. 1970;; However, such optimization may reorder the prologue/epilogue blocks 1971;; together with basic blocks within function body. 1972;; So we must disable this pattern if we have already decided 1973;; to perform fp_as_gp optimization, which requires prologue to be 1974;; first block and epilogue to be last block. 1975(define_expand "simple_return" 1976 [(simple_return)] 1977 "!cfun->machine->fp_as_gp_p" 1978 "" 1979) 1980 1981(define_insn "*nds32_return" 1982 [(parallel [(return) 1983 (clobber (reg:SI FP_REGNUM))])] 1984 "" 1985{ 1986 return nds32_output_return (); 1987} 1988 [(set_attr "type" "branch") 1989 (set_attr "enabled" "yes") 1990 (set_attr "length" "4")]) 1991 1992(define_insn "return_internal" 1993 [(simple_return)] 1994 "" 1995{ 1996 if (nds32_isr_function_critical_p (current_function_decl)) 1997 return "iret"; 1998 1999 if (TARGET_16_BIT) 2000 return "ret5"; 2001 else 2002 return "ret"; 2003} 2004 [(set_attr "type" "branch") 2005 (set_attr "enabled" "yes") 2006 (set (attr "length") 2007 (if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)") 2008 (const_int 4) 2009 (if_then_else (match_test "TARGET_16_BIT") 2010 (const_int 2) 2011 (const_int 4))))]) 2012 2013 2014;; ---------------------------------------------------------------------------- 2015;; Jump Table patterns 2016;; ---------------------------------------------------------------------------- 2017;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table) 2018;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well. 2019;; 2020;; operands[0]: The index to dispatch on. 2021;; operands[1]: The lower bound for indices in the table. 2022;; operands[2]: The total range of indices int the table. 2023;; i.e. The largest index minus the smallest one. 2024;; operands[3]: A label that precedes the table itself. 2025;; operands[4]: A label to jump to if the index has a value outside the bounds. 2026;; 2027;; We need to create following sequences for jump table code generation: 2028;; A) k <-- (plus (operands[0]) (-operands[1])) 2029;; B) if (gtu k operands[2]) then goto operands[4] 2030;; C) t <-- operands[3] 2031;; D) z <-- (mem (plus (k << 0 or 1 or 2) t)) 2032;; E) z <-- t + z (NOTE: This is only required for pc relative jump table.) 2033;; F) jump to target with register t or z 2034;; 2035;; The steps C, D, E, and F are performed by casesi_internal pattern. 2036(define_expand "casesi" 2037 [(match_operand:SI 0 "register_operand" "r") ; index to jump on 2038 (match_operand:SI 1 "immediate_operand" "i") ; lower bound 2039 (match_operand:SI 2 "immediate_operand" "i") ; total range 2040 (match_operand:SI 3 "" "") ; table label 2041 (match_operand:SI 4 "" "")] ; Out of range label 2042 "" 2043{ 2044 rtx add_tmp; 2045 rtx reg, test; 2046 rtx tmp_reg; 2047 2048 /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */ 2049 if (operands[1] != const0_rtx) 2050 { 2051 reg = gen_reg_rtx (SImode); 2052 add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode); 2053 2054 /* If the integer value is not in the range of imm15s, 2055 we need to force register first because our addsi3 pattern 2056 only accept nds32_rimm15s_operand predicate. */ 2057 add_tmp = force_reg (SImode, add_tmp); 2058 2059 emit_insn (gen_addsi3 (reg, operands[0], add_tmp)); 2060 operands[0] = reg; 2061 } 2062 2063 /* Step B: "if (gtu k operands[2]) then goto operands[4]". */ 2064 test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]); 2065 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], 2066 operands[4])); 2067 2068 tmp_reg = gen_reg_rtx (SImode); 2069 /* Step C, D, E, and F, using another temporary register tmp_reg. */ 2070 if (flag_pic) 2071 emit_use (pic_offset_table_rtx); 2072 2073 emit_jump_insn (gen_casesi_internal (operands[0], 2074 operands[3], 2075 tmp_reg)); 2076 DONE; 2077}) 2078 2079;; We are receiving operands from casesi pattern: 2080;; 2081;; operands[0]: The index that have been substracted with lower bound. 2082;; operands[1]: A label that precedes the table itself. 2083;; operands[2]: A temporary register to retrieve value in table. 2084;; 2085;; We need to perform steps C, D, E, and F: 2086;; 2087;; C) t <-- operands[1] 2088;; D) z <-- (mem (plus (operands[0] << m) t)) 2089;; m is 2 for normal jump table. 2090;; m is 0, 1, or 2 for pc relative jump table based on diff size. 2091;; E) t <-- z + t (NOTE: This is only required for pc relative jump table.) 2092;; F) Jump to target with register t or z. 2093;; 2094;; The USE in this pattern is needed to tell flow analysis that this is 2095;; a CASESI insn. It has no other purpose. 2096(define_insn "casesi_internal" 2097 [(parallel [(set (pc) 2098 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") 2099 (const_int 4)) 2100 (label_ref (match_operand 1 "" ""))))) 2101 (use (label_ref (match_dup 1))) 2102 (clobber (match_operand:SI 2 "register_operand" "=r")) 2103 (clobber (reg:SI TA_REGNUM))])] 2104 "" 2105{ 2106 if (CASE_VECTOR_PC_RELATIVE) 2107 return nds32_output_casesi_pc_relative (operands); 2108 else 2109 return nds32_output_casesi (operands); 2110} 2111 [(set_attr "type" "branch") 2112 (set (attr "length") 2113 (if_then_else (match_test "flag_pic") 2114 (const_int 28) 2115 (const_int 20)))]) 2116 2117;; ---------------------------------------------------------------------------- 2118 2119;; Performance Extension 2120 2121; If -fwrapv option is issued, GCC expects there will be 2122; signed overflow situation. So the ABS(INT_MIN) is still INT_MIN 2123; (e.g. ABS(0x80000000)=0x80000000). 2124; However, the hardware ABS instruction of nds32 target 2125; always performs saturation: abs 0x80000000 -> 0x7fffffff. 2126; So that we can only enable abssi2 pattern if flag_wrapv is NOT presented. 2127(define_insn "abssi2" 2128 [(set (match_operand:SI 0 "register_operand" "=r") 2129 (abs:SI (match_operand:SI 1 "register_operand" " r")))] 2130 "TARGET_EXT_PERF && TARGET_HW_ABS && !flag_wrapv" 2131 "abs\t%0, %1" 2132 [(set_attr "type" "alu") 2133 (set_attr "length" "4")]) 2134 2135(define_insn "clzsi2" 2136 [(set (match_operand:SI 0 "register_operand" "=r") 2137 (clz:SI (match_operand:SI 1 "register_operand" " r")))] 2138 "TARGET_EXT_PERF" 2139 "clz\t%0, %1" 2140 [(set_attr "type" "alu") 2141 (set_attr "length" "4")]) 2142 2143(define_insn "smaxsi3" 2144 [(set (match_operand:SI 0 "register_operand" "=r") 2145 (smax:SI (match_operand:SI 1 "register_operand" " r") 2146 (match_operand:SI 2 "register_operand" " r")))] 2147 "TARGET_EXT_PERF" 2148 "max\t%0, %1, %2" 2149 [(set_attr "type" "alu") 2150 (set_attr "length" "4")]) 2151 2152(define_insn "sminsi3" 2153 [(set (match_operand:SI 0 "register_operand" "=r") 2154 (smin:SI (match_operand:SI 1 "register_operand" " r") 2155 (match_operand:SI 2 "register_operand" " r")))] 2156 "TARGET_EXT_PERF" 2157 "min\t%0, %1, %2" 2158 [(set_attr "type" "alu") 2159 (set_attr "length" "4")]) 2160 2161(define_insn "btst" 2162 [(set (match_operand:SI 0 "register_operand" "= r") 2163 (zero_extract:SI (match_operand:SI 1 "register_operand" " r") 2164 (const_int 1) 2165 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))] 2166 "TARGET_EXT_PERF" 2167 "btst\t%0, %1, %2" 2168 [(set_attr "type" "alu") 2169 (set_attr "length" "4")]) 2170 2171(define_insn "ave" 2172 [(set (match_operand:SI 0 "register_operand" "=r") 2173 (truncate:SI 2174 (ashiftrt:DI 2175 (plus:DI 2176 (plus:DI 2177 (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) 2178 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))) 2179 (const_int 1)) 2180 (const_int 1))))] 2181 "TARGET_EXT_PERF" 2182 "ave\t%0, %1, %2" 2183 [(set_attr "type" "alu") 2184 (set_attr "length" "4")]) 2185 2186;; ---------------------------------------------------------------------------- 2187 2188;; Pseudo NOPs 2189 2190(define_insn "relax_group" 2191 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)] 2192 "" 2193 ".relax_hint %0" 2194 [(set_attr "length" "0")] 2195) 2196 2197;; Output .omit_fp_begin for fp-as-gp optimization. 2198;; Also we have to set $fp register. 2199(define_insn "omit_fp_begin" 2200 [(set (match_operand:SI 0 "register_operand" "=x") 2201 (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_OMIT_FP_BEGIN))] 2202 "" 2203 "! -----\;.omit_fp_begin\;la\t$fp,_FP_BASE_\;! -----" 2204 [(set_attr "length" "8")] 2205) 2206 2207;; Output .omit_fp_end for fp-as-gp optimization. 2208;; Claim that we have to use $fp register. 2209(define_insn "omit_fp_end" 2210 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "x")] UNSPEC_VOLATILE_OMIT_FP_END)] 2211 "" 2212 "! -----\;.omit_fp_end\;! -----" 2213 [(set_attr "length" "0")] 2214) 2215 2216(define_insn "pop25return" 2217 [(return) 2218 (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)] 2219 "" 2220 "! return for pop 25" 2221 [(set_attr "length" "0")] 2222) 2223 2224;; Add pc 2225(define_insn "add_pc" 2226 [(set (match_operand:SI 0 "register_operand" "=r") 2227 (plus:SI (match_operand:SI 1 "register_operand" "0") 2228 (pc)))] 2229 "TARGET_LINUX_ABI || flag_pic" 2230 "add5.pc\t%0" 2231 [(set_attr "type" "alu") 2232 (set_attr "length" "4")] 2233) 2234 2235(define_expand "bswapsi2" 2236 [(set (match_operand:SI 0 "register_operand" "=r") 2237 (bswap:SI (match_operand:SI 1 "register_operand" "r")))] 2238 "" 2239{ 2240 emit_insn (gen_unspec_wsbh (operands[0], operands[1])); 2241 emit_insn (gen_rotrsi3 (operands[0], operands[0], GEN_INT (16))); 2242 DONE; 2243}) 2244 2245(define_insn "bswaphi2" 2246 [(set (match_operand:HI 0 "register_operand" "=r") 2247 (bswap:HI (match_operand:HI 1 "register_operand" "r")))] 2248 "" 2249 "wsbh\t%0, %1" 2250 [(set_attr "type" "alu") 2251 (set_attr "length" "4")] 2252) 2253 2254;; ---------------------------------------------------------------------------- 2255 2256;; Patterns for exception handling 2257 2258(define_expand "eh_return" 2259 [(use (match_operand 0 "general_operand"))] 2260 "" 2261{ 2262 emit_insn (gen_nds32_eh_return (operands[0])); 2263 DONE; 2264}) 2265 2266(define_insn_and_split "nds32_eh_return" 2267 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_EH_RETURN)] 2268 "" 2269 "#" 2270 "reload_completed" 2271 [(const_int 0)] 2272{ 2273 rtx place; 2274 rtx addr; 2275 2276 /* The operands[0] is the handler address. We need to assign it 2277 to return address rtx so that we can jump to exception handler 2278 when returning from current function. */ 2279 2280 if (cfun->machine->lp_size == 0) 2281 { 2282 /* If $lp is not saved in the stack frame, we can take $lp directly. */ 2283 place = gen_rtx_REG (SImode, LP_REGNUM); 2284 } 2285 else 2286 { 2287 /* Otherwise, we need to locate the stack slot of return address. 2288 The return address is generally saved in [$fp-4] location. 2289 However, DSE (dead store elimination) does not detect an alias 2290 between [$fp-x] and [$sp+y]. This can result in a store to save 2291 $lp introduced by builtin_eh_return() being incorrectly deleted 2292 if it is based on $fp. The solution we take here is to compute 2293 the offset relative to stack pointer and then use $sp to access 2294 location so that the alias can be detected. 2295 FIXME: What if the immediate value "offset" is too large to be 2296 fit in a single addi instruction? */ 2297 HOST_WIDE_INT offset; 2298 2299 offset = (cfun->machine->fp_size 2300 + cfun->machine->gp_size 2301 + cfun->machine->lp_size 2302 + cfun->machine->callee_saved_gpr_regs_size 2303 + cfun->machine->callee_saved_area_gpr_padding_bytes 2304 + cfun->machine->callee_saved_fpr_regs_size 2305 + cfun->machine->eh_return_data_regs_size 2306 + cfun->machine->local_size 2307 + cfun->machine->out_args_size); 2308 2309 addr = plus_constant (Pmode, stack_pointer_rtx, offset - 4); 2310 place = gen_frame_mem (SImode, addr); 2311 } 2312 2313 emit_move_insn (place, operands[0]); 2314 DONE; 2315}) 2316 2317;; ---------------------------------------------------------------------------- 2318 2319;; Patterns for __builtin_trap. 2320(define_insn "trap" 2321 [(trap_if (const_int 1) (const_int 0))] 2322 "" 2323 "trap\t0") 2324 2325;; ---------------------------------------------------------------------------- 2326 2327;; Patterns for TLS. 2328;; The following two tls patterns don't be expanded directly because the 2329;; intermediate value may be spilled into the stack. As a result, it is 2330;; hard to analyze the define-use chain in the relax_opt pass. 2331 2332 2333;; There is a unspec operand to record RELAX_GROUP number because each 2334;; emitted instruction need a relax_hint above it. 2335(define_insn "tls_desc" 2336 [(set (reg:SI 0) 2337 (call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC) 2338 (const_int 1))) 2339 (use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)) 2340 (use (reg:SI GP_REGNUM)) 2341 (clobber (reg:SI LP_REGNUM)) 2342 (clobber (reg:SI TA_REGNUM))] 2343 "" 2344 { 2345 return nds32_output_tls_desc (operands); 2346 } 2347 [(set_attr "length" "20") 2348 (set_attr "type" "branch")] 2349) 2350 2351;; There is a unspec operand to record RELAX_GROUP number because each 2352;; emitted instruction need a relax_hint above it. 2353(define_insn "tls_ie" 2354 [(set (match_operand:SI 0 "register_operand" "=r") 2355 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE)) 2356 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)) 2357 (use (reg:SI GP_REGNUM))] 2358 "" 2359 { 2360 return nds32_output_tls_ie (operands); 2361 } 2362 [(set (attr "length") (if_then_else (match_test "flag_pic") 2363 (const_int 12) 2364 (const_int 8))) 2365 (set_attr "type" "misc")] 2366) 2367 2368;; There is a unspec operand to record RELAX_GROUP number because each 2369;; emitted instruction need a relax_hint above it. 2370(define_insn "tls_le" 2371 [(set (match_operand:SI 0 "register_operand" "=r") 2372 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE)) 2373 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))] 2374 "" 2375 { 2376 return nds32_output_symrel (operands); 2377 } 2378 [(set_attr "length" "8") 2379 (set_attr "type" "misc")] 2380) 2381 2382;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode. 2383(define_insn "addsi3_32bit" 2384 [(set (match_operand:SI 0 "register_operand" "=r") 2385 (unspec:SI [(match_operand:SI 1 "register_operand" "%r") 2386 (match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))] 2387 "" 2388 "add\t%0, %1, %2"; 2389 [(set_attr "type" "alu") 2390 (set_attr "length" "4") 2391 (set_attr "feature" "v1")]) 2392 2393;; Patterns for PIC. 2394(define_insn "sym_got" 2395 [(set (match_operand:SI 0 "register_operand" "=r") 2396 (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_GOT)) 2397 (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))] 2398 "" 2399 { 2400 return nds32_output_symrel (operands); 2401 } 2402 [(set_attr "length" "8") 2403 (set_attr "type" "misc")] 2404) 2405 2406;; ---------------------------------------------------------------------------- 2407