1;; GCC machine description for CR16. 2;; Copyright (C) 2012-2020 Free Software Foundation, Inc. 3;; Contributed by KPIT Cummins Infosystems Limited. 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 by 9;; the Free Software Foundation; either version 3, or (at your option) 10;; 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;; Register numbers 22(define_constants 23 [(SP_REGNUM 15); Stack pointer 24 (RA_REGNUM 14); Return address 25 ] 26) 27 28;; Predicates & Constraints 29(include "predicates.md") 30(include "constraints.md") 31 32;; UNSPEC usage 33(define_constants 34 [(UNSPEC_PIC_ADDR 0) 35 (UNSPEC_PIC_LOAD_ADDR 1) 36 (UNSPEC_LIBRARY_OFFSET 2) 37 (UNSPEC_SH_LIB_PUSH_R12 3) 38 (UNSPEC_SH_LIB_POP_R12 4) 39 (UNSPEC_RETURN_ADDR 5) 40 ] 41) 42 43;; Attributes 44(define_attr "length" "" (const_int 2)) 45 46(define_asm_attributes 47 [(set_attr "length" "2")] 48) 49 50;; Mode Macro Definitions 51(define_mode_iterator CR16IM [QI HI SI]) 52(define_mode_iterator LONG [SI SF]) 53(define_mode_iterator ALLMTD [QI HI SI SF DI DF]) 54(define_mode_iterator DOUBLE [DI DF]) 55(define_mode_iterator SHORT [QI HI]) 56(define_mode_attr tIsa [(QI "b") (HI "w") (SI "d") (SF "d")]) 57(define_mode_attr lImmArith [(QI "4") (HI "4") (SI "6") (SF "6")]) 58(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")]) 59(define_mode_attr iF [(QI "i") (HI "i") (SI "i") (SF "F")]) 60(define_mode_attr iFD [(DI "i") (DF "F")]) 61(define_mode_attr LL [(QI "L") (HI "L")]) 62(define_mode_attr shImmBits [(QI "3") (HI "4") (SI "5")]) 63 64; In QI mode we push 2 bytes instead of 1 byte. 65(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")]) 66 67; tpush will be used to generate the 'number of registers to push' in the 68; push instruction. 69(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")]) 70 71;; Code Macro Definitions 72(define_code_attr sIsa [(sign_extend "") (zero_extend "u")]) 73(define_code_attr sPat [(sign_extend "s") (zero_extend "u")]) 74(define_code_attr szPat [(sign_extend "") (zero_extend "zero_")]) 75(define_code_attr szIsa [(sign_extend "x") (zero_extend "z")]) 76 77(define_code_iterator sz_xtnd [ sign_extend zero_extend]) 78(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu]) 79(define_code_iterator plusminus [plus minus]) 80 81(define_code_attr plusminus_insn [(plus "add") (minus "sub")]) 82(define_code_attr plusminus_flag [(plus "PLUS") (minus "MINUS")]) 83(define_code_attr comm [(plus "%") (minus "")]) 84 85(define_code_iterator any_logic [and ior xor]) 86(define_code_attr logic [(and "and") (ior "or") (xor "xor")]) 87(define_code_attr any_logic_insn [(and "and") (ior "ior") (xor "xor")]) 88(define_code_attr any_logic_flag [(and "AND") (ior "IOR") (xor "XOR")]) 89 90(define_mode_iterator QH [QI HI]) 91(define_mode_attr qh [(QI "qi") (HI "hi")]) 92(define_mode_attr QHsz [(QI "2,2,2") (HI "2,2,4")]) 93(define_mode_attr QHsuffix [(QI "b") (HI "w")]) 94 95 96;; Function Prologue and Epilogue 97(define_expand "prologue" 98 [(const_int 0)] 99 "" 100 { 101 cr16_expand_prologue (); 102 DONE; 103 } 104) 105 106(define_insn "push_for_prologue" 107 [(set (reg:SI SP_REGNUM) 108 (minus:SI (reg:SI SP_REGNUM) 109 (match_operand:SI 0 "immediate_operand" "i")))] 110 "reload_completed" 111 { 112 return cr16_prepare_push_pop_string (0); 113 } 114 [(set_attr "length" "4")] 115) 116 117(define_expand "epilogue" 118 [(return)] 119 "" 120 { 121 cr16_expand_epilogue (); 122 DONE; 123 } 124) 125 126(define_insn "pop_and_popret_return" 127 [(set (reg:SI SP_REGNUM) 128 (plus:SI (reg:SI SP_REGNUM) 129 (match_operand:SI 0 "immediate_operand" "i"))) 130 (use (reg:SI RA_REGNUM)) 131 (return)] 132 "reload_completed" 133 { 134 return cr16_prepare_push_pop_string (1); 135 } 136 [(set_attr "length" "4")] 137) 138 139(define_insn "popret_RA_return" 140 [(use (reg:SI RA_REGNUM)) 141 (return)] 142 "reload_completed" 143 "popret\tra" 144 [(set_attr "length" "2")] 145) 146 147;; Arithmetic Instruction Patterns 148 149;; Addition-Subtraction "adddi3/subdi3" insns. 150(define_insn "<plusminus_insn>di3" 151 [(set (match_operand:DI 0 "register_operand" "=r") 152 (plusminus:DI (match_operand:DI 1 "register_operand" "<comm>0") 153 (match_operand:DI 2 "register_operand" "r")))] 154 "" 155 { 156 return cr16_emit_add_sub_di (operands, <plusminus_flag>); 157 }) 158 159(define_insn "addsi3" 160 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") 161 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0") 162 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))] 163 "" 164 "addd\t%2, %0" 165 [(set_attr "length" "2,2,4,4,6")] 166) 167 168;; Addition-Subtraction "addhi3/subhi3" insns. 169(define_insn "<plusminus_insn>hi3" 170 [(set (match_operand:HI 0 "register_operand" "=c,c,c") 171 (plusminus:HI (match_operand:HI 1 "register_operand" "<comm>0,0,0") 172 (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))] 173 "" 174 "<plusminus_insn>w\t%2, %0" 175 [(set_attr "length" "2,2,4")] 176) 177 178;; Addition-Subtraction "addqi3/subqi3" insns. 179(define_insn "<plusminus_insn>qi3" 180 [(set (match_operand:QI 0 "register_operand" "=c,c") 181 (plusminus:QI (match_operand:QI 1 "register_operand" "<comm>0,0") 182 (match_operand:QI 2 "reg_qi_int_operand" "c,M")))] 183 "" 184 "<plusminus_insn>b\t%2, %0" 185 [(set_attr "length" "2,2")] 186) 187 188;; Subtract Instruction 189(define_insn "subsi3" 190 [(set (match_operand:SI 0 "register_operand" "=r,r") 191 (minus:SI (match_operand:SI 1 "register_operand" "0,0") 192 (match_operand:SI 2 "reg_si_int_operand" "r,i")))] 193 "" 194 "subd\t%2, %0" 195 [(set_attr "length" "4,6")] 196) 197 198;; Multiply and Accumulate Instructions "smachisi3/umachisi3" 199(define_insn "<sPat>maddhisi4" 200 [(set (match_operand:SI 0 "register_operand" "=r") 201 (plus:SI 202 (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")) 203 (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r"))) 204 (match_operand:SI 3 "register_operand" "0")))] 205 "TARGET_MAC" 206 "mac<sPat>w\t%1, %2, %0" 207 [(set_attr "length" "2")] 208) 209 210;; Multiply Instructions 211(define_insn "mulhi3" 212 [(set (match_operand:HI 0 "register_operand" "=c,c,c") 213 (mult:HI (match_operand:HI 1 "register_operand" "%0,0,0") 214 (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))] 215 "" 216 "mulw\t%2, %0" 217 [(set_attr "length" "2,2,4")] 218) 219 220(define_insn "mulqihi3" 221 [(set (match_operand:HI 0 "register_operand" "=c") 222 (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) 223 (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))] 224 "" 225 "mulsb\t%2, %0" 226 [(set_attr "length" "2")] 227) 228 229;; Bit Set/Clear Instructions 230(define_expand "insv" 231 [(set (zero_extract (match_operand 0 "memory_operand" "") 232 (match_operand 1 "immediate_operand" "") 233 (match_operand 2 "immediate_operand" "")) 234 (match_operand 3 "immediate_operand" ""))] 235 "TARGET_BIT_OPS" 236 { 237 if (INTVAL (operands[1]) != 1) 238 FAIL; 239 if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15) 240 FAIL; 241 if (INTVAL (operands[3]) == 1) 242 { 243 if (GET_MODE (operands[0]) == QImode) 244 { 245 emit_insn (gen_set_bitqi (operands[0], operands[2])); 246 DONE; 247 } 248 else if (GET_MODE (operands[0]) == HImode) 249 { 250 emit_insn (gen_set_bithi (operands[0], operands[2])); 251 DONE; 252 } 253 } 254 if (INTVAL (operands[3]) == 0) 255 { 256 if (GET_MODE (operands[0]) == QImode) 257 { 258 emit_insn (gen_clr_bitqi (operands[0], operands[2])); 259 DONE; 260 } 261 else if (GET_MODE (operands[0]) == HImode) 262 { 263 emit_insn (gen_clr_bithi (operands[0], operands[2])); 264 DONE; 265 } 266 } 267 } 268) 269 270(define_insn "set_bit<mode>" 271 [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m") 272 (const_int 1) 273 (match_operand 1 "immediate_operand" "i")) 274 (const_int 1))] 275 "TARGET_BIT_OPS" 276 "sbit<tIsa>\t%1,%0" 277 [(set_attr "length" "2")] 278) 279 280(define_insn "clr_bit<mode>" 281 [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m") 282 (const_int 1) 283 (match_operand 1 "immediate_operand" "i")) 284 (const_int 0))] 285 "TARGET_BIT_OPS" 286 "cbit<tIsa>\t%1,%0" 287 [(set_attr "length" "2")] 288) 289 290(define_insn "set_bit<mode>_mem" 291 [(set (match_operand:SHORT 0 "bit_operand" "=m") 292 (ior:SHORT (match_dup 0) 293 (match_operand:SHORT 1 "one_bit_operand" "i")) 294 )] 295 "TARGET_BIT_OPS" 296 "sbit<tIsa>\t$%s1,%0" 297 [(set_attr "length" "2")] 298) 299 300(define_insn "clear_bit<mode>_mem" 301 [(set (match_operand:SHORT 0 "bit_operand" "=m") 302 (and:SHORT (match_dup 0) 303 (match_operand:SHORT 1 "rev_one_bit_operand" "i")) 304 )] 305 "TARGET_BIT_OPS" 306 "cbit<tIsa>\t$%r1,%0" 307 [(set_attr "length" "2")] 308) 309 310;; Logical Instructions - and/ior/xor "anddi3/iordi3/xordi3" 311(define_insn "<any_logic_insn>di3" 312 [(set (match_operand:DI 0 "register_operand" "=r") 313 (any_logic:DI (match_operand:DI 1 "register_operand" "%0") 314 (match_operand:DI 2 "register_operand" "r")))] 315 "" 316 { 317 return cr16_emit_logical_di (operands, <any_logic_flag>); 318 }) 319 320; Logical and/ior/xor "andsi3/iorsi3/xorsi3" 321(define_insn "<any_logic_insn>si3" 322 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") 323 (any_logic:SI (match_operand:SI 1 "register_operand" "%0,0,0,0") 324 (match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))] 325 "" 326 "<logic>d\t%2, %0" 327 [(set_attr "length" "2,2,4,6")] 328) 329 330; Logical and/ior/xor in HImode "andhi3/iorhi3/xorhi3" 331; Logical and/ior/xor in QImode "andqi3/iorqi3/xorqi3" 332(define_insn "<any_logic_insn><qh>3" 333 [(set (match_operand:QH 0 "register_operand" "=c,c,c") 334 (any_logic:QH (match_operand:QH 1 "register_operand" "%0,0,0") 335 (match_operand:QH 2 "reg_hi_int_operand" "c,M,N")))] 336 "" 337 "<logic><QHsuffix>\t%2, %0" 338 [(set_attr "length" "<QHsz>")] 339) 340 341;; Sign and Zero Extend Instructions 342(define_insn "<szPat>extendhisi2" 343 [(set (match_operand:SI 0 "register_operand" "=r") 344 (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))] 345 "" 346 "mov<szIsa>w\t%1, %0" 347 [(set_attr "length" "4")] 348) 349 350(define_insn "<szPat>extendqihi2" 351 [(set (match_operand:HI 0 "register_operand" "=r") 352 (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))] 353 "" 354 "mov<szIsa>b\t%1, %0" 355 [(set_attr "length" "4")] 356) 357 358;; One's Complement 359(define_insn "one_cmpldi2" 360 [(set (match_operand:DI 0 "register_operand" "=r") 361 (not:DI (match_operand:DI 1 "register_operand" "0")))] 362 "" 363 { 364 rtx xoperand ; 365 int reg0 = REGNO (operands[0]); 366 367 xoperand = gen_rtx_REG (SImode, reg0 + 2); 368 output_asm_insn ("xord\t$-1, %0", operands); 369 output_asm_insn ("xord\t$-1, %0", &xoperand); 370 return "" ; 371 } 372 [(set_attr "length" "12")] 373) 374 375(define_insn "one_cmpl<mode>2" 376 [(set (match_operand:CR16IM 0 "register_operand" "=r") 377 (not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))] 378 "" 379 "xor<tIsa>\t$-1, %0" 380 [(set_attr "length" "2")] 381) 382 383;; Arithmetic Left and Right Shift Instructions 384(define_insn "ashlqi3" 385 [(set (match_operand:QI 0 "register_operand" "=c,c") 386 (ashift:QI (match_operand:QI 1 "register_operand" "0,0") 387 (match_operand:QI 2 "nonmemory_operand" "c,I")))] 388 "" 389 "ashub\t%2, %0" 390 [(set_attr "length" "2,2")] 391) 392 393(define_insn "ashlhi3" 394 [(set (match_operand:HI 0 "register_operand" "=c,c") 395 (ashift:HI (match_operand:HI 1 "register_operand" "0,0") 396 (match_operand:QI 2 "nonmemory_operand" "c,J")))] 397 "" 398 "ashuw\t%2, %0" 399 [(set_attr "length" "2,2")] 400) 401 402(define_insn "ashlsi3" 403 [(set (match_operand:SI 0 "register_operand" "=r,r") 404 (ashift:SI (match_operand:SI 1 "register_operand" "0,0") 405 (match_operand:QI 2 "nonmemory_operand" "r,K")))] 406 "" 407 "ashud\t%2, %0" 408 [(set_attr "length" "2,2")] 409) 410 411(define_expand "ashr<mode>3" 412 [(set (match_operand:CR16IM 0 "register_operand" "") 413 (ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "") 414 (match_operand:QI 2 "nonmemory_operand" "")))] 415 "" 416 { 417 if (GET_CODE (operands[2]) == CONST_INT) 418 { 419 /* If the constant is not in range, try placing it in a reg */ 420 if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>)) 421 operands[2] = copy_to_mode_reg(QImode, operands[2]); 422 } 423 424 if (GET_CODE (operands[2]) != CONST_INT) 425 operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2])); 426 } 427) 428 429(define_insn "ashrqi3_imm_insn" 430 [(set (match_operand:QI 0 "register_operand" "=c") 431 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") 432 (match_operand:QI 2 "shift_qi_imm_operand" "i")))] 433 "" 434 "ashub\t$%n2, %0" 435 [(set_attr "length" "2")] 436) 437 438(define_insn "ashrhi3_imm_insn" 439 [(set (match_operand:HI 0 "register_operand" "=c") 440 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") 441 (match_operand:QI 2 "shift_hi_imm_operand" "i")))] 442 "" 443 "ashuw\t$%n2, %0" 444 [(set_attr "length" "2")] 445) 446 447(define_insn "ashrsi3_imm_insn" 448 [(set (match_operand:SI 0 "register_operand" "=r") 449 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") 450 (match_operand:QI 2 "shift_si_imm_operand" "i")))] 451 "" 452 "ashud\t$%n2, %0" 453 [(set_attr "length" "2")] 454) 455 456(define_insn "ashrqi3_neg_insn" 457 [(set (match_operand:QI 0 "register_operand" "=c") 458 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") 459 (neg:QI (match_operand:QI 2 "register_operand" "c"))))] 460 "" 461 "ashub\t%2,%0" 462 [(set_attr "length" "2")] 463) 464 465(define_insn "ashrhi3_neg_insn" 466 [(set (match_operand:HI 0 "register_operand" "=c") 467 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") 468 (neg:QI (match_operand:QI 2 "register_operand" "c"))))] 469 "" 470 "ashuw\t%2,%0" 471 [(set_attr "length" "2")] 472) 473 474(define_insn "ashrdi3_neg_insn" 475 [(set (match_operand:SI 0 "register_operand" "=r") 476 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") 477 (neg:QI (match_operand:QI 2 "register_operand" "r"))))] 478 "" 479 "ashud\t%2,%0" 480 [(set_attr "length" "2")] 481) 482 483(define_expand "lshr<mode>3" 484 [(set (match_operand:CR16IM 0 "register_operand" "") 485 (lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "") 486 (match_operand:QI 2 "reg_or_int_operand" "")))] 487 "" 488 { 489 if (GET_CODE (operands[2]) == CONST_INT) 490 { 491 /* If the constant is not in range, try placing it in a reg */ 492 if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>)) 493 operands[2] = copy_to_mode_reg(QImode, operands[2]); 494 } 495 496 if (GET_CODE (operands[2]) != CONST_INT) 497 operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2])); 498 } 499) 500 501(define_insn "lshrqi3_imm_insn" 502 [(set (match_operand:QI 0 "register_operand" "=c") 503 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") 504 (match_operand:QI 2 "shift_qi_operand" "Q")))] 505 "" 506 "lshb\t$%n2, %0" 507 [(set_attr "length" "2")] 508) 509 510(define_insn "lshrhi3_imm_insn" 511 [(set (match_operand:HI 0 "register_operand" "=c") 512 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") 513 (match_operand:QI 2 "shift_hi_operand" "R")))] 514 "" 515 "lshw\t$%n2, %0" 516 [(set_attr "length" "2")] 517) 518 519(define_insn "lshrsi3_imm_insn" 520 [(set (match_operand:SI 0 "register_operand" "=r") 521 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") 522 (match_operand:QI 2 "shift_si_operand" "S")))] 523 "" 524 "lshd\t$%n2, %0" 525 [(set_attr "length" "2")] 526) 527 528(define_insn "lshrqi3_neg_insn" 529 [(set (match_operand:QI 0 "register_operand" "=c") 530 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") 531 (neg:QI (match_operand:QI 2 "register_operand" "c"))))] 532 "" 533 "lshb\t%2,%0" 534 [(set_attr "length" "2")] 535) 536 537(define_insn "lshrhi3_neg_insn" 538 [(set (match_operand:HI 0 "register_operand" "=c") 539 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") 540 (neg:QI (match_operand:QI 2 "register_operand" "c"))))] 541 "" 542 "lshw\t%2,%0" 543 [(set_attr "length" "2")] 544) 545 546(define_insn "lshrsi3_neg_insn" 547 [(set (match_operand:SI 0 "register_operand" "=r") 548 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") 549 (neg:QI (match_operand:QI 2 "register_operand" "r"))))] 550 "" 551 "lshd\t%2,%0" 552 [(set_attr "length" "2")] 553) 554 555;; Move Instructions 556 557;; Move any non-immediate operand 0 to a general operand 1. 558;; This applies only before starting the reload process 559;; Operand 0 is not a register operand of type mode MODE 560;; If Operand 0 is a push operand of type mode MODE 561;; then, if Operand 1 is a non-SP register 562;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1) 563;; endif 564;; else 565;; if Operand 1 is either register or 4-bit immediate constant 566;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1) 567;; endif 568;; endif 569;; 570;; What does copy_to_mode_reg (mode, rtx val) do? 571;; Copy the value into new temp reg and return the reg where the 572;; mode of the new reg is always mode MODE when value is constant 573;; 574;; Why should copy_to_mode_reg be called? 575;; All sorts of move are nor supported by CR16. Therefore, 576;; when unsupported move is encountered, the additional instructions 577;; will be introduced for the purpose. 578;; 579;; A new move insn is inserted for Op 1 when one of the following 580;; conditions is met. 581;; Case 1: Op 0 is push_operand 582;; Op 1 is SP register 583;; 584;; Case 2: Op 0 is not push_operand 585;; Op 1 is neither register nor unsigned 4-bit immediate 586 587(define_expand "mov<mode>" 588 [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "") 589 (match_operand:ALLMTD 1 "general_operand" ""))] 590 "" 591 { 592 if (!(reload_in_progress || reload_completed)) 593 { 594 /* Only if Op0 is a register operand. */ 595 if (!register_operand (operands[0], <MODE>mode)) 596 { 597 if (push_operand (operands[0], <MODE>mode)) 598 { 599 /* Use copy_to_mode_reg only if the register needs 600 to be pushed is SP as CR16 does not support pushing SP. */ 601 if (!nosp_reg_operand (operands[1], <MODE>mode)) 602 operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]); 603 } 604 else 605 { 606 /* Use copy_to_mode_reg if op1 is not register operand 607 subject to conditions inside. */ 608 if (!register_operand (operands[1], <MODE>mode)) 609 { 610 /* CR16 does not support moving immediate to SI or SF 611 type memory. */ 612 if (<MODE>mode == SImode || <MODE>mode == SFmode || 613 <MODE>mode == DImode || <MODE>mode == DFmode) 614 operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]); 615 else 616 /* moving imm4 is supported by CR16 instruction. */ 617 if (!u4bits_operand (operands[1], <MODE>mode)) 618 operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]); 619 } 620 } 621 } 622 623 /* If operand-1 is a symbol, convert it into a BRO or GOT Format. */ 624 if (flag_pic && ! legitimate_pic_operand_p (operands[1])) 625 { 626 operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0); 627 } 628 } 629 } 630) 631 632; ALLMT : QI,HI,SI,SF 633; pushCnstr : Push constraints 634; QI : X 635; HI,SI,SF,DI,DF : < 636; b : All non-sp registers 637; tpush : Push count 638; QI,HI : 1 639; SI,SF : 2 640; DI,DF : 4 641(define_insn "push<mode>_internal" 642 [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>") 643 (match_operand:ALLMTD 1 "nosp_reg_operand" "b"))] 644 "" 645 "push\t$<tpush>,%p1" 646 [(set_attr "length" "2")] 647) 648 649; (DI, DF) move 650(define_insn "*mov<mode>_double" 651 [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m") 652 (match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))] 653 "register_operand (operands[0], DImode) 654 || register_operand (operands[0], DFmode) 655 || register_operand (operands[1], DImode) 656 || register_operand (operands[1], DFmode)" 657 { 658 if (which_alternative == 0) { 659 rtx xoperands[2]; 660 int reg0 = REGNO (operands[0]); 661 int reg1 = REGNO (operands[1]); 662 663 xoperands[0] = gen_rtx_REG (SImode, reg0 + 2); 664 xoperands[1] = gen_rtx_REG (SImode, reg1 + 2); 665 if ((reg1 + 2) != reg0) 666 { 667 output_asm_insn ("movd\t%1, %0", operands); 668 output_asm_insn ("movd\t%1, %0", xoperands); 669 } 670 else 671 { 672 output_asm_insn ("movd\t%1, %0", xoperands); 673 output_asm_insn ("movd\t%1, %0", operands); 674 }} 675 676 else if (which_alternative == 1) { 677 rtx lo_operands[2]; 678 rtx hi_operands[2]; 679 680 lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); 681 hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2); 682 lo_operands[1] = simplify_gen_subreg (SImode, operands[1], 683 VOIDmode == GET_MODE (operands[1]) 684 ? DImode : GET_MODE (operands[1]), 0); 685 hi_operands[1] = simplify_gen_subreg (SImode, operands[1], 686 VOIDmode == GET_MODE (operands[1]) 687 ? DImode : GET_MODE (operands[1]), 4); 688 output_asm_insn ("movd\t%1, %0", lo_operands); 689 output_asm_insn ("movd\t%1, %0", hi_operands);} 690 691 else if (which_alternative == 2) { 692 rtx xoperands[2]; 693 int reg0 = REGNO (operands[0]), reg1 = -2; 694 rtx addr; 695 696 if (MEM_P (operands[1])) 697 addr = XEXP (operands[1], 0); 698 else 699 addr = NULL_RTX; 700 switch (GET_CODE (addr)) 701 { 702 case REG: 703 case SUBREG: 704 reg1 = REGNO (addr); 705 break; 706 case PLUS: 707 switch (GET_CODE (XEXP (addr, 0))) { 708 case REG: 709 case SUBREG: 710 reg1 = REGNO (XEXP (addr, 0)); 711 break; 712 case PLUS: 713 reg1 = REGNO (XEXP (XEXP (addr, 0), 0)); 714 break; 715 default: 716 inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:"); 717 debug_rtx (addr); 718 inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:"); 719 debug_rtx (operands[1]); 720 inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n"); 721 break;} 722 break; 723 default: 724 break; 725 } 726 727 xoperands[0] = gen_rtx_REG (SImode, reg0 + 2); 728 xoperands[1] = offset_address (operands[1], GEN_INT (4), 2); 729 gcc_assert ((reg0 + 1) != reg1); 730 if (reg0 != reg1 && (reg1 + 1) != reg0) 731 { 732 output_asm_insn ("loadd\t%1, %0", operands); 733 output_asm_insn ("loadd\t%1, %0", xoperands); 734 } 735 else 736 { 737 output_asm_insn ("loadd\t%1, %0", xoperands); 738 output_asm_insn ("loadd\t%1, %0", operands); 739 }} 740 else 741 { 742 rtx xoperands[2]; 743 xoperands[0] = offset_address (operands[0], GEN_INT (4), 2); 744 xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2); 745 output_asm_insn ("stord\t%1, %0", operands); 746 output_asm_insn ("stord\t%1, %0", xoperands); 747 } 748 return ""; 749 } 750 [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")] 751) 752 753; All long (SI, SF) register move, load and store operations 754; The print_operand will take care of printing the register pair 755; when mode is SI/SF and register is in SHORT_REGS 756(define_insn "*mov<mode>_long" 757 [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m") 758 (match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))] 759 "register_operand (operands[0], <MODE>mode) 760 || register_operand (operands[1], <MODE>mode)" 761 "@ 762 mov<tIsa>\t%1, %0 763 mov<tIsa>\t%1, %0 764 load<tIsa>\t%1, %0 765 stor<tIsa>\t%1, %0" 766 [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")] 767) 768 769;; All short (QI, HI) register move, load and store operations 770(define_insn "*mov<mode>_short" 771 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m") 772 (match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))] 773 "(register_operand (operands[0], <MODE>mode)) 774 || (store_operand (operands[0], <MODE>mode) 775 && (register_operand (operands[1], <MODE>mode) 776 || u4bits_operand (operands[1], <MODE>mode)))" 777 "@ 778 mov<tIsa>\t%1, %0 779 mov<tIsa>\t%1, %0 780 load<tIsa>\t%1, %0 781 stor<tIsa>\t%1, %0 782 stor<tIsa>\t%1, %0" 783 [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")] 784) 785 786;; Compare Instructions 787; Instruction generated compares the operands in reverse order 788; Therefore, while printing the asm, the reverse of the 789; compare condition shall be printed. 790(define_insn "cbranch<mode>4" 791 [(set (pc) 792 (if_then_else (match_operator 0 "ordered_comparison_operator" 793 [(match_operand:CR16IM 1 "register_operand" "r,r") 794 (match_operand:CR16IM 2 "nonmemory_operand" "r,n")]) 795 (label_ref (match_operand 3 "" "")) 796 (pc))) 797 (clobber (cc0))] 798 "" 799 "cmp<tIsa>\t%2, %1\;b%d0\t%l3" 800 [(set_attr "length" "6,6")] 801) 802 803(define_expand "cmp<mode>" 804 [(parallel [(set (cc0) 805 (compare (match_operand:CR16IM 0 "register_operand" "") 806 (match_operand:CR16IM 1 "nonmemory_operand" ""))) 807 (clobber (match_scratch:HI 2 "=r"))] ) ] 808 "" 809 "") 810 811;; Scond Instructions 812(define_expand "cstore<mode>4" 813 [(set (cc0) 814 (compare (match_operand:CR16IM 2 "register_operand" "") 815 (match_operand:CR16IM 3 "nonmemory_operand" ""))) 816 (set (match_operand:HI 0 "register_operand") 817 (match_operator:HI 1 "ordered_comparison_operator" 818 [(cc0) (const_int 0)]))] 819 "" 820 "" 821) 822 823(define_insn "*cmp<mode>_insn" 824 [(set (cc0) 825 (compare (match_operand:CR16IM 0 "register_operand" "r,r") 826 (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))] 827 "" 828 "cmp<tIsa>\t%1, %0" 829 [(set_attr "length" "2,4")] 830) 831 832(define_insn "sCOND_internal" 833 [(set (match_operand:HI 0 "register_operand" "=r") 834 (match_operator:HI 1 "ordered_comparison_operator" 835 [(cc0) (const_int 0)]))] 836 "" 837 "s%d1\t%0" 838 [(set_attr "length" "2")] 839) 840 841;; Jumps and Branches 842(define_insn "indirect_jump_return" 843 [(set (pc) 844 (reg:SI RA_REGNUM)) 845 (return)] 846 "reload_completed" 847 "jump\t (ra)" 848 [(set_attr "length" "2")] 849) 850 851(define_insn "jump_return" 852 [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR) 853 (return)] 854 "reload_completed" 855 "jump\t(ra)" 856 [(set_attr "length" "2")] 857) 858 859(define_insn "indirect_jump" 860 [(set (pc) 861 (match_operand:SI 0 "reg_or_sym_operand" "r,i"))] 862 "" 863 "@ 864 jump\t%0 865 br\t%a0" 866 [(set_attr "length" "2,6")] 867) 868 869(define_insn "interrupt_return" 870 [(unspec_volatile [(const_int 0)] 0) 871 (return)] 872 "" 873 { 874 return cr16_prepare_push_pop_string (1); 875 } 876 [(set_attr "length" "14")] 877) 878 879(define_insn "jump_to_imm" 880 [(set (pc) 881 (match_operand 0 "jump_imm_operand" "i"))] 882 "" 883 "br\t%c0" 884 [(set_attr "length" "6")] 885) 886 887(define_insn "jump" 888 [(set (pc) 889 (label_ref (match_operand 0 "" "")))] 890 "" 891 "br\t%l0" 892 [(set_attr "length" "6")] 893) 894 895;; Table Jump 896(define_insn "tablejump" 897 [(set (pc) 898 (match_operand:SI 0 "register_operand" "r")) 899 (use (label_ref:SI (match_operand 1 "" "")))] 900 "!flag_pic" 901 "jump\t%0" 902 [(set_attr "length" "2")] 903) 904 905;; Call Instructions 906(define_expand "call" 907 [(call (match_operand:QI 0 "memory_operand" "") 908 (match_operand 1 "" ""))] 909 "" 910 { 911 if (flag_pic && ! legitimate_pic_operand_p (operands[0])) 912 { 913 operands[0] = gen_const_mem (QImode, 914 legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0)); 915 emit_call_insn (gen_cr16_call (operands[0], operands[1])); 916 } 917 else 918 emit_call_insn (gen_cr16_call (operands[0], operands[1])); 919 DONE; 920 } 921) 922 923(define_expand "cr16_call" 924 [(parallel 925 [(call (match_operand:QI 0 "memory_operand" "") 926 (match_operand 1 "" "")) 927 (clobber (reg:SI RA_REGNUM))])] 928 "" 929 "" 930) 931 932(define_insn "cr16_call_insn_branch_pic" 933 [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i")) 934 (match_operand 1 "" "")) 935 (clobber (match_operand:SI 2 "register_operand" "+r"))] 936 "flag_pic == FAR_PIC" 937 { 938 if (GET_CODE (operands[0]) != CONST_INT) 939 return "loadd\t%g0, %2 \n\tjal %2"; 940 else 941 return "jal %2"; 942 } 943 [(set_attr "length" "8")] 944) 945 946(define_insn "cr16_call_insn_branch" 947 [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i")) 948 (match_operand 1 "" "")) 949 (clobber (match_operand:SI 2 "register_operand" "+r"))] 950 "flag_pic == 0 || flag_pic == NEAR_PIC" 951 { 952 /* Print the immediate address for bal 953 'b' is used instead of 'a' to avoid compiler calling 954 the GO_IF_LEGITIMATE_ADDRESS which cannot 955 perform checks on const_int code addresses as it 956 assumes all const_int are data addresses. 957 */ 958 if (GET_CODE (operands[0]) != CONST_INT) 959 return "bal (ra), %a0"; 960 else 961 operands[4] = GEN_INT ((INTVAL (operands[0]))>>1); 962 return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)"; 963 } 964 [(set_attr "length" "6")] 965) 966 967(define_insn "cr16_call_insn_jump" 968 [(call (mem:QI (match_operand:SI 0 "register_operand" "r")) 969 (match_operand 1 "" "")) 970 (clobber (match_operand:SI 2 "register_operand" "+r"))] 971 "" 972 "jal\t%0" 973 [(set_attr "length" "2")] 974) 975 976;; Call Value Instructions 977 978(define_expand "call_value" 979 [(set (match_operand 0 "general_operand" "") 980 (call (match_operand:QI 1 "memory_operand" "") 981 (match_operand 2 "" "")))] 982 "" 983 { 984 if (flag_pic && !legitimate_pic_operand_p (operands[1])) 985 { 986 operands[1] = gen_const_mem (QImode, 987 legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0)); 988 emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2])); 989 } 990 else 991 emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2])); 992 DONE; 993 } 994) 995 996(define_expand "cr16_call_value" 997 [(parallel 998 [(set (match_operand 0 "general_operand" "") 999 (call (match_operand 1 "memory_operand" "") 1000 (match_operand 2 "" ""))) 1001 (clobber (reg:SI RA_REGNUM))])] 1002 "" 1003 "" 1004) 1005 1006(define_insn "cr16_call_value_insn_branch_pic" 1007 [(set (match_operand 0 "" "=g") 1008 (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i")) 1009 (match_operand 2 "" ""))) 1010 (clobber (match_operand:SI 3 "register_operand" "+r"))] 1011 "flag_pic == FAR_PIC" 1012 { 1013 if (GET_CODE (operands[1]) != CONST_INT) 1014 return "loadd\t%g1, %3 \n\tjal %3"; 1015 else 1016 return "jal %3"; 1017 } 1018 [(set_attr "length" "8")] 1019) 1020 1021(define_insn "cr16_call_value_insn_branch" 1022 [(set (match_operand 0 "" "=g") 1023 (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i")) 1024 (match_operand 2 "" ""))) 1025 (clobber (match_operand:SI 3 "register_operand" "+r"))] 1026 "flag_pic == 0 || flag_pic == NEAR_PIC" 1027 { 1028 /* Print the immediate address for bal 1029 'b' is used instead of 'a' to avoid compiler calling 1030 the GO_IF_LEGITIMATE_ADDRESS which cannot 1031 perform checks on const_int code addresses as it 1032 assumes all const_int are data addresses. 1033 */ 1034 if (GET_CODE (operands[1]) != CONST_INT) 1035 return "bal (ra), %a1"; 1036 else 1037 { 1038 operands[4] = GEN_INT ((INTVAL (operands[1]))>>1); 1039 return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)"; 1040 } 1041 } 1042 [(set_attr "length" "6")] 1043) 1044 1045 1046(define_insn "cr16_call_value_insn_jump" 1047 [(set (match_operand 0 "" "=g") 1048 (call (mem:QI (match_operand:SI 1 "register_operand" "r")) 1049 (match_operand 2 "" ""))) 1050 (clobber (match_operand:SI 3 "register_operand" "+r"))] 1051 "" 1052 "jal\t%1" 1053 [(set_attr "length" "2")] 1054) 1055 1056 1057;; Nop 1058(define_insn "nop" 1059 [(const_int 0)] 1060 "" 1061 "nop\t" 1062) 1063 1064;; PIC 1065/* When generating pic, we need to load the symbol offset into a register. 1066 So that the optimizer does not confuse this with a normal symbol load 1067 we use an unspec. The offset will be loaded from a constant pool entry, 1068 since that is the only type of relocation we can use. */ 1069 1070(define_insn "unspec_bro_addr" 1071 [(set (match_operand:SI 0 "register_operand" "=r") 1072 (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))] 1073 "" 1074 "movd \t%f1, %0" 1075 [(set_attr "length" "4")] 1076) 1077 1078(define_insn "unspec_got_addr" 1079 [(set (match_operand:SI 0 "register_operand" "=r") 1080 (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))] 1081 "" 1082 "loadd \t%g1, %0" 1083 [(set_attr "length" "6")] 1084) 1085