1;; Machine Description for TI MSP43* processors 2;; Copyright (C) 2013-2018 Free Software Foundation, Inc. 3;; Contributed by Red Hat. 4 5;; This file is part of GCC. 6 7;; GCC is free software; you can redistribute it and/or modify 8;; it 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, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public 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 22(define_constants 23 [ 24 (PC_REGNO 0) 25 (SP_REGNO 1) 26 (CARRY 2) 27 ]) 28 29(define_c_enum "unspec" 30 [ 31 UNS_PROLOGUE_START_MARKER 32 UNS_PROLOGUE_END_MARKER 33 UNS_EPILOGUE_START_MARKER 34 UNS_EPILOGUE_HELPER 35 36 UNS_PUSHM 37 UNS_POPM 38 39 UNS_GROW_AND_SWAP 40 UNS_SWAP_AND_SHRINK 41 42 UNS_DINT 43 UNS_EINT 44 UNS_PUSH_INTR 45 UNS_POP_INTR 46 UNS_BIC_SR 47 UNS_BIS_SR 48 49 UNS_REFSYM_NEED_EXIT 50 51 UNS_DELAY_32 52 UNS_DELAY_32X 53 UNS_DELAY_16 54 UNS_DELAY_16X 55 UNS_DELAY_2 56 UNS_DELAY_1 57 UNS_DELAY_START 58 UNS_DELAY_END 59 ]) 60 61;; This is an approximation. 62(define_attr "length" "" (const_int 4)) 63 64(include "predicates.md") 65(include "constraints.md") 66 67(define_mode_iterator QHI [QI HI PSI]) 68 69;; There are two basic "family" tests we do here: 70;; 71;; msp430x - true if 430X instructions are available. 72;; TARGET_LARGE - true if pointers are 20-bits 73;; 74;; Note that there are three supported cases, since the base 430 75;; doesn't have 20-bit pointers: 76;; 77;; 1. MSP430 cpu, small model 78;; 2. MSP430X cpu, small model. 79;; 3. MSP430X cpu, large model. 80 81;;------------------------------------------------------------ 82;; Moves 83 84;; Push/Pop must be before the generic move patterns 85 86(define_insn "push" 87 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO))) 88 (match_operand:HI 0 "register_operand" "r"))] 89 "" 90 "PUSH\t%0" 91 ) 92 93(define_insn "pusha" 94 [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO))) 95 (match_operand:PSI 0 "register_operand" "r"))] 96 "TARGET_LARGE" 97 "PUSHX.A\t%0" 98 ) 99 100(define_insn "pushm" 101 [(unspec_volatile [(match_operand 0 "register_operand" "r") 102 (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)] 103 "" 104 "PUSHM%b0\t%1, %0" 105 ) 106 107(define_insn "pop" 108 [(set (match_operand:HI 0 "register_operand" "=r") 109 (mem:HI (post_inc:HI (reg:HI SP_REGNO))))] 110 "" 111 "POP\t%0" 112 ) 113 114(define_insn "popa" 115 [(set (match_operand:PSI 0 "register_operand" "=r") 116 (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))] 117 "TARGET_LARGE" 118 "POPX.A\t%0" 119 ) 120 121;; This is nasty. Operand0 is bogus. It is only there so that we can get a 122;; mode for the %b0 to work. We should use operand1 for this, but that does 123;; not have a mode. 124;; 125;; Operand1 is actually a register, but we cannot accept (REG...) because the 126;; cprop_hardreg pass can and will renumber registers even inside 127;; unspec_volatiles. So we take an integer register number parameter and 128;; fudge it to be a register name when we generate the assembler. 129;; 130;; The pushm pattern does not have this problem because of all of the 131;; frame info cruft attached to it, so cprop_hardreg leaves it alone. 132(define_insn "popm" 133 [(unspec_volatile [(match_operand 0 "register_operand" "r") 134 (match_operand 1 "immediate_operand" "i") 135 (match_operand 2 "immediate_operand" "i")] UNS_POPM)] 136 "" 137 "POPM%b0\t%2, r%J1" 138 ) 139 140;; The next two patterns are here to support a "feature" of how GCC implements 141;; varargs. When a function uses varargs and the *second* to last named 142;; argument is split between argument registers and the stack, gcc expects the 143;; callee to allocate space on the stack that can contain the register-based 144;; part of the argument. This space *has* to be just before the remaining 145;; arguments (ie the ones that are fully on the stack). 146;; 147;; The problem is that the MSP430 CALL instruction pushes the return address 148;; onto the stack in the exact place where the callee wants to allocate 149;; this extra space. So we need a sequence of instructions that can allocate 150;; the extra space and then move the return address down the stack, so that 151;; the extra space is now adjacent to the remaining arguments. 152;; 153;; This could be constructed through regular insns, but they might be split up 154;; by a misguided optimization, so an unspec volatile is used instead. 155 156(define_insn "grow_and_swap" 157 [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)] 158 "" 159 "* 160 if (TARGET_LARGE) 161 return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\"; 162 return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\"; 163 " 164) 165 166(define_insn "swap_and_shrink" 167 [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)] 168 "" 169 "* return TARGET_LARGE 170 ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\" 171 : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\"; 172 ") 173 174; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a 175; zero_extend anyway. Catch it here. 176(define_insn "movqihi" 177 [(set (match_operand:HI 0 "register_operand" "=r,r") 178 (zero_extend:HI (match_operand:QI 1 "memory_operand" "Ys,m")))] 179 "" 180 "@ 181 MOV.B\t%1, %0 182 MOV%X1.B\t%1, %0" 183) 184 185(define_insn "movqi_topbyte" 186 [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r") 187 (subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))] 188 "msp430x" 189 "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0" 190) 191 192(define_insn "movqi" 193 [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm") 194 (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))] 195 "" 196 "@ 197 MOV.B\t%1, %0 198 MOV%X0.B\t%1, %0" 199) 200 201(define_insn "movhi" 202 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rYs,rm") 203 (match_operand:HI 1 "msp_general_operand" "N,riYs,rmi"))] 204 "" 205 "@ 206 MOV.B\t%1, %0 207 MOV.W\t%1, %0 208 MOV%X0.W\t%1, %0" 209) 210 211(define_expand "movsi" 212 [(set (match_operand:SI 0 "nonimmediate_operand") 213 (match_operand:SI 1 "general_operand"))] 214 "" 215 "" 216 ) 217 218(define_insn_and_split "movsi_s" 219 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 220 (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] 221 "" 222 "" 223 "reload_completed" 224 [(set (match_operand:HI 2 "nonimmediate_operand") 225 (match_operand:HI 4 "general_operand")) 226 (set (match_operand:HI 3 "nonimmediate_operand") 227 (match_operand:HI 5 "general_operand"))] 228 "msp430_split_movsi (operands);" 229 ) 230 231(define_insn_and_split "movsi_x" 232 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 233 (match_operand:SI 1 "general_operand" "rmi"))] 234 "" 235 "#" 236 "reload_completed" 237 [(set (match_operand:HI 2 "nonimmediate_operand") 238 (match_operand:HI 4 "general_operand")) 239 (set (match_operand:HI 3 "nonimmediate_operand") 240 (match_operand:HI 5 "general_operand"))] 241 "msp430_split_movsi (operands);" 242) 243 244;; Some MOVX.A cases can be done with MOVA, this is only a few of them. 245(define_insn "movpsi" 246 [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,r,r,Ya,rm") 247 (match_operand:PSI 1 "msp_general_operand" "N,O,riYa,r,rmi"))] 248 "" 249 "@ 250 MOV.B\t%1, %0 251 MOV.W\t%1, %0 252 MOVA\t%1, %0 253 MOVA\t%1, %0 254 MOVX.A\t%1, %0") 255 256; This pattern is identical to the truncsipsi2 pattern except 257; that it uses a SUBREG instead of a TRUNC. It is needed in 258; order to prevent reload from converting (set:SI (SUBREG:PSI (SI))) 259; into (SET:PSI (PSI)). 260; 261; Note: using POPM.A #1 is two bytes smaller than using POPX.A.... 262 263(define_insn "movsipsi2" 264 [(set (match_operand:PSI 0 "register_operand" "=r") 265 (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))] 266 "msp430x" 267 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0" 268) 269 270;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c. 271(define_insn "*movpsihi2_lo" 272 [(set (match_operand:HI 0 "register_operand" "=r") 273 (subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] 274 "msp430x" 275 "MOVA\t%1, %0" 276) 277 278;;------------------------------------------------------------ 279;; Math 280 281(define_insn "addpsi3" 282 [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,rm") 283 (plus:PSI (match_operand:PSI 1 "msp_nonimmediate_operand" "%0,0") 284 (match_operand:PSI 2 "msp_general_operand" "rLs,rmi")))] 285 "" 286 "@ 287 ADDA\t%2, %0 288 ADDX.A\t%2, %0" 289) 290 291(define_insn "addqi3" 292 [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm") 293 (plus:QI (match_operand:QI 1 "msp_nonimmediate_operand" "%0,0") 294 (match_operand:QI 2 "msp_general_operand" "riYs,rmi")))] 295 "" 296 "@ 297 ADD.B\t%2, %0 298 ADD%X0.B\t%2, %0" 299) 300 301(define_insn "addhi3" 302 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,rm") 303 (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0") 304 (match_operand:HI 2 "msp_general_operand" "riYs,rmi")))] 305 "" 306 "@ 307 ADD.W\t%2, %0 308 ADD%X0.W\t%2, %0" 309) 310 311; This pattern is needed in order to avoid reload problems. 312; It takes an SI pair of registers, adds a value to them, and 313; then converts them into a single PSI register. 314 315(define_insn "addsipsi3" 316 [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0) 317 (plus:SI (match_operand:SI 1 "register_operand" "0") 318 (match_operand 2 "general_operand" "rmi")))] 319 "" 320 "ADD.W\t%L2, %L0 { ADDC.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0" 321) 322 323(define_insn "addsi3" 324 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,rm") 325 (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") 326 (match_operand:SI 2 "general_operand" "r,mi")))] 327 "" 328 "@ 329 ADD\t%L2, %L0 { ADDC\t%H2, %H0 330 ADD%X0\t%L2, %L0 { ADDC%X0\t%H2, %H0" 331) 332 333; Version of addhi that exposes the carry operations, for SImode adds. 334; 335; NOTE - we are playing a dangerous game with GCC here. We have these two 336; add patterns and the splitter that follows because our tests have shown 337; that this results in a significant reduction in code size - because GCC is 338; able to discard any unused part of the addition. We have to annotate the 339; patterns with the set and use of the carry flag because otherwise GCC will 340; discard parts of the addition when they are actually needed. But we have 341; not annotated all the other patterns that set the CARRY flag as doing so 342; results in an overall increase in code size[1]. Instead we just *hope* 343; that GCC will not move a carry-setting instruction in between the first 344; and second adds. 345; 346; So far our experiments have shown that GCC is likely to move MOV and CMP 347; instructions in between the two adds, but not other instructions. MOV is 348; safe, CMP is not. So we have annotated the CMP patterns and left the 349; subtract, shift and other add patterns alone. At the moment this is 350; working, but with future changes to the generic parts of GCC that might 351; change. 352; 353; [1] It is not clear exactly why the code size increases. The cause appears 354; to be that reload is more prevelent to spilling a variable onto the stack 355; but why it does this is unknown. Possibly the additional CLOBBERs necessary 356; to correctly annotate the other patterns makes reload think that there is 357; increased register pressure. Or possibly reload does not handle ADD patterns 358; that are not single_set() very well. 359 360(define_insn "addhi3_cy" 361 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm") 362 (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0") 363 (match_operand:HI 2 "msp_nonimmediate_operand" "r,rm"))) 364 (set (reg:BI CARRY) 365 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) 366 (zero_extend:SI (match_dup 2))) 367 (const_int 16)))) 368 ] 369 "" 370 "@ 371 ADD\t%2, %1 ; cy 372 ADD%X0\t%2, %1 ; cy" 373 ) 374 375(define_insn "addhi3_cy_i" 376 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,rm") 377 (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") 378 (match_operand:HI 2 "immediate_operand" "i,i"))) 379 (set (reg:BI CARRY) 380 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) 381 (match_operand 3 "immediate_operand" "i,i")) 382 (const_int 16)))) 383 ] 384 "" 385 "@ 386 ADD\t%2, %1 ; cy 387 ADD%X0\t%2, %1 ; cy" 388 ) 389 390; Version of addhi that adds the carry, for SImode adds. 391(define_insn "addchi4_cy" 392 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=r,rm") 393 (plus:HI (plus:HI (match_operand:HI 1 "msp_nonimmediate_operand" "%0,0") 394 (match_operand:HI 2 "msp_general_operand" "ri,rmi")) 395 (zero_extend:HI (reg:BI CARRY)))) 396 ] 397 "" 398 "@ 399 ADDC\t%2, %1 400 ADDC%X0\t%2, %1" 401 ) 402 403; Split an SImode add into two HImode adds, keeping track of the carry 404; so that gcc knows when it can and can't optimize away the two 405; halves. 406(define_split 407 [(set (match_operand:SI 0 "msp430_nonsubreg_operand") 408 (plus:SI (match_operand:SI 1 "msp430_nonsubreg_operand") 409 (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand"))) 410 ] 411 "" 412 [(parallel [(set (match_operand:HI 3 "nonimmediate_operand" "=&rm") 413 (plus:HI (match_dup 4) 414 (match_dup 5))) 415 (set (reg:BI CARRY) 416 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4)) 417 (match_dup 9)) 418 (const_int 16)))) 419 ]) 420 (set (match_operand:HI 6 "nonimmediate_operand" "=&rm") 421 (plus:HI (plus:HI (match_dup 7) 422 (match_dup 8)) 423 (zero_extend:HI (reg:BI CARRY)))) 424 ] 425 " 426 operands[3] = msp430_subreg (HImode, operands[0], SImode, 0); 427 operands[4] = msp430_subreg (HImode, operands[1], SImode, 0); 428 operands[5] = msp430_subreg (HImode, operands[2], SImode, 0); 429 operands[6] = msp430_subreg (HImode, operands[0], SImode, 2); 430 operands[7] = msp430_subreg (HImode, operands[1], SImode, 2); 431 operands[8] = msp430_subreg (HImode, operands[2], SImode, 2); 432 433 /* BZ 64160: Do not use this splitter when the dest partially overlaps the source. */ 434 if (reg_overlap_mentioned_p (operands[3], operands[7]) 435 || reg_overlap_mentioned_p (operands[3], operands[8])) 436 FAIL; 437 438 if (GET_CODE (operands[5]) == CONST_INT) 439 operands[9] = GEN_INT (INTVAL (operands[5]) & 0xffff); 440 else 441 operands[9] = gen_rtx_ZERO_EXTEND (SImode, operands[5]); 442 " 443 ) 444 445 446;; Alternatives 2 and 3 are to handle cases generated by reload. 447(define_insn "subpsi3" 448 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r, rm, &?r, ?&r") 449 (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i") 450 (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))] 451 "" 452 "@ 453 SUBA\t%2, %0 454 SUBX.A\t%2, %0 455 MOVX.A\t%1, %0 { SUBX.A\t%2, %0 456 MOVX.A\t%1, %0 { SUBA\t%2, %0" 457) 458 459;; Alternatives 2 and 3 are to handle cases generated by reload. 460(define_insn "subqi3" 461 [(set (match_operand:QI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r") 462 (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i") 463 (match_operand:QI 2 "general_operand" " riYs, rmi, rmi, r")))] 464 "" 465 "@ 466 SUB.B\t%2, %0 467 SUB%X0.B\t%2, %0 468 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0 469 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0" 470) 471 472;; Alternatives 2 and 3 are to handle cases generated by reload. 473(define_insn "subhi3" 474 [(set (match_operand:HI 0 "nonimmediate_operand" "=rYs, rm, &?r, ?&r") 475 (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i") 476 (match_operand:HI 2 "general_operand" " riYs, rmi, rmi, r")))] 477 "" 478 "@ 479 SUB.W\t%2, %0 480 SUB%X0.W\t%2, %0 481 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0 482 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0" 483) 484 485(define_insn "subsi3" 486 [(set (match_operand:SI 0 "nonimmediate_operand" "=&rm") 487 (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0") 488 (match_operand:SI 2 "general_operand" "rmi")))] 489 "" 490 "SUB%X0\t%L2, %L0 { SUBC%X0\t%H2, %H0" 491) 492 493(define_insn "*bic<mode>_cg" 494 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m") 495 (and:QHI (match_operand:QHI 1 "msp_general_operand" "0,0") 496 (match_operand 2 "msp430_inv_constgen_operator" "n,n")))] 497 "" 498 "@ 499 BIC%x0%b0\t#%I2, %0 500 BIC%X0%b0\t#%I2, %0" 501) 502 503(define_insn "bic<mode>3" 504 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm") 505 (and:QHI (not:QHI (match_operand:QHI 1 "msp_general_operand" "rYs,rmn")) 506 (match_operand:QHI 2 "msp_nonimmediate_operand" "0,0")))] 507 "" 508 "@ 509 BIC%x0%b0\t%1, %0 510 BIC%X0%b0\t%1, %0" 511) 512 513(define_insn "and<mode>3" 514 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=r,rYs,rm") 515 (and:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0,0") 516 (match_operand:QHI 2 "msp_general_operand" "N,riYs,rmi")))] 517 "" 518 "@ 519 AND%x0.B\t%2, %0 520 AND%x0%b0\t%2, %0 521 AND%X0%b0\t%2, %0" 522) 523 524(define_insn "ior<mode>3" 525 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm") 526 (ior:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0") 527 (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))] 528 "" 529 "@ 530 BIS%x0%b0\t%2, %0 531 BIS%X0%b0\t%2, %0" 532) 533 534(define_insn "xor<mode>3" 535 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,rm") 536 (xor:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "%0,0") 537 (match_operand:QHI 2 "msp_general_operand" "riYs,rmi")))] 538 "" 539 "@ 540 XOR%x0%b0\t%2, %0 541 XOR%X0%b0\t%2, %0" 542) 543 544;; Macro : XOR #~0, %0 545(define_insn "one_cmpl<mode>2" 546 [(set (match_operand:QHI 0 "msp_nonimmediate_operand" "=rYs,m") 547 (not:QHI (match_operand:QHI 1 "msp_nonimmediate_operand" "0,0")))] 548 "" 549 "@ 550 INV%x0%b0\t%0 551 INV%X0%b0\t%0" 552) 553 554(define_insn "extendqihi2" 555 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,m") 556 (sign_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,0")))] 557 "" 558 "@ 559 SXT%X0\t%0 560 SXT%X0\t%0" 561) 562 563(define_insn "zero_extendqihi2" 564 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rYs,r,r,m") 565 (zero_extend:HI (match_operand:QI 1 "msp_nonimmediate_operand" "0,rYs,m,0")))] 566 "" 567 "@ 568 AND\t#0xff, %0 569 MOV.B\t%1, %0 570 MOV%X0.B\t%1, %0 571 AND%X0\t#0xff, %0" 572) 573 574;; Eliminate extraneous zero-extends mysteriously created by gcc. 575(define_peephole2 576 [(set (match_operand:HI 0 "register_operand") 577 (zero_extend:HI (match_operand:QI 1 "general_operand"))) 578 (set (match_operand:HI 2 "register_operand") 579 (zero_extend:HI (match_operand:QI 3 "register_operand")))] 580 "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])" 581 [(set (match_dup 0) 582 (zero_extend:HI (match_dup 1)))] 583) 584 585(define_insn "zero_extendhipsi2" 586 [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,m") 587 (zero_extend:PSI (match_operand:HI 1 "msp_nonimmediate_operand" "rm,r")))] 588 "" 589 "@ 590 MOVX\t%1, %0 591 MOVX.A\t%1, %0" 592) 593 594(define_insn "truncpsihi2" 595 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rm") 596 (truncate:HI (match_operand:PSI 1 "register_operand" "r")))] 597 "" 598 "MOVX\t%1, %0" 599) 600 601(define_insn "extendhisi2" 602 [(set (match_operand:SI 0 "nonimmediate_operand" "=r") 603 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))] 604 "" 605 { return msp430x_extendhisi (operands); } 606) 607 608(define_insn "extendhipsi2" 609 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r") 610 (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))] 611 "msp430x" 612 "RLAM.A #4, %0 { RRAM.A #4, %0" 613) 614 615;; Look for cases where integer/pointer conversions are suboptimal due 616;; to missing patterns, despite us not having opcodes for these 617;; patterns. Doing these manually allows for alternate optimization 618;; paths. 619 620(define_insn "zero_extendqisi2" 621 [(set (match_operand:SI 0 "nonimmediate_operand" "=r") 622 (zero_extend:SI (subreg:HI (match_operand:QI 1 "nonimmediate_operand" "rm") 0)))] 623 "msp430x" 624 "MOV.B\t%1,%L0 { CLR\t%H0" 625) 626 627(define_insn "zero_extendhisi2" 628 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") 629 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")))] 630 "msp430x" 631 "@ 632 MOV.W\t#0,%H0 633 MOV.W\t%1,%L0 { MOV.W\t#0,%H0" 634) 635 636(define_insn "zero_extendhisipsi2" 637 [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r") 638 (subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))] 639 "msp430x" 640 "@ 641 AND.W\t#-1,%0 642 MOV.W\t%1,%0" 643) 644 645(define_insn "extend_and_shift1_hipsi2" 646 [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0) 647 (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 648 (const_int 1)))] 649 "msp430x" 650 "RLAM.A #4, %0 { RRAM.A #3, %0" 651) 652 653(define_insn "extend_and_shift2_hipsi2" 654 [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0) 655 (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 656 (const_int 2)))] 657 "msp430x" 658 "RLAM.A #4, %0 { RRAM.A #2, %0" 659) 660 661; Nasty - we are sign-extending a 20-bit PSI value in one register into 662; two adjacent 16-bit registers to make an SI value. There is no MSP430X 663; instruction that will do this, so we push the 20-bit value onto the stack 664; and then pop it off as two 16-bit values. 665; 666; FIXME: The MSP430X documentation does not specify if zero-extension or 667; sign-extension happens when the 20-bit value is pushed onto the stack. 668; It is probably zero-extension, but if not this pattern will not work 669; when the PSI value is negative.. 670; 671; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A.... 672; 673; Note: We use a + constraint on operand 0 as otherwise GCC gets confused 674; about extending a single PSI mode register into a pair of SImode registers 675; with the same starting register. It thinks that the upper register of 676; the pair is unused and so it can clobber it. Try compiling 20050826-2.c 677; at -O2 to see this. 678 679(define_insn "zero_extendpsisi2" 680 [(set (match_operand:SI 0 "register_operand" "+r") 681 (zero_extend:SI (match_operand:PSI 1 "register_operand" "r")))] 682 "" 683 "* 684 if (REGNO (operands[1]) == SP_REGNO) 685 /* If the source register is the stack pointer, the value 686 stored in the stack slot will be the value *after* the 687 stack pointer has been decremented. So allow for that 688 here. */ 689 return \"PUSHM.A\t#1, %1 { ADDX.W\t#4, @r1 { POPX.W\t%L0 { POPX.W\t%H0 ; get stack pointer into %L0:%H0\"; 690 else 691 return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\"; 692 " 693) 694 695;; We also need to be able to sign-extend pointer types (eg ptrdiff_t). 696;; Since (we assume) pushing a 20-bit value onto the stack zero-extends 697;; it, we use a different method here. 698 699(define_insn "extendpsisi2" 700 [(set (match_operand:SI 0 "register_operand" "=r") 701 (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))] 702 "msp430x" 703 "* 704 /* The intention here is that we copy the bottom 16-bits of 705 %1 into %L0 (zeroing the top four bits). Then we copy the 706 entire 20-bits of %1 into %H0 and then arithmetically shift 707 it right by 16 bits, to get the top four bits of the pointer 708 sign-extended in %H0. */ 709 if (REGNO (operands[0]) == REGNO (operands[1])) 710 return \"MOVX.A\t%1, %H0 { MOV.W\t%1, %L0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\"; 711 else 712 return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\"; 713 " 714) 715 716; See the movsipsi2 pattern above for another way that GCC performs this 717; conversion. 718(define_insn "truncsipsi2" 719 [(set (match_operand:PSI 0 "register_operand" "=r") 720 (truncate:PSI (match_operand:SI 1 "register_operand" "r")))] 721 "" 722 "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0" 723) 724 725;;------------------------------------------------------------ 726;; Shift Functions 727 728;; Note: We do not use the RPT ... SHIFT instruction sequence 729;; when the repeat count is in a register, because even though RPT 730;; accepts counts in registers, it does not work if the count is 731;; zero, and the actual count in the register has to be one less 732;; than the required number of iterations. We could encode a 733;; seqeunce like this: 734;; 735;; bit #0xf, Rn 736;; bz 1f 737;; dec Rn 738;; rpt Rn 739;; <shift> Rm 740;; inc Rn 741;; 1: 742;; 743;; But is longer than calling a helper function, and we are mostly 744;; concerned with code size. FIXME: Maybe enable a sequence like 745;; this at -O3 and above ? 746;; 747;; Note - we ignore shift counts of less than one or more than 15. 748;; This is permitted by the ISO C99 standard as such shifts result 749;; in "undefined" behavior. [6.5.7 (3)] 750 751;; signed A << C 752 753(define_expand "ashlhi3" 754 [(set (match_operand:HI 0 "nonimmediate_operand") 755 (ashift:HI (match_operand:HI 1 "general_operand") 756 (match_operand:HI 2 "general_operand")))] 757 "" 758 { 759 if (GET_CODE (operands[1]) == SUBREG 760 && REG_P (XEXP (operands[1], 0))) 761 operands[1] = force_reg (HImode, operands[1]); 762 if (msp430x 763 && REG_P (operands[0]) 764 && REG_P (operands[1]) 765 && CONST_INT_P (operands[2])) 766 emit_insn (gen_430x_shift_left (operands[0], operands[1], operands[2])); 767 else if (CONST_INT_P (operands[2]) 768 && INTVAL (operands[2]) == 1) 769 emit_insn (gen_slli_1 (operands[0], operands[1])); 770 else 771 msp430_expand_helper (operands, \"__mspabi_slli\", true); 772 DONE; 773 } 774) 775 776(define_insn "slli_1" 777 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") 778 (ashift:HI (match_operand:HI 1 "general_operand" "0") 779 (const_int 1)))] 780 "" 781 "RLA.W\t%0" ;; Note - this is a macro for ADD 782) 783 784(define_insn "430x_shift_left" 785 [(set (match_operand:HI 0 "register_operand" "=r") 786 (ashift:HI (match_operand:HI 1 "register_operand" "0") 787 (match_operand 2 "immediate_operand" "n")))] 788 "msp430x" 789 "* 790 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16) 791 return \"rpt\t%2 { rlax.w\t%0\"; 792 return \"# nop left shift\"; 793 " 794) 795 796(define_insn "slll_1" 797 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 798 (ashift:SI (match_operand:SI 1 "general_operand" "0") 799 (const_int 1)))] 800 "" 801 "RLA.W\t%L0 { RLC.W\t%H0" 802) 803 804(define_insn "slll_2" 805 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 806 (ashift:SI (match_operand:SI 1 "general_operand" "0") 807 (const_int 2)))] 808 "" 809 "RLA.W\t%L0 { RLC.W\t%H0 { RLA.W\t%L0 { RLC.W\t%H0" 810) 811 812(define_expand "ashlsi3" 813 [(set (match_operand:SI 0 "nonimmediate_operand") 814 (ashift:SI (match_operand:SI 1 "general_operand") 815 (match_operand:SI 2 "general_operand")))] 816 "" 817 "msp430_expand_helper (operands, \"__mspabi_slll\", true); 818 DONE;" 819) 820 821;;---------- 822 823;; signed A >> C 824 825(define_expand "ashrhi3" 826 [(set (match_operand:HI 0 "nonimmediate_operand") 827 (ashiftrt:HI (match_operand:HI 1 "general_operand") 828 (match_operand:HI 2 "general_operand")))] 829 "" 830 { 831 if (GET_CODE (operands[1]) == SUBREG 832 && REG_P (XEXP (operands[1], 0))) 833 operands[1] = force_reg (HImode, operands[1]); 834 if (msp430x 835 && REG_P (operands[0]) 836 && REG_P (operands[1]) 837 && CONST_INT_P (operands[2])) 838 emit_insn (gen_430x_arithmetic_shift_right (operands[0], operands[1], operands[2])); 839 else if (CONST_INT_P (operands[2]) 840 && INTVAL (operands[2]) == 1) 841 emit_insn (gen_srai_1 (operands[0], operands[1])); 842 else 843 msp430_expand_helper (operands, \"__mspabi_srai\", true); 844 DONE; 845 } 846) 847 848(define_insn "srai_1" 849 [(set (match_operand:HI 0 "msp_nonimmediate_operand" "=rm") 850 (ashiftrt:HI (match_operand:HI 1 "msp_general_operand" "0") 851 (const_int 1)))] 852 "" 853 "RRA.W\t%0" 854) 855 856(define_insn "430x_arithmetic_shift_right" 857 [(set (match_operand:HI 0 "register_operand" "=r") 858 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") 859 (match_operand 2 "immediate_operand" "n")))] 860 "msp430x" 861 "* 862 if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 16) 863 return \"rpt\t%2 { rrax.w\t%0\"; 864 return \"# nop arith right shift\"; 865 " 866) 867 868(define_insn "srap_1" 869 [(set (match_operand:PSI 0 "register_operand" "=r") 870 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0") 871 (const_int 1)))] 872 "msp430x" 873 "RRAM.A #1,%0" 874) 875 876(define_insn "srap_2" 877 [(set (match_operand:PSI 0 "register_operand" "=r") 878 (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "0") 879 (const_int 2)))] 880 "msp430x" 881 "RRAM.A #2,%0" 882) 883 884(define_insn "sral_1" 885 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 886 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") 887 (const_int 1)))] 888 "" 889 "RRA.W\t%H0 { RRC.W\t%L0" 890) 891 892(define_insn "sral_2" 893 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 894 (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") 895 (const_int 2)))] 896 "" 897 "RRA.W\t%H0 { RRC.W\t%L0 { RRA.W\t%H0 { RRC.W\t%L0" 898) 899 900(define_expand "ashrsi3" 901 [(set (match_operand:SI 0 "nonimmediate_operand") 902 (ashiftrt:SI (match_operand:SI 1 "general_operand") 903 (match_operand:SI 2 "general_operand")))] 904 "" 905 "msp430_expand_helper (operands, \"__mspabi_sral\", true); 906 DONE;" 907) 908 909;;---------- 910 911;; unsigned A >> C 912 913(define_expand "lshrhi3" 914 [(set (match_operand:HI 0 "nonimmediate_operand") 915 (lshiftrt:HI (match_operand:HI 1 "general_operand") 916 (match_operand:HI 2 "general_operand")))] 917 "" 918 { 919 if (GET_CODE (operands[1]) == SUBREG 920 && REG_P (XEXP (operands[1], 0))) 921 operands[1] = force_reg (HImode, operands[1]); 922 if (msp430x 923 && REG_P (operands[0]) 924 && REG_P (operands[1]) 925 && CONST_INT_P (operands[2])) 926 emit_insn (gen_430x_logical_shift_right (operands[0], operands[1], operands[2])); 927 else if (CONST_INT_P (operands[2]) 928 && INTVAL (operands[2]) == 1) 929 emit_insn (gen_srli_1 (operands[0], operands[1])); 930 else 931 msp430_expand_helper (operands, \"__mspabi_srli\", true); 932 DONE; 933 } 934) 935 936(define_insn "srli_1" 937 [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") 938 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") 939 (const_int 1)))] 940 "" 941 "CLRC { RRC.W\t%0" 942) 943 944(define_insn "430x_logical_shift_right" 945 [(set (match_operand:HI 0 "register_operand" "=r") 946 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") 947 (match_operand 2 "immediate_operand" "n")))] 948 "msp430x" 949 { 950 return msp430x_logical_shift_right (operands[2]); 951 } 952) 953 954(define_insn "srlp_1" 955 [(set (match_operand:PSI 0 "register_operand" "=r") 956 (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "0") 957 (const_int 1)))] 958 "" 959 "RRUM.A #1,%0" 960) 961 962(define_insn "srll_1" 963 [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") 964 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") 965 (const_int 1)))] 966 "" 967 "CLRC { RRC.W\t%H0 { RRC.W\t%L0" 968) 969 970(define_insn "srll_2x" 971 [(set (match_operand:SI 0 "nonimmediate_operand" "=r") 972 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") 973 (const_int 2)))] 974 "msp430x" 975 "RRUX.W\t%H0 { RRC.W\t%L0 { RRUX.W\t%H0 { RRC.W\t%L0" 976) 977 978(define_expand "lshrsi3" 979 [(set (match_operand:SI 0 "nonimmediate_operand") 980 (lshiftrt:SI (match_operand:SI 1 "general_operand") 981 (match_operand:SI 2 "general_operand")))] 982 "" 983 "msp430_expand_helper (operands, \"__mspabi_srll\", true); 984 DONE;" 985) 986 987;;------------------------------------------------------------ 988;; Function Entry/Exit 989 990(define_expand "prologue" 991 [(const_int 0)] 992 "" 993 "msp430_expand_prologue (); DONE;" 994 ) 995 996(define_expand "epilogue" 997 [(const_int 0)] 998 "" 999 "msp430_expand_epilogue (0); DONE;" 1000 ) 1001 1002(define_insn "epilogue_helper" 1003 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)] 1004 "" 1005 "BR%Q0\t#__mspabi_func_epilog_%J0" 1006 ) 1007 1008(define_insn "prologue_start_marker" 1009 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)] 1010 "" 1011 "; start of prologue" 1012 ) 1013 1014(define_insn "prologue_end_marker" 1015 [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)] 1016 "" 1017 "; end of prologue" 1018 ) 1019 1020(define_insn "epilogue_start_marker" 1021 [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)] 1022 "" 1023 "; start of epilogue" 1024 ) 1025 1026;; This makes the linker add a call to exit() after the call to main() 1027;; in crt0 1028(define_insn "msp430_refsym_need_exit" 1029 [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)] 1030 "" 1031 ".refsym\t__crt0_call_exit" 1032 ) 1033 1034;;------------------------------------------------------------ 1035;; Jumps 1036 1037(define_expand "call" 1038 [(call:HI (match_operand 0 "") 1039 (match_operand 1 ""))] 1040 "" 1041 "" 1042) 1043 1044(define_insn "call_internal" 1045 [(call (mem:HI (match_operand 0 "general_operand" "rYci")) 1046 (match_operand 1 ""))] 1047 "" 1048 "CALL%Q0\t%0" 1049) 1050 1051(define_expand "call_value" 1052 [(set (match_operand 0 "register_operand") 1053 (call:HI (match_operand 1 "general_operand") 1054 (match_operand 2 "")))] 1055 "" 1056 "" 1057) 1058 1059(define_insn "call_value_internal" 1060 [(set (match_operand 0 "register_operand" "=r") 1061 (call (mem:HI (match_operand 1 "general_operand" "rYci")) 1062 (match_operand 2 "")))] 1063 "" 1064 "CALL%Q0\t%1" 1065) 1066 1067(define_insn "msp_return" 1068 [(return)] 1069 "" 1070 { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); } 1071) 1072 1073;; This pattern is NOT, as expected, a return pattern. It's called 1074;; before reload and must only store its operands, and emit a 1075;; placeholder where the epilog needs to be. AFTER reload, the 1076;; placeholder should get expanded into a regular-type epilogue that 1077;; also does the EH return. 1078(define_expand "eh_return" 1079 [(match_operand:HI 0 "")] 1080 "" 1081 "msp430_expand_eh_return (operands[0]); 1082 emit_jump_insn (gen_msp430_eh_epilogue ()); 1083 emit_barrier (); 1084 DONE;" 1085) 1086 1087;; This is the actual EH epilogue. We emit it in the pattern above, 1088;; before reload, and convert it to a real epilogue after reload. 1089(define_insn_and_split "msp430_eh_epilogue" 1090 [(eh_return)] 1091 "" 1092 "#" 1093 "reload_completed" 1094 [(const_int 0)] 1095 "msp430_expand_epilogue (1); DONE;" 1096 ) 1097 1098(define_insn "jump" 1099 [(set (pc) 1100 (label_ref (match_operand 0 "" "")))] 1101 "" 1102 "BR%Q0\t#%l0" 1103) 1104 1105;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs 1106;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c). 1107(define_insn "indirect_jump" 1108 [(set (pc) 1109 (match_operand 0 "nonimmediate_operand" "rYl"))] 1110 "" 1111 "BR%Q0\t%0" 1112) 1113 1114;;------------------------------------------------------------ 1115;; Various Conditionals 1116 1117(define_expand "cbranch<mode>4" 1118 [(parallel [(set (pc) (if_then_else 1119 (match_operator 0 "" 1120 [(match_operand:QHI 1 "nonimmediate_operand") 1121 (match_operand:QHI 2 "general_operand")]) 1122 (label_ref (match_operand 3 "" "")) 1123 (pc))) 1124 (clobber (reg:BI CARRY))] 1125 )] 1126 "" 1127 "msp430_fixup_compare_operands (<MODE>mode, operands);" 1128 ) 1129 1130(define_insn "cbranchpsi4_real" 1131 [(set (pc) (if_then_else 1132 (match_operator 0 "msp430_cmp_operator" 1133 [(match_operand:PSI 1 "nonimmediate_operand" "r,rYs,rm") 1134 (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")]) 1135 (label_ref (match_operand 3 "" "")) 1136 (pc))) 1137 (clobber (reg:BI CARRY)) 1138 ] 1139 "" 1140 "@ 1141 CMP%Q0\t%2, %1 { J%0\t%l3 1142 CMPX.A\t%2, %1 { J%0\t%l3 1143 CMPX.A\t%2, %1 { J%0\t%l3" 1144 ) 1145 1146(define_insn "cbranchqi4_real" 1147 [(set (pc) (if_then_else 1148 (match_operator 0 "msp430_cmp_operator" 1149 [(match_operand:QI 1 "nonimmediate_operand" "rYs,rm") 1150 (match_operand:QI 2 "general_operand" "rYsi,rmi")]) 1151 (label_ref (match_operand 3 "" "")) 1152 (pc))) 1153 (clobber (reg:BI CARRY)) 1154 ] 1155 "" 1156 "@ 1157 CMP.B\t%2, %1 { J%0\t%l3 1158 CMP%X0.B\t%2, %1 { J%0\t%l3" 1159 ) 1160 1161(define_insn "cbranchhi4_real" 1162 [(set (pc) (if_then_else 1163 (match_operator 0 "msp430_cmp_operator" 1164 [(match_operand:HI 1 "nonimmediate_operand" "rYs,rm") 1165 (match_operand:HI 2 "general_operand" "rYsi,rmi")]) 1166 (label_ref (match_operand 3 "" "")) 1167 (pc))) 1168 (clobber (reg:BI CARRY)) 1169 ] 1170 "" 1171 "* 1172 /* This is nasty. If we are splitting code between low and high memory 1173 then we do not want the linker to increase the size of sections by 1174 relaxing out of range jump instructions. (Since relaxation occurs 1175 after section placement). So we have to generate pessimal branches 1176 here. But we only want to do this when really necessary. 1177 1178 FIXME: Do we need code in the other cbranch patterns ? */ 1179 if (msp430_do_not_relax_short_jumps () && get_attr_length (insn) > 6) 1180 { 1181 return which_alternative == 0 ? 1182 \"CMP.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\" : 1183 \"CMP%X0.W\t%2, %1 { J%r0 1f { BRA #%l3 { 1:\"; 1184 } 1185 1186 return which_alternative == 0 ? 1187 \"CMP.W\t%2, %1 { J%0\t%l3\" : 1188 \"CMP%X0.W\t%2, %1 { J%0\t%l3\"; 1189 " 1190 [(set (attr "length") 1191 (if_then_else 1192 (and (ge (minus (match_dup 3) (pc)) (const_int -510)) 1193 (le (minus (match_dup 3) (pc)) (const_int 510))) 1194 (const_int 6) 1195 (const_int 10)) 1196 )] 1197 ) 1198 1199(define_insn "cbranchpsi4_reversed" 1200 [(set (pc) (if_then_else 1201 (match_operator 0 "msp430_reversible_cmp_operator" 1202 [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi") 1203 (match_operand:PSI 2 "general_operand" "r,rYs,rm")]) 1204 (label_ref (match_operand 3 "" "")) 1205 (pc))) 1206 (clobber (reg:BI CARRY)) 1207 ] 1208 "" 1209 "@ 1210 CMP%Q0\t%1, %2 { J%R0\t%l3 1211 CMPX.A\t%1, %2 { J%R0\t%l3 1212 CMPX.A\t%1, %2 { J%R0\t%l3" 1213 ) 1214 1215(define_insn "cbranchqi4_reversed" 1216 [(set (pc) (if_then_else 1217 (match_operator 0 "msp430_reversible_cmp_operator" 1218 [(match_operand:QI 1 "general_operand" "rYsi,rmi") 1219 (match_operand:QI 2 "general_operand" "rYs,rm")]) 1220 (label_ref (match_operand 3 "" "")) 1221 (pc))) 1222 (clobber (reg:BI CARRY)) 1223 ] 1224 "" 1225 "@ 1226 CMP.B\t%1, %2 { J%R0\t%l3 1227 CMP%X0.B\t%1, %2 { J%R0\t%l3" 1228 ) 1229 1230(define_insn "cbranchhi4_reversed" 1231 [(set (pc) (if_then_else 1232 (match_operator 0 "msp430_reversible_cmp_operator" 1233 [(match_operand:HI 1 "general_operand" "rYsi,rmi") 1234 (match_operand:HI 2 "general_operand" "rYs,rm")]) 1235 (label_ref (match_operand 3 "" "")) 1236 (pc))) 1237 (clobber (reg:BI CARRY)) 1238 ] 1239 "" 1240 "@ 1241 CMP.W\t%1, %2 { J%R0\t%l3 1242 CMP%X0.W\t%1, %2 { J%R0\t%l3" 1243 ) 1244 1245(define_insn "*bitbranch<mode>4" 1246 [(set (pc) (if_then_else 1247 (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm") 1248 (match_operand:QHI 1 "msp_general_operand" "rYsi,rmi")) 1249 (const_int 0)) 1250 (label_ref (match_operand 2 "" "")) 1251 (pc))) 1252 (clobber (reg:BI CARRY)) 1253 ] 1254 "" 1255 "@ 1256 BIT%x0%b0\t%1, %0 { JNE\t%l2 1257 BIT%X0%b0\t%1, %0 { JNE\t%l2" 1258 ) 1259 1260(define_insn "*bitbranch<mode>4" 1261 [(set (pc) (if_then_else 1262 (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") 1263 (match_operand:QHI 1 "msp_general_operand" "rmi")) 1264 (const_int 0)) 1265 (label_ref (match_operand 2 "" "")) 1266 (pc))) 1267 (clobber (reg:BI CARRY)) 1268 ] 1269 "" 1270 "BIT%x0%b0\t%1, %0 { JEQ\t%l2" 1271 ) 1272 1273(define_insn "*bitbranch<mode>4" 1274 [(set (pc) (if_then_else 1275 (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") 1276 (match_operand:QHI 1 "msp_general_operand" "rmi")) 1277 (const_int 0)) 1278 (pc) 1279 (label_ref (match_operand 2 "" "")))) 1280 (clobber (reg:BI CARRY)) 1281 ] 1282 "" 1283 "BIT%X0%b0\t%1, %0 { JNE\t%l2" 1284 ) 1285 1286(define_insn "*bitbranch<mode>4" 1287 [(set (pc) (if_then_else 1288 (ne (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") 1289 (match_operand:QHI 1 "msp_general_operand" "rmi")) 1290 (const_int 0)) 1291 (pc) 1292 (label_ref (match_operand 2 "" "")))) 1293 (clobber (reg:BI CARRY)) 1294 ] 1295 "" 1296 "BIT%X0%b0\t%1, %0 { JEQ\t%l2" 1297 ) 1298 1299;;------------------------------------------------------------ 1300;; zero-extract versions of the above 1301 1302(define_insn "*bitbranch<mode>4_z" 1303 [(set (pc) (if_then_else 1304 (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rYs,rm") 1305 (const_int 1) 1306 (match_operand 1 "msp430_bitpos" "i,i")) 1307 (const_int 0)) 1308 (label_ref (match_operand 2 "" "")) 1309 (pc))) 1310 (clobber (reg:BI CARRY)) 1311 ] 1312 "" 1313 "@ 1314 BIT%x0%b0\t%p1, %0 { JNE\t%l2 1315 BIT%X0%b0\t%p1, %0 { JNE\t%l2" 1316 ) 1317 1318(define_insn "*bitbranch<mode>4_z" 1319 [(set (pc) (if_then_else 1320 (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") 1321 (const_int 1) 1322 (match_operand 1 "msp430_bitpos" "i")) 1323 (const_int 0)) 1324 (label_ref (match_operand 2 "" "")) 1325 (pc))) 1326 (clobber (reg:BI CARRY)) 1327 ] 1328 "" 1329 "BIT%x0%X0%b0\t%p1, %0 { JEQ\t%l2" 1330 ) 1331 1332(define_insn "*bitbranch<mode>4_z" 1333 [(set (pc) (if_then_else 1334 (eq (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") 1335 (const_int 1) 1336 (match_operand 1 "msp430_bitpos" "i")) 1337 (const_int 0)) 1338 (pc) 1339 (label_ref (match_operand 2 "" "")))) 1340 (clobber (reg:BI CARRY)) 1341 ] 1342 "" 1343 "BIT%X0%b0\t%p1, %0 { JNE\t%l2" 1344 ) 1345 1346(define_insn "*bitbranch<mode>4_z" 1347 [(set (pc) (if_then_else 1348 (ne (zero_extract:HI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") 1349 (const_int 1) 1350 (match_operand 1 "msp430_bitpos" "i")) 1351 (const_int 0)) 1352 (pc) 1353 (label_ref (match_operand 2 "" "")))) 1354 (clobber (reg:BI CARRY)) 1355 ] 1356 "" 1357 "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" 1358 ) 1359 1360;;------------------------------------------------------------ 1361;; Misc 1362 1363(define_insn "nop" 1364 [(const_int 0)] 1365 "1" 1366 "NOP" 1367) 1368 1369(define_insn "disable_interrupts" 1370 [(unspec_volatile [(const_int 0)] UNS_DINT)] 1371 "" 1372 "DINT \; NOP" 1373 ) 1374 1375(define_insn "enable_interrupts" 1376 [(unspec_volatile [(const_int 0)] UNS_EINT)] 1377 "" 1378 "EINT" 1379 ) 1380 1381(define_insn "push_intr_state" 1382 [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)] 1383 "" 1384 "PUSH\tSR" 1385 ) 1386 1387(define_insn "pop_intr_state" 1388 [(unspec_volatile [(const_int 0)] UNS_POP_INTR)] 1389 "" 1390 "POP\tSR" 1391 ) 1392 1393;; Clear bits in the copy of the status register that is currently 1394;; saved on the stack at the top of the interrupt handler. 1395(define_insn "bic_SR" 1396 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)] 1397 "" 1398 "BIC.W\t%0, %O0(SP)" 1399 ) 1400 1401;; Set bits in the copy of the status register that is currently 1402;; saved on the stack at the top of the interrupt handler. 1403(define_insn "bis_SR" 1404 [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)] 1405 "" 1406 "BIS.W\t%0, %O0(SP)" 1407 ) 1408 1409;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int))) 1410;; very late on in the compilation and not splitting it into separate 1411;; instructions, so we provide a pattern to support it here. 1412(define_insn "andneghi3" 1413 [(set (match_operand:HI 0 "register_operand" "=r") 1414 (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r")) 1415 (match_operand 2 "immediate_operand" "n")))] 1416 "" 1417 "* 1418 if (REGNO (operands[0]) != REGNO (operands[1])) 1419 return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\"; 1420 else 1421 return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\"; 1422 " 1423 ) 1424 1425(define_insn "delay_cycles_start" 1426 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 1427 UNS_DELAY_START)] 1428 "" 1429 "; Begin %J0 cycle delay" 1430 ) 1431 1432(define_insn "delay_cycles_end" 1433 [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 1434 UNS_DELAY_END)] 1435 "" 1436 "; End %J0 cycle delay" 1437 ) 1438 1439(define_insn "delay_cycles_32" 1440 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1441 (match_operand 1 "immediate_operand" "i") 1442 ] UNS_DELAY_32)] 1443 "" 1444 "PUSH r13 1445 PUSH r14 1446 MOV.W %A0, r13 1447 MOV.W %B0, r14 14481: SUB.W #1, r13 1449 SUBC.W #0, r14 1450 JNE 1b 1451 TST.W r13 1452 JNE 1b 1453 POP r14 1454 POP r13" 1455 ) 1456 1457(define_insn "delay_cycles_32x" 1458 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1459 (match_operand 1 "immediate_operand" "i") 1460 ] UNS_DELAY_32X)] 1461 "" 1462 "PUSHM.A #2,r14 1463 MOV.W %A0, r13 1464 MOV.W %B0, r14 14651: SUB.W #1, r13 1466 SUBC.W #0, r14 1467 JNE 1b 1468 TST.W r13 1469 JNE 1b 1470 POPM.A #2,r14" 1471 ) 1472 1473(define_insn "delay_cycles_16" 1474 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1475 (match_operand 1 "immediate_operand" "i") 1476 ] UNS_DELAY_16)] 1477 "" 1478 "PUSH r13 1479 MOV.W %0, r13 14801: SUB.W #1, r13 1481 JNE 1b 1482 POP r13" 1483 ) 1484 1485(define_insn "delay_cycles_16x" 1486 [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1487 (match_operand 1 "immediate_operand" "i") 1488 ] UNS_DELAY_16X)] 1489 "" 1490 "PUSHM.A #1,r13 1491 MOV.W %0, r13 14921: SUB.W #1, r13 1493 JNE 1b 1494 POPM.A #1,r13" 1495 ) 1496 1497(define_insn "delay_cycles_2" 1498 [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)] 1499 "" 1500 "JMP .+2" 1501 ) 1502 1503(define_insn "delay_cycles_1" 1504 [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)] 1505 "" 1506 "NOP" 1507 ) 1508 1509(define_insn "mulhisi3" 1510 [(set (match_operand:SI 0 "register_operand" "=r") 1511 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1512 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1513 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE" 1514 "* 1515 if (msp430_use_f5_series_hwmult ()) 1516 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C2 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\"; 1517 else 1518 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\"; 1519 " 1520) 1521 1522(define_insn "umulhisi3" 1523 [(set (match_operand:SI 0 "register_operand" "=r") 1524 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1525 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1526 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE" 1527 "* 1528 if (msp430_use_f5_series_hwmult ()) 1529 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x04C0 { MOV.W %2, &0x04C8 { MOV.W &0x04CA, %L0 { MOV.W &0x04CC, %H0 { POP.W sr\"; 1530 else 1531 return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\"; 1532 " 1533) 1534 1535(define_insn "mulsidi3" 1536 [(set (match_operand:DI 0 "register_operand" "=r") 1537 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1538 (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1539 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE" 1540 "* 1541 if (msp430_use_f5_series_hwmult ()) 1542 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D4 { MOV.W %H1, &0x04D6 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\"; 1543 else 1544 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\"; 1545 " 1546) 1547 1548(define_insn "umulsidi3" 1549 [(set (match_operand:DI 0 "register_operand" "=r") 1550 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1551 (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1552 "optimize > 2 && msp430_hwmult_type != MSP430_HWMULT_NONE" 1553 "* 1554 if (msp430_use_f5_series_hwmult ()) 1555 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x04D0 { MOV.W %H1, &0x04D2 { MOV.W %L2, &0x04E0 { MOV.W %H2, &0x04E2 { MOV.W &0x04E4, %A0 { MOV.W &0x04E6, %B0 { MOV.W &0x04E8, %C0 { MOV.W &0x04EA, %D0 { POP.W sr\"; 1556 else 1557 return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\"; 1558 " 1559) 1560