1 1.1 mrg ;; Machine Description for TI MSP43* processors 2 1.7 mrg ;; Copyright (C) 2013-2022 Free Software Foundation, Inc. 3 1.1 mrg ;; Contributed by Red Hat. 4 1.1 mrg 5 1.1 mrg ;; This file is part of GCC. 6 1.1 mrg 7 1.1 mrg ;; GCC is free software; you can redistribute it and/or modify 8 1.1 mrg ;; it under the terms of the GNU General Public License as published by 9 1.1 mrg ;; the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg ;; any later version. 11 1.1 mrg 12 1.1 mrg ;; GCC is distributed in the hope that it will be useful, 13 1.1 mrg ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 mrg ;; GNU General Public License for more details. 16 1.1 mrg 17 1.1 mrg ;; You should have received a copy of the GNU General Public License 18 1.1 mrg ;; along with GCC; see the file COPYING3. If not see 19 1.1 mrg ;; <http://www.gnu.org/licenses/>. 20 1.1 mrg 22 1.1 mrg 23 1.1 mrg (define_constants 24 1.1 mrg [ 25 1.1 mrg (PC_REGNO 0) 26 1.1 mrg (SP_REGNO 1) 27 1.1 mrg (CARRY 2) 28 1.1 mrg ]) 29 1.1 mrg 30 1.1 mrg (define_c_enum "unspec" 31 1.1 mrg [ 32 1.1 mrg UNS_PROLOGUE_START_MARKER 33 1.1 mrg UNS_PROLOGUE_END_MARKER 34 1.1 mrg UNS_EPILOGUE_START_MARKER 35 1.1 mrg UNS_EPILOGUE_HELPER 36 1.1 mrg 37 1.1 mrg UNS_PUSHM 38 1.1 mrg UNS_POPM 39 1.1 mrg 40 1.1 mrg UNS_GROW_AND_SWAP 41 1.1 mrg UNS_SWAP_AND_SHRINK 42 1.1 mrg 43 1.1 mrg UNS_DINT 44 1.1 mrg UNS_EINT 45 1.1 mrg UNS_PUSH_INTR 46 1.1 mrg UNS_POP_INTR 47 1.1 mrg UNS_BIC_SR 48 1.1 mrg UNS_BIS_SR 49 1.1 mrg 50 1.1 mrg UNS_REFSYM_NEED_EXIT 51 1.1 mrg 52 1.1 mrg UNS_DELAY_32 53 1.1 mrg UNS_DELAY_32X 54 1.1 mrg UNS_DELAY_16 55 1.1 mrg UNS_DELAY_16X 56 1.1 mrg UNS_DELAY_2 57 1.1 mrg UNS_DELAY_1 58 1.1 mrg UNS_DELAY_START 59 1.1 mrg UNS_DELAY_END 60 1.1 mrg ]) 61 1.7 mrg 62 1.7 mrg ;; Instruction length is calculated by examining the type and number of 63 1.7 mrg ;; operands. 64 1.7 mrg ;; Whether the insn uses the 430X extension word, or is a 430X address 65 1.7 mrg ;; instruction also has an effect. 66 1.7 mrg ;; "Cheap" source operands do not contribute to the overall length of the insn 67 1.7 mrg ;; and are register (Rn), indirect post-increment (@Rn+) and indirect register 68 1.7 mrg ;; (@Rn). 69 1.7 mrg ;; The lengths of instructions in bytes are: 70 1.7 mrg ;; Single-op 430: Cheap op == 2 71 1.7 mrg ;; (also CALLA) Other op == 4 72 1.7 mrg ;; Double-op 430: Source is not cheap == 2 73 1.7 mrg ;; (also MOVA, Dest is register == 2 74 1.7 mrg ;; CMPA, ADDA, Dest is not a register == 4 75 1.7 mrg ;; SUBA) (sum the source and dest cost) 76 1.7 mrg ;; Single-op 430X: For insn names ending in 'X' add 2 to single-op 430 cost. 77 1.7 mrg ;; Double-op 430X: Insn name ends in 'M' == 2 78 1.7 mrg ;; Others have the same cost as double-op 430 but add 2. 79 1.7 mrg ;; 80 1.7 mrg ;; The insn type describes whether it is a single or double operand MSP430 81 1.7 mrg ;; instruction (some single-operand GCC instructions are actually 82 1.7 mrg ;; double-operand on the target). 83 1.7 mrg ;; "triple" and "cmp" types use the costs of a double operand type but 84 1.7 mrg ;; instead assume that the src operand is in op2, and also cmp types assume the 85 1.7 mrg ;; dst operand is in op1. 86 1.7 mrg ;; This attribute also describes which operands are safe to examine 87 1.7 mrg ;; when calculating the length or extension. GCC will segfault trying to 88 1.7 mrg ;; examine a non-existant operand of an insn. 89 1.7 mrg (define_attr "type" "none,single,double,triple,cmp" (const_string "none")) 90 1.7 mrg 91 1.7 mrg ;; The M extension is for instructions like RRAM - they always 92 1.7 mrg ;; only, and the operand must be a register. 93 1.7 mrg (define_attr "extension" "none,x,a,m" 94 1.7 mrg (cond [(eq_attr "type" "none") 95 1.7 mrg (const_string "none") 96 1.7 mrg (match_operand 0 "msp430_high_memory_operand" "") 97 1.7 mrg (const_string "x") 98 1.7 mrg (and (eq_attr "type" "double") 99 1.7 mrg (match_operand 1 "msp430_high_memory_operand" "")) 100 1.7 mrg (const_string "x") 101 1.7 mrg (and (ior (eq_attr "type" "triple") (eq_attr "type" "cmp")) 102 1.7 mrg (ior (match_operand 1 "msp430_high_memory_operand" "") 103 1.7 mrg (match_operand 2 "msp430_high_memory_operand" ""))) 104 1.7 mrg (const_string "x")] 105 1.7 mrg (const_string "none"))) 106 1.7 mrg 107 1.7 mrg ;; Multiply the default length by this constant value. 108 1.7 mrg (define_attr "length_multiplier" "" (const_int 1)) 109 1.7 mrg 110 1.7 mrg ;; Add an additional amount to the total length of the insn. 111 1.7 mrg (define_attr "extra_length" "" (const_int 0)) 112 1.7 mrg 113 1.7 mrg ;; FIXME for some reason if we move the addition of 2 for extension == x to 114 1.7 mrg ;; ADJUST_INSN_LENGTH, codesize gets much worse. 115 1.7 mrg (define_attr "length" "" 116 1.7 mrg (cond [(eq_attr "extension" "m") 117 1.7 mrg (const_int 2) 118 1.7 mrg (eq_attr "type" "single") 119 1.7 mrg (plus (if_then_else (match_operand 0 "msp430_cheap_operand" "") 120 1.7 mrg (const_int 2) 121 1.7 mrg (const_int 4)) 122 1.7 mrg (if_then_else (eq_attr "extension" "x") 123 1.7 mrg (const_int 2) 124 1.7 mrg (const_int 0))) 125 1.7 mrg (eq_attr "type" "double") 126 1.7 mrg (plus (plus (if_then_else (match_operand 0 "register_operand" "") 127 1.7 mrg (const_int 2) 128 1.7 mrg (const_int 4)) 129 1.7 mrg (if_then_else (match_operand 1 "msp430_cheap_operand" "") 130 1.7 mrg (const_int 0) 131 1.7 mrg (const_int 2))) 132 1.7 mrg (if_then_else (eq_attr "extension" "x") 133 1.7 mrg (const_int 2) 134 1.7 mrg (const_int 0))) 135 1.7 mrg (eq_attr "type" "triple") 136 1.7 mrg (plus (plus (if_then_else (match_operand 0 "register_operand" "") 137 1.7 mrg (const_int 2) 138 1.7 mrg (const_int 4)) 139 1.7 mrg (if_then_else (match_operand 2 "msp430_cheap_operand" "") 140 1.7 mrg (const_int 0) 141 1.7 mrg (const_int 2))) 142 1.7 mrg (if_then_else (eq_attr "extension" "x") 143 1.7 mrg (const_int 2) 144 1.7 mrg (const_int 0))) 145 1.7 mrg (eq_attr "type" "cmp") 146 1.7 mrg (plus (plus (if_then_else (match_operand 1 "register_operand" "") 147 1.7 mrg (const_int 2) 148 1.7 mrg (const_int 4)) 149 1.7 mrg (if_then_else (match_operand 2 "msp430_cheap_operand" "") 150 1.7 mrg (const_int 0) 151 1.7 mrg (const_int 2))) 152 1.7 mrg (if_then_else (eq_attr "extension" "x") 153 1.7 mrg (const_int 2) 154 1.7 mrg (const_int 0)))] 155 1.3 mrg (const_int 2))) 156 1.1 mrg 157 1.1 mrg (include "predicates.md") 158 1.1 mrg (include "constraints.md") 159 1.1 mrg 160 1.7 mrg (define_mode_iterator QHI [QI HI PSI]) 161 1.7 mrg (define_mode_iterator HPSI [HI PSI]) 162 1.7 mrg (define_mode_iterator HDI [HI PSI SI DI]) 163 1.7 mrg 164 1.7 mrg ;; Mapping of all shift operators 165 1.7 mrg (define_code_iterator any_shift [ashift ashiftrt lshiftrt]) 166 1.7 mrg 167 1.7 mrg ;; Base name for define_insn 168 1.7 mrg (define_code_attr shift_insn 169 1.1 mrg [(ashift "ashl") (lshiftrt "lshr") (ashiftrt "ashr")]) 170 1.1 mrg 171 1.1 mrg ;; There are two basic "family" tests we do here: 172 1.1 mrg ;; 173 1.1 mrg ;; msp430x - true if 430X instructions are available. 174 1.1 mrg ;; TARGET_LARGE - true if pointers are 20-bits 175 1.1 mrg ;; 176 1.1 mrg ;; Note that there are three supported cases, since the base 430 177 1.1 mrg ;; doesn't have 20-bit pointers: 178 1.1 mrg ;; 179 1.1 mrg ;; 1. MSP430 cpu, small model 180 1.1 mrg ;; 2. MSP430X cpu, small model. 181 1.1 mrg ;; 3. MSP430X cpu, large model. 182 1.1 mrg 183 1.1 mrg ;;------------------------------------------------------------ 184 1.1 mrg ;; Moves 185 1.1 mrg 186 1.1 mrg ;; Push/Pop must be before the generic move patterns 187 1.1 mrg 188 1.1 mrg (define_insn "push" 189 1.1 mrg [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO))) 190 1.1 mrg (match_operand:HI 0 "register_operand" "r"))] 191 1.1 mrg "" 192 1.7 mrg "PUSH\t%0" 193 1.7 mrg [(set_attr "type" "single")] 194 1.1 mrg ) 195 1.1 mrg 196 1.1 mrg (define_insn "pusha" 197 1.1 mrg [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO))) 198 1.1 mrg (match_operand:PSI 0 "register_operand" "r"))] 199 1.1 mrg "TARGET_LARGE" 200 1.7 mrg "PUSHX.A\t%0" 201 1.7 mrg [(set_attr "type" "single") 202 1.7 mrg (set_attr "extension" "x")] 203 1.1 mrg ) 204 1.1 mrg 205 1.1 mrg (define_insn "pushm" 206 1.1 mrg [(unspec_volatile [(match_operand 0 "register_operand" "r") 207 1.1 mrg (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)] 208 1.1 mrg "" 209 1.7 mrg "PUSHM%b0\t%1, %0" 210 1.7 mrg [(set_attr "type" "single") 211 1.7 mrg (set_attr "extension" "m")] 212 1.1 mrg ) 213 1.1 mrg 214 1.1 mrg (define_insn "pop" 215 1.1 mrg [(set (match_operand:HI 0 "register_operand" "=r") 216 1.1 mrg (mem:HI (post_inc:HI (reg:HI SP_REGNO))))] 217 1.1 mrg "" 218 1.7 mrg "POP\t%0" 219 1.7 mrg [(set_attr "type" "single")] 220 1.1 mrg ) 221 1.1 mrg 222 1.1 mrg (define_insn "popa" 223 1.1 mrg [(set (match_operand:PSI 0 "register_operand" "=r") 224 1.1 mrg (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))] 225 1.1 mrg "TARGET_LARGE" 226 1.7 mrg "POPX.A\t%0" 227 1.7 mrg [(set_attr "type" "single") 228 1.7 mrg (set_attr "extension" "x")] 229 1.1 mrg ) 230 1.1 mrg 231 1.1 mrg ;; This is nasty. Operand0 is bogus. It is only there so that we can get a 232 1.1 mrg ;; mode for the %b0 to work. We should use operand1 for this, but that does 233 1.1 mrg ;; not have a mode. 234 1.1 mrg ;; 235 1.1 mrg ;; Operand1 is actually a register, but we cannot accept (REG...) because the 236 1.1 mrg ;; cprop_hardreg pass can and will renumber registers even inside 237 1.1 mrg ;; unspec_volatiles. So we take an integer register number parameter and 238 1.1 mrg ;; fudge it to be a register name when we generate the assembler. 239 1.1 mrg ;; 240 1.1 mrg ;; The pushm pattern does not have this problem because of all of the 241 1.1 mrg ;; frame info cruft attached to it, so cprop_hardreg leaves it alone. 242 1.1 mrg (define_insn "popm" 243 1.1 mrg [(unspec_volatile [(match_operand 0 "register_operand" "r") 244 1.1 mrg (match_operand 1 "immediate_operand" "i") 245 1.1 mrg (match_operand 2 "immediate_operand" "i")] UNS_POPM)] 246 1.1 mrg "" 247 1.7 mrg "POPM%b0\t%2, r%J1" 248 1.7 mrg [(set_attr "type" "single") 249 1.7 mrg (set_attr "extension" "m")] 250 1.1 mrg ) 251 1.1 mrg 252 1.1 mrg ;; The next two patterns are here to support a "feature" of how GCC implements 253 1.1 mrg ;; varargs. When a function uses varargs and the *second* to last named 254 1.1 mrg ;; argument is split between argument registers and the stack, gcc expects the 255 1.1 mrg ;; callee to allocate space on the stack that can contain the register-based 256 1.1 mrg ;; part of the argument. This space *has* to be just before the remaining 257 1.1 mrg ;; arguments (ie the ones that are fully on the stack). 258 1.1 mrg ;; 259 1.1 mrg ;; The problem is that the MSP430 CALL instruction pushes the return address 260 1.1 mrg ;; onto the stack in the exact place where the callee wants to allocate 261 1.1 mrg ;; this extra space. So we need a sequence of instructions that can allocate 262 1.1 mrg ;; the extra space and then move the return address down the stack, so that 263 1.1 mrg ;; the extra space is now adjacent to the remaining arguments. 264 1.1 mrg ;; 265 1.1 mrg ;; This could be constructed through regular insns, but they might be split up 266 1.1 mrg ;; by a misguided optimization, so an unspec volatile is used instead. 267 1.1 mrg 268 1.1 mrg (define_insn "grow_and_swap" 269 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_GROW_AND_SWAP)] 270 1.1 mrg "" 271 1.1 mrg "* 272 1.1 mrg if (TARGET_LARGE) 273 1.1 mrg return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\"; 274 1.1 mrg return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\"; 275 1.7 mrg " 276 1.7 mrg [(set (attr "length") 277 1.7 mrg (if_then_else (match_test "TARGET_LARGE") 278 1.7 mrg (const_int 8) 279 1.1 mrg (const_int 6)))] 280 1.1 mrg ) 281 1.1 mrg 282 1.1 mrg (define_insn "swap_and_shrink" 283 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_SWAP_AND_SHRINK)] 284 1.1 mrg "" 285 1.1 mrg "* return TARGET_LARGE 286 1.1 mrg ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\" 287 1.7 mrg : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\"; 288 1.7 mrg " 289 1.7 mrg [(set (attr "length") 290 1.7 mrg (if_then_else (match_test "TARGET_LARGE") 291 1.7 mrg (const_int 10) 292 1.7 mrg (const_int 8)))] 293 1.1 mrg ) 294 1.1 mrg 295 1.1 mrg ; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a 296 1.1 mrg ; zero_extend anyway. Catch it here. 297 1.1 mrg (define_insn "movqihi" 298 1.1 mrg [(set (match_operand:HI 0 "register_operand" "=r,r") 299 1.1 mrg (zero_extend:HI (match_operand:QI 1 "memory_operand" "Ys,m")))] 300 1.1 mrg "" 301 1.1 mrg "@ 302 1.1 mrg MOV.B\t%1, %0 303 1.7 mrg MOV%X1.B\t%1, %0" 304 1.1 mrg [(set_attr "type" "double")] 305 1.1 mrg ) 306 1.1 mrg 307 1.6 mrg (define_insn "movqi_topbyte" 308 1.6 mrg [(set (match_operand:QI 0 "msp430_general_dst_operand" "=r") 309 1.1 mrg (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))] 310 1.1 mrg "msp430x" 311 1.7 mrg "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0" 312 1.7 mrg [(set_attr "length" "6") 313 1.1 mrg (set_attr "type" "double")] 314 1.1 mrg ) 315 1.1 mrg 316 1.6 mrg (define_insn "movqi" 317 1.6 mrg [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm") 318 1.1 mrg (match_operand:QI 1 "msp430_general_operand" "riYsYx,rmi"))] 319 1.1 mrg "" 320 1.1 mrg "@ 321 1.6 mrg MOV.B\t%1, %0 322 1.7 mrg MOVX.B\t%1, %0" 323 1.1 mrg [(set_attr "type" "double")] 324 1.1 mrg ) 325 1.1 mrg 326 1.6 mrg (define_insn "movhi" 327 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=r,rYsYx,rm") 328 1.1 mrg (match_operand:HI 1 "msp430_general_operand" "N,riYsYx,rmi"))] 329 1.1 mrg "" 330 1.3 mrg "@ 331 1.1 mrg MOV.B\t%1, %0 332 1.6 mrg MOV.W\t%1, %0 333 1.7 mrg MOVX.W\t%1, %0" 334 1.1 mrg [(set_attr "type" "double")] 335 1.1 mrg ) 336 1.1 mrg 337 1.6 mrg (define_expand "movsi" 338 1.1 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand") 339 1.1 mrg (match_operand:SI 1 "general_operand"))] 340 1.1 mrg "" 341 1.7 mrg "" 342 1.3 mrg ) 343 1.3 mrg 344 1.6 mrg (define_insn_and_split "movsi_s" 345 1.3 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") 346 1.3 mrg (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] 347 1.3 mrg "" 348 1.3 mrg "" 349 1.6 mrg "reload_completed" 350 1.3 mrg [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand") 351 1.6 mrg (match_operand:HI 4 "general_operand")) 352 1.3 mrg (set (match_operand:HI 3 "msp430_general_dst_nonv_operand") 353 1.3 mrg (match_operand:HI 5 "general_operand"))] 354 1.7 mrg "msp430_split_movsi (operands);" 355 1.7 mrg [(set_attr "type" "double")] 356 1.3 mrg ) 357 1.1 mrg 358 1.6 mrg (define_insn_and_split "movsi_x" 359 1.1 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") 360 1.1 mrg (match_operand:SI 1 "general_operand" "rmi"))] 361 1.1 mrg "" 362 1.1 mrg "#" 363 1.6 mrg "reload_completed" 364 1.1 mrg [(set (match_operand:HI 2 "msp430_general_dst_nonv_operand") 365 1.6 mrg (match_operand:HI 4 "general_operand")) 366 1.1 mrg (set (match_operand:HI 3 "msp430_general_dst_nonv_operand") 367 1.1 mrg (match_operand:HI 5 "general_operand"))] 368 1.7 mrg "msp430_split_movsi (operands);" 369 1.1 mrg [(set_attr "type" "double")] 370 1.1 mrg ) 371 1.6 mrg 372 1.1 mrg ;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them. 373 1.6 mrg (define_insn "movpsi" 374 1.6 mrg [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,r,Ya,rm") 375 1.1 mrg (match_operand:PSI 1 "msp430_general_operand" "N,O,riYa,r,rmi"))] 376 1.1 mrg "" 377 1.3 mrg "@ 378 1.3 mrg MOV.B\t%1, %0 379 1.1 mrg MOV.W\t%1, %0 380 1.1 mrg MOVA\t%1, %0 381 1.7 mrg MOVA\t%1, %0 382 1.7 mrg MOVX.A\t%1, %0" 383 1.7 mrg [(set_attr "extension" "none,none,a,a,x") 384 1.7 mrg (set_attr "type" "double")] 385 1.1 mrg ) 386 1.1 mrg 387 1.1 mrg ; This pattern is identical to the truncsipsi2 pattern except 388 1.1 mrg ; that it uses a SUBREG instead of a TRUNC. It is needed in 389 1.1 mrg ; order to prevent reload from converting (set:SI (SUBREG:PSI (SI))) 390 1.1 mrg ; into (SET:PSI (PSI)). 391 1.1 mrg ; 392 1.1 mrg ; Note: using POPM.A #1 is two bytes smaller than using POPX.A.... 393 1.1 mrg 394 1.1 mrg (define_insn "movsipsi2" 395 1.1 mrg [(set (match_operand:PSI 0 "register_operand" "=r") 396 1.1 mrg (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))] 397 1.1 mrg "msp430x" 398 1.7 mrg "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0" 399 1.7 mrg [(set_attr "length" "6") 400 1.1 mrg (set_attr "type" "double")] 401 1.1 mrg ) 402 1.3 mrg 403 1.3 mrg ;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c. 404 1.3 mrg (define_insn "*movpsihi2_lo" 405 1.3 mrg [(set (match_operand:HI 0 "register_operand" "=r") 406 1.3 mrg (subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] 407 1.3 mrg "msp430x" 408 1.7 mrg "MOVA\t%1, %0" 409 1.7 mrg [(set_attr "extension" "a") 410 1.3 mrg (set_attr "type" "double")] 411 1.3 mrg ) 412 1.1 mrg 413 1.1 mrg ;;------------------------------------------------------------ 414 1.1 mrg ;; Math 415 1.1 mrg 416 1.6 mrg (define_insn "addpsi3" 417 1.6 mrg [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,rm") 418 1.6 mrg (plus:PSI (match_operand:PSI 1 "msp430_general_operand" "%0,0") 419 1.1 mrg (match_operand:PSI 2 "msp430_general_operand" "rLs,rmi")))] 420 1.1 mrg "" 421 1.1 mrg "@ 422 1.1 mrg ADDA\t%2, %0 423 1.7 mrg ADDX.A\t%2, %0" 424 1.7 mrg [(set_attr "extension" "a,x") 425 1.1 mrg (set_attr "type" "triple")] 426 1.1 mrg ) 427 1.1 mrg 428 1.6 mrg (define_insn "addqi3" 429 1.6 mrg [(set (match_operand:QI 0 "msp430_general_dst_operand" "=rYsYx,rm") 430 1.6 mrg (plus:QI (match_operand:QI 1 "msp430_general_operand" "%0,0") 431 1.1 mrg (match_operand:QI 2 "msp430_general_operand" "riYsYx,rmi")))] 432 1.1 mrg "" 433 1.1 mrg "@ 434 1.6 mrg ADD.B\t%2, %0 435 1.7 mrg ADDX.B\t%2, %0" 436 1.1 mrg [(set_attr "type" "triple")] 437 1.1 mrg ) 438 1.1 mrg 439 1.6 mrg (define_insn "addhi3" 440 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm") 441 1.6 mrg (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0") 442 1.1 mrg (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")))] 443 1.1 mrg "" 444 1.1 mrg "@ 445 1.6 mrg ADD.W\t%2, %0 446 1.7 mrg ADDX.W\t%2, %0" 447 1.1 mrg [(set_attr "type" "triple")] 448 1.1 mrg ) 449 1.1 mrg 450 1.1 mrg ; This pattern is needed in order to avoid reload problems. 451 1.1 mrg ; It takes an SI pair of registers, adds a value to them, and 452 1.1 mrg ; then converts them into a single PSI register. 453 1.1 mrg 454 1.1 mrg (define_insn "addsipsi3" 455 1.1 mrg [(set (subreg:SI (match_operand:PSI 0 "register_operand" "=&r") 0) 456 1.1 mrg (plus:SI (match_operand:SI 1 "register_operand" "0") 457 1.1 mrg (match_operand 2 "general_operand" "rmi")))] 458 1.6 mrg "" 459 1.7 mrg "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0" 460 1.7 mrg [(set (attr "length") 461 1.7 mrg (if_then_else (match_operand 2 "register_operand" "") 462 1.7 mrg (const_int 10) 463 1.7 mrg (if_then_else (match_operand 2 "msp430_high_memory_operand" "") 464 1.7 mrg (const_int 18) 465 1.7 mrg (const_int 14)))) 466 1.1 mrg (set_attr "type" "triple")] 467 1.1 mrg ) 468 1.1 mrg 469 1.6 mrg (define_insn "addsi3" 470 1.6 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,rm") 471 1.6 mrg (plus:SI (match_operand:SI 1 "general_operand" "%0,0") 472 1.1 mrg (match_operand:SI 2 "general_operand" "rYsYxi,mi")))] 473 1.1 mrg "" 474 1.1 mrg "@ 475 1.6 mrg ADD\t%L2, %L0 { ADDC\t%H2, %H0 476 1.7 mrg ADDX\t%L2, %L0 { ADDCX\t%H2, %H0" 477 1.7 mrg [(set_attr "length_multiplier" "2") 478 1.1 mrg (set_attr "type" "triple")] 479 1.1 mrg ) 480 1.1 mrg 481 1.1 mrg ; Version of addhi that exposes the carry operations, for SImode adds. 482 1.1 mrg ; 483 1.1 mrg ; NOTE - we are playing a dangerous game with GCC here. We have these two 484 1.1 mrg ; add patterns and the splitter that follows because our tests have shown 485 1.1 mrg ; that this results in a significant reduction in code size - because GCC is 486 1.1 mrg ; able to discard any unused part of the addition. We have to annotate the 487 1.1 mrg ; patterns with the set and use of the carry flag because otherwise GCC will 488 1.1 mrg ; discard parts of the addition when they are actually needed. But we have 489 1.1 mrg ; not annotated all the other patterns that set the CARRY flag as doing so 490 1.1 mrg ; results in an overall increase in code size[1]. Instead we just *hope* 491 1.1 mrg ; that GCC will not move a carry-setting instruction in between the first 492 1.1 mrg ; and second adds. 493 1.1 mrg ; 494 1.1 mrg ; So far our experiments have shown that GCC is likely to move MOV and CMP 495 1.1 mrg ; instructions in between the two adds, but not other instructions. MOV is 496 1.1 mrg ; safe, CMP is not. So we have annotated the CMP patterns and left the 497 1.1 mrg ; subtract, shift and other add patterns alone. At the moment this is 498 1.1 mrg ; working, but with future changes to the generic parts of GCC that might 499 1.1 mrg ; change. 500 1.1 mrg ; 501 1.1 mrg ; [1] It is not clear exactly why the code size increases. The cause appears 502 1.1 mrg ; to be that reload is more prevelent to spilling a variable onto the stack 503 1.1 mrg ; but why it does this is unknown. Possibly the additional CLOBBERs necessary 504 1.1 mrg ; to correctly annotate the other patterns makes reload think that there is 505 1.1 mrg ; increased register pressure. Or possibly reload does not handle ADD patterns 506 1.1 mrg ; that are not single_set() very well. 507 1.6 mrg 508 1.6 mrg ; match_operand 3 is likely to be the same as op2 most of the time - except 509 1.6 mrg ; when op2 is a post_inc and we have stripped the post_inc from match_operand 3 510 1.1 mrg 511 1.6 mrg (define_insn "addhi3_cy" 512 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm") 513 1.6 mrg (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0") 514 1.1 mrg (match_operand:HI 2 "msp430_nonimmediate_operand" "rYsYxi,rm"))) 515 1.1 mrg (set (reg:BI CARRY) 516 1.6 mrg (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) 517 1.1 mrg (zero_extend:SI (match_operand:HI 3 "msp430_nonimmediate_operand" "rYsYxi,rm"))) 518 1.1 mrg (const_int 16)))) 519 1.1 mrg ] 520 1.1 mrg "" 521 1.1 mrg "@ 522 1.6 mrg ADD\t%2, %1 ; cy 523 1.7 mrg ADDX\t%2, %1 ; cy" 524 1.7 mrg [(set_attr "type" "triple")] 525 1.1 mrg ) 526 1.1 mrg 527 1.6 mrg (define_insn "addhi3_cy_i" 528 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm") 529 1.1 mrg (plus:HI (match_operand:HI 1 "general_operand" "%0,0") 530 1.1 mrg (match_operand:HI 2 "immediate_operand" "i,i"))) 531 1.1 mrg (set (reg:BI CARRY) 532 1.1 mrg (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1)) 533 1.1 mrg (match_operand 3 "immediate_operand" "i,i")) 534 1.1 mrg (const_int 16)))) 535 1.1 mrg ] 536 1.1 mrg "" 537 1.1 mrg "@ 538 1.1 mrg ADD\t%2, %1 ; cy 539 1.7 mrg ADD%X0\t%2, %1 ; cy" 540 1.7 mrg [(set_attr "type" "triple")] 541 1.1 mrg ) 542 1.1 mrg 543 1.1 mrg ; Version of addhi that adds the carry, for SImode adds. 544 1.6 mrg (define_insn "addchi4_cy" 545 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYsYx,rm") 546 1.6 mrg (plus:HI (plus:HI (match_operand:HI 1 "msp430_general_operand" "%0,0") 547 1.1 mrg (match_operand:HI 2 "msp430_general_operand" "riYsYx,rmi")) 548 1.1 mrg (zero_extend:HI (reg:BI CARRY)))) 549 1.1 mrg ] 550 1.1 mrg "" 551 1.1 mrg "@ 552 1.6 mrg ADDC\t%2, %1 553 1.7 mrg ADDCX\t%2, %1" 554 1.7 mrg [(set_attr "type" "triple")] 555 1.1 mrg ) 556 1.1 mrg 557 1.1 mrg ; Split an SImode add into two HImode adds, keeping track of the carry 558 1.1 mrg ; so that gcc knows when it can and can't optimize away the two 559 1.6 mrg ; halves. 560 1.6 mrg ; We use the ugly predicate "msp430_nonsubregnonpostinc_or_imm_operand" to 561 1.1 mrg ; enforce the position of a post_inc into op2 if present 562 1.6 mrg (define_split 563 1.6 mrg [(set (match_operand:SI 0 "msp430_nonsubreg_dst_operand") 564 1.1 mrg (plus:SI (match_operand:SI 1 "msp430_nonsubregnonpostinc_or_imm_operand") 565 1.1 mrg (match_operand:SI 2 "msp430_nonsubreg_or_imm_operand"))) 566 1.1 mrg ] 567 1.6 mrg "" 568 1.1 mrg [(parallel [(set (match_operand:HI 3 "msp430_general_dst_nonv_operand" "=&rm") 569 1.1 mrg (plus:HI (match_dup 4) 570 1.1 mrg (match_dup 5))) 571 1.1 mrg (set (reg:BI CARRY) 572 1.1 mrg (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 4)) 573 1.1 mrg (match_dup 9)) 574 1.1 mrg (const_int 16)))) 575 1.6 mrg ]) 576 1.1 mrg (set (match_operand:HI 6 "msp430_general_dst_nonv_operand" "=&rm") 577 1.1 mrg (plus:HI (plus:HI (match_dup 7) 578 1.1 mrg (match_dup 8)) 579 1.1 mrg (zero_extend:HI (reg:BI CARRY)))) 580 1.1 mrg ] 581 1.6 mrg " 582 1.6 mrg if (msp430_split_addsi (operands)) 583 1.6 mrg FAIL; 584 1.7 mrg " 585 1.1 mrg ) 586 1.1 mrg 587 1.1 mrg 588 1.1 mrg ;; Alternatives 2 and 3 are to handle cases generated by reload. 589 1.6 mrg (define_insn "subpsi3" 590 1.6 mrg [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r, rm, &?r, ?&r") 591 1.6 mrg (minus:PSI (match_operand:PSI 1 "general_operand" "0, 0, !r, !i") 592 1.1 mrg (match_operand:PSI 2 "general_operand" "rLs, rmi, rmi, r")))] 593 1.1 mrg "" 594 1.1 mrg "@ 595 1.1 mrg SUBA\t%2, %0 596 1.1 mrg SUBX.A\t%2, %0 597 1.1 mrg MOVX.A\t%1, %0 { SUBX.A\t%2, %0 598 1.7 mrg MOVX.A\t%1, %0 { SUBA\t%2, %0" 599 1.7 mrg [(set_attr "type" "triple") 600 1.7 mrg (set_attr "extension" "a,x,x,x") 601 1.1 mrg (set_attr "length_multiplier" "1,1,2,2")] 602 1.1 mrg ) 603 1.1 mrg 604 1.1 mrg ;; Alternatives 2 and 3 are to handle cases generated by reload. 605 1.6 mrg (define_insn "subqi3" 606 1.1 mrg [(set (match_operand:QI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r") 607 1.6 mrg (minus:QI (match_operand:QI 1 "general_operand" "0, 0, !r, !i") 608 1.1 mrg (match_operand:QI 2 "general_operand" " riYsYx, rmi, rmi, r")))] 609 1.1 mrg "" 610 1.1 mrg "@ 611 1.6 mrg SUB.B\t%2, %0 612 1.6 mrg SUBX.B\t%2, %0 613 1.1 mrg MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0 614 1.7 mrg MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0" 615 1.7 mrg [(set_attr "length_multiplier" "1,1,2,2") 616 1.1 mrg (set_attr "type" "triple")] 617 1.1 mrg ) 618 1.1 mrg 619 1.1 mrg ;; Alternatives 2 and 3 are to handle cases generated by reload. 620 1.6 mrg (define_insn "subhi3" 621 1.1 mrg [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rYsYx, rm, &?r, ?&r") 622 1.6 mrg (minus:HI (match_operand:HI 1 "general_operand" "0, 0, !r, !i") 623 1.1 mrg (match_operand:HI 2 "general_operand" " riYsYx, rmi, rmi, r")))] 624 1.1 mrg "" 625 1.1 mrg "@ 626 1.6 mrg SUB.W\t%2, %0 627 1.6 mrg SUBX.W\t%2, %0 628 1.1 mrg MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0 629 1.7 mrg MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0" 630 1.7 mrg [(set_attr "length_multiplier" "1,1,2,2") 631 1.1 mrg (set_attr "type" "triple")] 632 1.1 mrg ) 633 1.1 mrg 634 1.6 mrg (define_insn "subsi3" 635 1.6 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=&rYsYx,m") 636 1.6 mrg (minus:SI (match_operand:SI 1 "general_operand" "0,0") 637 1.1 mrg (match_operand:SI 2 "general_operand" "riYsYx,mi")))] 638 1.6 mrg "" 639 1.6 mrg "@ 640 1.6 mrg SUB\t%L2, %L0 { SUBC\t%H2, %H0 641 1.7 mrg SUBX\t%L2, %L0 { SUBCX\t%H2, %H0" 642 1.7 mrg [(set_attr "length_multiplier" "2") 643 1.1 mrg (set_attr "type" "triple")] 644 1.1 mrg ) 645 1.1 mrg 646 1.6 mrg (define_insn "*bic<mode>_cg" 647 1.6 mrg [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m") 648 1.1 mrg (and:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0") 649 1.1 mrg (match_operand 2 "msp430_inv_constgen_operator" "n,n")))] 650 1.1 mrg "" 651 1.1 mrg "@ 652 1.1 mrg BIC%x0%b0\t#%I2, %0 653 1.7 mrg BIC%X0%b0\t#%I2, %0" 654 1.7 mrg [(set_attr "length" "2") ; Smaller length achieved by using constant generator 655 1.1 mrg (set_attr "type" "double")] 656 1.1 mrg ) 657 1.1 mrg 658 1.6 mrg (define_insn "bic<mode>3" 659 1.6 mrg [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm") 660 1.6 mrg (and:QHI (not:QHI (match_operand:QHI 1 "msp430_general_operand" "rYsYx,rmn")) 661 1.1 mrg (match_operand:QHI 2 "msp430_general_operand" "0,0")))] 662 1.1 mrg "" 663 1.1 mrg "@ 664 1.6 mrg BIC%x0%b0\t%1, %0 665 1.7 mrg BICX%b0\t%1, %0" 666 1.1 mrg [(set_attr "type" "double")] 667 1.1 mrg ) 668 1.1 mrg 669 1.6 mrg (define_insn "and<mode>3" 670 1.6 mrg [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=r,rYsYx,rm") 671 1.6 mrg (and:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0,0") 672 1.1 mrg (match_operand:QHI 2 "msp430_general_operand" "N,riYsYx,rmi")))] 673 1.1 mrg "" 674 1.3 mrg "@ 675 1.1 mrg AND%x0.B\t%2, %0 676 1.6 mrg AND%x0%b0\t%2, %0 677 1.7 mrg ANDX%b0\t%2, %0" 678 1.1 mrg [(set_attr "type" "triple")] 679 1.1 mrg ) 680 1.1 mrg 681 1.6 mrg (define_insn "ior<mode>3" 682 1.6 mrg [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm") 683 1.6 mrg (ior:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0") 684 1.1 mrg (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))] 685 1.1 mrg "" 686 1.1 mrg "@ 687 1.6 mrg BIS%x0%b0\t%2, %0 688 1.7 mrg BISX%b0\t%2, %0" 689 1.1 mrg [(set_attr "type" "triple")] 690 1.1 mrg ) 691 1.1 mrg 692 1.6 mrg (define_insn "xor<mode>3" 693 1.6 mrg [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYsYx,rm") 694 1.6 mrg (xor:QHI (match_operand:QHI 1 "msp430_general_operand" "%0,0") 695 1.1 mrg (match_operand:QHI 2 "msp430_general_operand" "riYsYx,rmi")))] 696 1.1 mrg "" 697 1.1 mrg "@ 698 1.6 mrg XOR%x0%b0\t%2, %0 699 1.7 mrg XORX%b0\t%2, %0" 700 1.1 mrg [(set_attr "type" "triple")] 701 1.1 mrg ) 702 1.1 mrg 703 1.1 mrg ;; Macro : XOR #~0, %0 704 1.6 mrg (define_insn "one_cmpl<mode>2" 705 1.6 mrg [(set (match_operand:QHI 0 "msp430_general_dst_operand" "=rYs,m") 706 1.1 mrg (not:QHI (match_operand:QHI 1 "msp430_general_operand" "0,0")))] 707 1.1 mrg "" 708 1.1 mrg "@ 709 1.1 mrg INV%x0%b0\t%0 710 1.7 mrg INV%X0%b0\t%0" 711 1.1 mrg [(set_attr "type" "double")] 712 1.1 mrg ) 713 1.1 mrg 714 1.6 mrg (define_insn "extendqihi2" 715 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,m") 716 1.1 mrg (sign_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,0")))] 717 1.1 mrg "" 718 1.1 mrg "@ 719 1.1 mrg SXT%X0\t%0 720 1.7 mrg SXT%X0\t%0" 721 1.7 mrg [(set_attr "type" "single")] 722 1.7 mrg ) 723 1.7 mrg 724 1.7 mrg (define_insn "extendqipsi2" 725 1.7 mrg [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,m") 726 1.7 mrg (sign_extend:PSI (match_operand:QI 1 "msp430_general_operand" "0,0")))] 727 1.7 mrg "" 728 1.7 mrg "@ 729 1.7 mrg SXT\t%0 730 1.7 mrg SXTX.A\t%0" 731 1.7 mrg [(set_attr "type" "single") 732 1.1 mrg (set_attr "extension" "none,x")] 733 1.1 mrg ) 734 1.6 mrg 735 1.6 mrg ;; ------------------------ 736 1.6 mrg ;; ZERO EXTEND INSTRUCTIONS 737 1.6 mrg ;; Byte-writes to registers clear bits 19:8 738 1.6 mrg ;; * Byte-writes to memory do not affect bits 15:8 739 1.6 mrg ;; Word-writes to registers clear bits 19:16 740 1.6 mrg ;; PSImode writes to memory clear bits 15:4 of the second memory word 741 1.6 mrg ;; We define all possible insns since that results in better code than if 742 1.6 mrg ;; they are inferred. 743 1.6 mrg ;; ------------------------ 744 1.1 mrg 745 1.6 mrg (define_insn "zero_extendqihi2" 746 1.6 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rYs,r,r,m") 747 1.1 mrg (zero_extend:HI (match_operand:QI 1 "msp430_general_operand" "0,rYs,m,0")))] 748 1.1 mrg "" 749 1.1 mrg "@ 750 1.3 mrg AND\t#0xff, %0 751 1.6 mrg MOV.B\t%1, %0 752 1.1 mrg MOV%X1.B\t%1, %0 753 1.7 mrg AND%X0\t#0xff, %0" 754 1.1 mrg [(set_attr "type" "double")] 755 1.1 mrg ) 756 1.6 mrg 757 1.6 mrg (define_insn "zero_extendqipsi2" 758 1.6 mrg [(set (match_operand:PSI 0 "register_operand" "=r,r") 759 1.6 mrg (zero_extend:PSI (match_operand:QI 1 "general_operand" "rYs,m")))] 760 1.6 mrg "msp430x" 761 1.6 mrg "@ 762 1.6 mrg MOV.B\t%1, %0 763 1.7 mrg MOV%X1.B\t%1, %0" 764 1.6 mrg [(set_attr "type" "double")] 765 1.6 mrg ) 766 1.6 mrg 767 1.6 mrg (define_insn "zero_extendqisi2" 768 1.6 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r,r") 769 1.6 mrg (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,rm")))] 770 1.6 mrg "" 771 1.6 mrg "@ 772 1.6 mrg CLR\t%H0 773 1.7 mrg MOV%X1.B\t%1,%L0 { CLR\t%H0" 774 1.7 mrg [(set_attr "extra_length" "2") 775 1.7 mrg (set_attr "length_multiplier" "1,2") 776 1.6 mrg (set_attr "type" "double")] 777 1.6 mrg ) 778 1.6 mrg 779 1.6 mrg (define_insn "zero_extendhipsi2" 780 1.6 mrg [(set (match_operand:PSI 0 "msp430_general_dst_operand" "=r,r,m") 781 1.6 mrg (zero_extend:PSI (match_operand:HI 1 "msp430_general_operand" "rYs,m,r")))] 782 1.6 mrg "msp430x" 783 1.6 mrg "@ 784 1.6 mrg MOV.W\t%1, %0 785 1.6 mrg MOV%X1\t%1, %0 786 1.7 mrg MOVX.A\t%1, %0" 787 1.6 mrg [(set_attr "type" "double")] 788 1.6 mrg ) 789 1.6 mrg 790 1.6 mrg (define_insn "zero_extendhisi2" 791 1.6 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm,r") 792 1.6 mrg (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")))] 793 1.6 mrg "" 794 1.6 mrg "@ 795 1.6 mrg MOV%X0.W\t#0,%H0 796 1.7 mrg MOV.W\t%1,%L0 { MOV.W\t#0,%H0" 797 1.7 mrg [(set_attr "length_multiplier" "1,2") 798 1.6 mrg (set_attr "type" "double")] 799 1.6 mrg ) 800 1.6 mrg 801 1.6 mrg (define_insn "zero_extendhisipsi2" 802 1.6 mrg [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r,r") 803 1.6 mrg (subreg:PSI (zero_extend:SI (match_operand:HI 1 "general_operand" "0,r")) 0))] 804 1.6 mrg "msp430x" 805 1.6 mrg "@ 806 1.6 mrg AND.W\t#-1,%0 807 1.7 mrg MOV.W\t%1,%0" 808 1.7 mrg [(set_attr "length" "4,2") 809 1.6 mrg (set_attr "type" "double")] 810 1.6 mrg ) 811 1.6 mrg 812 1.6 mrg ; Nasty - we are sign-extending a 20-bit PSI value in one register into 813 1.6 mrg ; two adjacent 16-bit registers to make an SI value. There is no MSP430X 814 1.6 mrg ; instruction that will do this, so we push the 20-bit value onto the stack 815 1.6 mrg ; and then pop it off as two 16-bit values. 816 1.6 mrg ; 817 1.6 mrg ; FIXME: The MSP430X documentation does not specify if zero-extension or 818 1.6 mrg ; sign-extension happens when the 20-bit value is pushed onto the stack. 819 1.6 mrg ; It is probably zero-extension, but if not this pattern will not work 820 1.6 mrg ; when the PSI value is negative.. 821 1.6 mrg ; 822 1.6 mrg ; Note: using PUSHM.A #1 is two bytes smaller than using PUSHX.A.... 823 1.6 mrg ; 824 1.6 mrg ; Note: We use a + constraint on operand 0 as otherwise GCC gets confused 825 1.6 mrg ; about extending a single PSI mode register into a pair of SImode registers 826 1.6 mrg ; with the same starting register. It thinks that the upper register of 827 1.6 mrg ; the pair is unused and so it can clobber it. Try compiling 20050826-2.c 828 1.6 mrg ; at -O2 to see this. 829 1.6 mrg 830 1.6 mrg ; FIXME we can use MOVA for r->m if m is &abs20 or z16(rdst) 831 1.6 mrg (define_insn "zero_extendpsisi2" 832 1.6 mrg [(set (match_operand:SI 0 "register_operand" "+r,m") 833 1.6 mrg (zero_extend:SI (match_operand:PSI 1 "register_operand" "r,r")))] 834 1.6 mrg "" 835 1.6 mrg "@ 836 1.6 mrg * if (REGNO (operands[1]) == SP_REGNO) \ 837 1.6 mrg /* If the source register is the stack pointer, the value \ 838 1.6 mrg stored in the stack slot will be the value *after* the \ 839 1.6 mrg stack pointer has been decremented. So allow for that \ 840 1.6 mrg here. */ \ 841 1.6 mrg 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\"; \ 842 1.6 mrg else \ 843 1.6 mrg return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\"; 844 1.7 mrg MOVX.A %1, %0" 845 1.7 mrg [(set (attr "length") 846 1.7 mrg (cond [(match_test "REGNO (operands[1]) == SP_REGNO") 847 1.7 mrg (const_int 18) 848 1.7 mrg (eq_attr "alternative" "1") 849 1.7 mrg (const_int 6)] 850 1.7 mrg (const_int 10))) 851 1.6 mrg (set_attr "type" "double")] 852 1.6 mrg ) 853 1.6 mrg 854 1.6 mrg ;; Below are unnamed insn patterns to catch pointer manipulation insns 855 1.6 mrg ;; generated by combine. 856 1.6 mrg ;; We get large code size bloat when a PSImode pointer is stored in 857 1.6 mrg ;; memory, so we try to avoid that where possible and keep point manipulation 858 1.6 mrg ;; between registers. 859 1.6 mrg ; FIXME many of these should be unnnecessary once combine deals with 860 1.6 mrg ; (sign_extend (zero_extend)) or (sign_extend (subreg)) BZ 91865. 861 1.6 mrg 862 1.6 mrg ;; This is just another way of writing movqipsi/zero_extendqipsi 863 1.6 mrg (define_insn "" 864 1.6 mrg [(set (match_operand:PSI 0 "register_operand" "=r") 865 1.6 mrg (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))] 866 1.6 mrg "msp430x" 867 1.7 mrg "MOV%X1.B\t%1, %0" 868 1.6 mrg [(set_attr "type" "double")] 869 1.6 mrg ) 870 1.6 mrg 871 1.6 mrg (define_insn "" 872 1.6 mrg [(set (match_operand:PSI 0 "register_operand" "=r,r") 873 1.6 mrg (sign_extend:PSI (zero_extend:HI (match_operand:QI 1 "general_operand" "rYs,m"))))] 874 1.6 mrg "msp430x" 875 1.6 mrg "@ 876 1.6 mrg MOV.B\t%1, %0 877 1.7 mrg MOV%X1.B\t%1, %0" 878 1.6 mrg [(set_attr "type" "double")] 879 1.6 mrg ) 880 1.7 mrg 881 1.7 mrg ;; The next three insns emit identical assembly code. 882 1.7 mrg ;; They take a QImode and shift it in SImode. Only shift counts <= 8 883 1.7 mrg ;; are handled since that is the simple case where the high 16-bits (i.e. the 884 1.6 mrg ;; high register) are always 0. 885 1.7 mrg (define_insn "" 886 1.7 mrg [(set (match_operand:SI 0 "register_operand" "=r,r,r") 887 1.7 mrg (ashift:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "0,rm,rm")) 888 1.6 mrg (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))] 889 1.7 mrg "msp430x" 890 1.7 mrg "@ 891 1.7 mrg RLAM.W %2, %L0 { CLR %H0 892 1.7 mrg MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 893 1.7 mrg MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" 894 1.7 mrg [(set_attr "length" "4,*,*") 895 1.7 mrg (set_attr "extra_length" "0,4,6") 896 1.6 mrg (set_attr "type" "double")] 897 1.6 mrg ) 898 1.6 mrg 899 1.7 mrg (define_insn "" 900 1.7 mrg [(set (match_operand:SI 0 "register_operand" "=r,r,r") 901 1.7 mrg (ashift:SI (zero_extend:SI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0)) 902 1.6 mrg (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))] 903 1.7 mrg "msp430x" 904 1.7 mrg "@ 905 1.7 mrg RLAM.W %2, %L0 { CLR %H0 906 1.7 mrg MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 907 1.7 mrg MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" 908 1.7 mrg [(set_attr "length" "4,*,*") 909 1.7 mrg (set_attr "extra_length" "0,4,6") 910 1.6 mrg (set_attr "type" "double")] 911 1.6 mrg ) 912 1.6 mrg 913 1.6 mrg ;; Same as above but with a NOP sign_extend round the subreg 914 1.7 mrg (define_insn "" 915 1.7 mrg [(set (match_operand:SI 0 "register_operand" "=r,r,r") 916 1.7 mrg (ashift:SI (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0))) 917 1.6 mrg (match_operand:HI 2 "const_1_to_8_operand" "M,M,i")))] 918 1.7 mrg "msp430x" 919 1.7 mrg "@ 920 1.7 mrg RLAM.W %2, %L0 { CLR %H0 921 1.7 mrg MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 922 1.7 mrg MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" 923 1.7 mrg [(set_attr "length" "4,*,*") 924 1.7 mrg (set_attr "extra_length" "0,4,6") 925 1.6 mrg (set_attr "type" "double")] 926 1.6 mrg ) 927 1.6 mrg 928 1.6 mrg (define_insn "" 929 1.6 mrg [(set (match_operand:SI 0 "register_operand" "=r") 930 1.6 mrg (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))))] 931 1.6 mrg "msp430x" 932 1.7 mrg "MOV%X1.B %1, %L0 { CLR %H0" 933 1.7 mrg [(set_attr "extra_length" "4") 934 1.6 mrg (set_attr "type" "double")] 935 1.6 mrg ) 936 1.6 mrg 937 1.7 mrg (define_insn "" 938 1.7 mrg [(set (match_operand:PSI 0 "register_operand" "=r,r,r") 939 1.7 mrg (ashift:PSI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "0,rm,rm") 0)) 940 1.6 mrg (match_operand:HI 2 "const_1_to_19_operand" "M,M,i")))] 941 1.7 mrg "msp430x" 942 1.7 mrg "@ 943 1.7 mrg RLAM.W %2, %0 944 1.7 mrg MOV%X1.B %1, %0 { RLAM.W %2, %0 945 1.7 mrg MOV%X1.B %1, %0 { RPT %2 { RLAX.A %0" 946 1.7 mrg [(set_attr "length" "2,*,*") 947 1.7 mrg (set_attr "extra_length" "0,2,4") 948 1.6 mrg (set_attr "type" "double")] 949 1.6 mrg ) 950 1.6 mrg ;; END msp430 pointer manipulation combine insn patterns 951 1.1 mrg 952 1.1 mrg ;; Eliminate extraneous zero-extends mysteriously created by gcc. 953 1.1 mrg (define_peephole2 954 1.1 mrg [(set (match_operand:HI 0 "register_operand") 955 1.1 mrg (zero_extend:HI (match_operand:QI 1 "general_operand"))) 956 1.1 mrg (set (match_operand:HI 2 "register_operand") 957 1.1 mrg (zero_extend:HI (match_operand:QI 3 "register_operand")))] 958 1.1 mrg "REGNO (operands[0]) == REGNO (operands[2]) && REGNO (operands[2]) == REGNO (operands[3])" 959 1.1 mrg [(set (match_dup 0) 960 1.1 mrg (zero_extend:HI (match_dup 1)))] 961 1.3 mrg ) 962 1.1 mrg 963 1.6 mrg (define_insn "truncpsihi2" 964 1.1 mrg [(set (match_operand:HI 0 "msp430_general_dst_operand" "=rm") 965 1.1 mrg (truncate:HI (match_operand:PSI 1 "register_operand" "r")))] 966 1.1 mrg "" 967 1.7 mrg "MOVX\t%1, %0" 968 1.7 mrg [(set_attr "extension" "m") 969 1.1 mrg (set_attr "type" "double")] 970 1.1 mrg ) 971 1.1 mrg 972 1.6 mrg (define_insn "extendhisi2" 973 1.1 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r") 974 1.1 mrg (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))] 975 1.7 mrg "" 976 1.7 mrg { msp430x_extendhisi (operands, 0); return ""; } 977 1.7 mrg [(set (attr "length") 978 1.7 mrg (symbol_ref "msp430x_extendhisi (operands, 1)")) 979 1.1 mrg (set_attr "type" "double")] 980 1.1 mrg ) 981 1.1 mrg 982 1.6 mrg (define_insn "extendhipsi2" 983 1.6 mrg [(set (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 984 1.1 mrg (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))] 985 1.1 mrg "msp430x" 986 1.7 mrg "RLAM.A #4, %0 { RRAM.A #4, %0" 987 1.7 mrg [(set_attr "length_multiplier" "2") 988 1.7 mrg (set_attr "extension" "m") 989 1.1 mrg (set_attr "type" "double")] 990 1.1 mrg ) 991 1.1 mrg 992 1.1 mrg ;; Look for cases where integer/pointer conversions are suboptimal due 993 1.1 mrg ;; to missing patterns, despite us not having opcodes for these 994 1.1 mrg ;; patterns. Doing these manually allows for alternate optimization 995 1.3 mrg ;; paths. 996 1.1 mrg 997 1.6 mrg (define_insn "extend_and_shift1_hipsi2" 998 1.6 mrg [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0) 999 1.1 mrg (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 1000 1.1 mrg (const_int 1)))] 1001 1.1 mrg "msp430x" 1002 1.7 mrg "RLAM.A #4, %0 { RRAM.A #3, %0" 1003 1.7 mrg [(set_attr "length_multiplier" "2") 1004 1.7 mrg (set_attr "extension" "m") 1005 1.1 mrg (set_attr "type" "double")] 1006 1.1 mrg ) 1007 1.1 mrg 1008 1.6 mrg (define_insn "extend_and_shift2_hipsi2" 1009 1.6 mrg [(set (subreg:SI (match_operand:PSI 0 "msp430_general_dst_nonv_operand" "=r") 0) 1010 1.1 mrg (ashift:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 1011 1.1 mrg (const_int 2)))] 1012 1.1 mrg "msp430x" 1013 1.7 mrg "RLAM.A #4, %0 { RRAM.A #2, %0" 1014 1.7 mrg [(set_attr "length_multiplier" "2") 1015 1.7 mrg (set_attr "extension" "m") 1016 1.1 mrg (set_attr "type" "double")] 1017 1.1 mrg ) 1018 1.1 mrg 1019 1.1 mrg ;; We also need to be able to sign-extend pointer types (eg ptrdiff_t). 1020 1.1 mrg ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends 1021 1.1 mrg ;; it, we use a different method here. 1022 1.1 mrg 1023 1.1 mrg (define_insn "extendpsisi2" 1024 1.1 mrg [(set (match_operand:SI 0 "register_operand" "=r") 1025 1.1 mrg (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))] 1026 1.1 mrg "msp430x" 1027 1.1 mrg "* 1028 1.1 mrg /* The intention here is that we copy the bottom 16-bits of 1029 1.1 mrg %1 into %L0 (zeroing the top four bits). Then we copy the 1030 1.1 mrg entire 20-bits of %1 into %H0 and then arithmetically shift 1031 1.1 mrg it right by 16 bits, to get the top four bits of the pointer 1032 1.1 mrg sign-extended in %H0. */ 1033 1.1 mrg if (REGNO (operands[0]) == REGNO (operands[1])) 1034 1.1 mrg 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\"; 1035 1.1 mrg else 1036 1.1 mrg 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\"; 1037 1.7 mrg " 1038 1.7 mrg [(set_attr "length" "10") 1039 1.1 mrg (set_attr "type" "double")] 1040 1.1 mrg ) 1041 1.1 mrg 1042 1.1 mrg ; See the movsipsi2 pattern above for another way that GCC performs this 1043 1.1 mrg ; conversion. 1044 1.1 mrg (define_insn "truncsipsi2" 1045 1.1 mrg [(set (match_operand:PSI 0 "register_operand" "=r") 1046 1.1 mrg (truncate:PSI (match_operand:SI 1 "register_operand" "r")))] 1047 1.1 mrg "" 1048 1.7 mrg "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0" 1049 1.7 mrg [(set_attr "length" "6") 1050 1.1 mrg (set_attr "type" "single")] 1051 1.1 mrg ) 1052 1.1 mrg 1053 1.1 mrg ;;------------------------------------------------------------ 1054 1.1 mrg ;; Shift Functions 1055 1.1 mrg 1056 1.1 mrg ;; Note: We do not use the RPT ... SHIFT instruction sequence 1057 1.1 mrg ;; when the repeat count is in a register, because even though RPT 1058 1.1 mrg ;; accepts counts in registers, it does not work if the count is 1059 1.1 mrg ;; zero, and the actual count in the register has to be one less 1060 1.1 mrg ;; than the required number of iterations. We could encode a 1061 1.1 mrg ;; seqeunce like this: 1062 1.1 mrg ;; 1063 1.1 mrg ;; bit #0xf, Rn 1064 1.1 mrg ;; bz 1f 1065 1.1 mrg ;; dec Rn 1066 1.1 mrg ;; rpt Rn 1067 1.1 mrg ;; <shift> Rm 1068 1.1 mrg ;; inc Rn 1069 1.1 mrg ;; 1: 1070 1.1 mrg ;; 1071 1.1 mrg ;; But is longer than calling a helper function, and we are mostly 1072 1.1 mrg ;; concerned with code size. FIXME: Maybe enable a sequence like 1073 1.1 mrg ;; this at -O3 and above ? 1074 1.1 mrg ;; 1075 1.1 mrg ;; Note - we ignore shift counts of less than one or more than 15. 1076 1.3 mrg ;; This is permitted by the ISO C99 standard as such shifts result 1077 1.7 mrg ;; in "undefined" behavior. [6.5.7 (3)] 1078 1.7 mrg ;; 1079 1.7 mrg ;; We avoid emitting insns in msp430_expand_shift, since we would have to handle 1080 1.7 mrg ;; many extra cases such as op0 != op1, or, op0 or op1 in memory. Instead we 1081 1.7 mrg ;; let reload coerce op0 and op1 into the same register. 1082 1.7 mrg 1083 1.7 mrg (define_expand "<shift_insn><mode>3" 1084 1.7 mrg [(set (match_operand:HDI 0 "msp430_general_dst_nonv_operand") 1085 1.7 mrg (any_shift:HDI (match_operand:HDI 1 "general_operand") 1086 1.1 mrg (match_operand:HDI 2 "general_operand")))] 1087 1.1 mrg "" 1088 1.7 mrg { 1089 1.7 mrg if (msp430_expand_shift (<CODE>, <MODE>mode, operands)) 1090 1.7 mrg DONE; 1091 1.1 mrg /* Otherwise, fallthrough. */ 1092 1.1 mrg } 1093 1.1 mrg ) 1094 1.7 mrg 1095 1.7 mrg ;; All 430 HImode constant shifts 1096 1.7 mrg (define_insn "<shift_insn>hi3_430" 1097 1.7 mrg [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=rm") 1098 1.7 mrg (any_shift:HI (match_operand:HI 1 "general_operand" "0") 1099 1.7 mrg (match_operand:HI 2 "const_int_operand" "n")))] 1100 1.7 mrg "!msp430x" 1101 1.7 mrg "* msp430_output_asm_shift_insns (<CODE>, HImode, operands, false); return \"\";" 1102 1.7 mrg [(set (attr "length") 1103 1.7 mrg (symbol_ref "msp430_output_asm_shift_insns (<CODE>, HImode, operands, true)")) 1104 1.1 mrg (set_attr "type" "single")] 1105 1.1 mrg ) 1106 1.7 mrg 1107 1.7 mrg ;; All 430 and 430X SImode constant shifts 1108 1.7 mrg (define_insn "<shift_insn>si3_const" 1109 1.7 mrg [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") 1110 1.7 mrg (any_shift:SI (match_operand:SI 1 "general_operand" "0") 1111 1.1 mrg (match_operand:SI 2 "const_int_operand" "n")))] 1112 1.7 mrg "" 1113 1.7 mrg "* msp430_output_asm_shift_insns (<CODE>, SImode, operands, false); return \"\";" 1114 1.7 mrg [(set (attr "length") 1115 1.7 mrg (symbol_ref "msp430_output_asm_shift_insns (<CODE>, SImode, operands, true)")) 1116 1.1 mrg (set_attr "type" "single")] 1117 1.1 mrg ) 1118 1.7 mrg 1119 1.7 mrg (define_insn "ashl<mode>3_430x" 1120 1.7 mrg [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r") 1121 1.7 mrg (ashift:HPSI (match_operand:HPSI 1 "general_operand" "0 ,0,0,0") 1122 1.1 mrg (match_operand:HPSI 2 "const_int_operand" "M ,P,K,i")))] 1123 1.7 mrg "msp430x" 1124 1.7 mrg "@ 1125 1.7 mrg RLAM%b0\t%2, %0 1126 1.7 mrg RPT\t%2 { RLAX%b0\t%0 1127 1.7 mrg RPT\t#16 { RLAX%b0\t%0 { RPT\t%W2 { RLAX%b0\t%0 1128 1.7 mrg # undefined behavior left shift of %1 by %2" 1129 1.7 mrg [(set_attr "length" "2,4,8,0") 1130 1.1 mrg (set_attr "type" "single")] 1131 1.1 mrg ) 1132 1.7 mrg 1133 1.7 mrg (define_insn "ashr<mode>3_430x" 1134 1.7 mrg [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r") 1135 1.7 mrg (ashiftrt:HPSI (match_operand:HPSI 1 "general_operand" "0,0,0,0") 1136 1.1 mrg (match_operand:HPSI 2 "const_int_operand" "M,P,K,i")))] 1137 1.7 mrg "msp430x" 1138 1.7 mrg "@ 1139 1.7 mrg RRAM%b0\t%2, %0 1140 1.7 mrg RPT\t%2 { RRAX%b0\t%0 1141 1.7 mrg RPT\t#16 { RRAX%b0\t%0 { RPT\t%W2 { RRAX%b0\t%0 1142 1.7 mrg # undefined behavior arithmetic right shift of %1 by %2" 1143 1.7 mrg [(set_attr "length" "2,4,8,0") 1144 1.1 mrg (set_attr "type" "single")] 1145 1.1 mrg ) 1146 1.7 mrg 1147 1.7 mrg (define_insn "lshr<mode>3_430x" 1148 1.7 mrg [(set (match_operand:HPSI 0 "msp430_general_dst_nonv_operand" "=r,r,r,r") 1149 1.7 mrg (lshiftrt:HPSI (match_operand:HPSI 1 "general_operand" "0,0,0,0") 1150 1.1 mrg (match_operand:HPSI 2 "const_int_operand" "M,P,K,i")))] 1151 1.7 mrg "msp430x" 1152 1.7 mrg "@ 1153 1.7 mrg RRUM%b0\t%2, %0 1154 1.7 mrg RPT\t%2 { RRUX%b0\t%0 1155 1.7 mrg RPT\t#16 { RRUX%b0\t%0 { RPT\t%W2 { RRUX%b0\t%0 1156 1.7 mrg # undefined behavior logical right shift of %1 by %2" 1157 1.7 mrg [(set_attr "length" "2,4,8,0") 1158 1.6 mrg (set_attr "type" "single")] 1159 1.6 mrg ) 1160 1.1 mrg 1161 1.1 mrg ;;------------------------------------------------------------ 1162 1.1 mrg ;; Function Entry/Exit 1163 1.1 mrg 1164 1.1 mrg (define_expand "prologue" 1165 1.1 mrg [(const_int 0)] 1166 1.1 mrg "" 1167 1.7 mrg "msp430_expand_prologue (); DONE;" 1168 1.1 mrg ) 1169 1.1 mrg 1170 1.1 mrg (define_expand "epilogue" 1171 1.1 mrg [(const_int 0)] 1172 1.1 mrg "" 1173 1.7 mrg "msp430_expand_epilogue (0); DONE;" 1174 1.1 mrg ) 1175 1.1 mrg 1176 1.6 mrg (define_insn "epilogue_helper" 1177 1.7 mrg [(set (pc) 1178 1.6 mrg (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)) 1179 1.7 mrg (return)] 1180 1.1 mrg "!msp430x" 1181 1.7 mrg "BR%Q0\t#__mspabi_func_epilog_%J0" 1182 1.7 mrg [(set_attr "length" "2")] 1183 1.1 mrg ) 1184 1.1 mrg 1185 1.1 mrg (define_insn "prologue_start_marker" 1186 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)] 1187 1.1 mrg "" 1188 1.7 mrg "; start of prologue" 1189 1.7 mrg [(set_attr "length" "0")] 1190 1.1 mrg ) 1191 1.1 mrg 1192 1.1 mrg (define_insn "prologue_end_marker" 1193 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)] 1194 1.1 mrg "" 1195 1.7 mrg "; end of prologue" 1196 1.7 mrg [(set_attr "length" "0")] 1197 1.1 mrg ) 1198 1.1 mrg 1199 1.1 mrg (define_insn "epilogue_start_marker" 1200 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)] 1201 1.1 mrg "" 1202 1.7 mrg "; start of epilogue" 1203 1.7 mrg [(set_attr "length" "0")] 1204 1.1 mrg ) 1205 1.1 mrg 1206 1.1 mrg ;; This makes the linker add a call to exit() after the call to main() 1207 1.1 mrg ;; in crt0 1208 1.1 mrg (define_insn "msp430_refsym_need_exit" 1209 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)] 1210 1.1 mrg "" 1211 1.7 mrg ".refsym\t__crt0_call_exit" 1212 1.7 mrg [(set_attr "length" "0")] 1213 1.1 mrg ) 1214 1.1 mrg 1215 1.1 mrg ;;------------------------------------------------------------ 1216 1.1 mrg ;; Jumps 1217 1.1 mrg 1218 1.1 mrg (define_expand "call" 1219 1.1 mrg [(call:HI (match_operand 0 "") 1220 1.1 mrg (match_operand 1 ""))] 1221 1.1 mrg "" 1222 1.1 mrg "" 1223 1.1 mrg ) 1224 1.1 mrg 1225 1.1 mrg (define_insn "call_internal" 1226 1.1 mrg [(call (mem:HI (match_operand 0 "general_operand" "rYci")) 1227 1.1 mrg (match_operand 1 ""))] 1228 1.1 mrg "" 1229 1.7 mrg "CALL%Q0\t%0" 1230 1.7 mrg [(set_attr "extension" "none") 1231 1.1 mrg (set_attr "type" "single")] 1232 1.1 mrg ) 1233 1.1 mrg 1234 1.1 mrg (define_expand "call_value" 1235 1.1 mrg [(set (match_operand 0 "register_operand") 1236 1.1 mrg (call:HI (match_operand 1 "general_operand") 1237 1.1 mrg (match_operand 2 "")))] 1238 1.1 mrg "" 1239 1.1 mrg "" 1240 1.1 mrg ) 1241 1.1 mrg 1242 1.1 mrg (define_insn "call_value_internal" 1243 1.1 mrg [(set (match_operand 0 "register_operand" "=r") 1244 1.1 mrg (call (mem:HI (match_operand 1 "general_operand" "rYci")) 1245 1.1 mrg (match_operand 2 "")))] 1246 1.1 mrg "" 1247 1.7 mrg "CALL%Q0\t%1" 1248 1.7 mrg [(set_attr "extension" "none") 1249 1.1 mrg (set_attr "type" "single")] 1250 1.1 mrg ) 1251 1.6 mrg 1252 1.1 mrg (define_insn "msp430_return" 1253 1.1 mrg [(return)] 1254 1.1 mrg "" 1255 1.7 mrg { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); } 1256 1.1 mrg [(set_attr "length" "2")] 1257 1.1 mrg ) 1258 1.1 mrg 1259 1.1 mrg ;; This pattern is NOT, as expected, a return pattern. It's called 1260 1.1 mrg ;; before reload and must only store its operands, and emit a 1261 1.1 mrg ;; placeholder where the epilog needs to be. AFTER reload, the 1262 1.1 mrg ;; placeholder should get expanded into a regular-type epilogue that 1263 1.1 mrg ;; also does the EH return. 1264 1.1 mrg (define_expand "eh_return" 1265 1.1 mrg [(match_operand:HI 0 "")] 1266 1.1 mrg "" 1267 1.1 mrg "msp430_expand_eh_return (operands[0]); 1268 1.1 mrg emit_jump_insn (gen_msp430_eh_epilogue ()); 1269 1.1 mrg emit_barrier (); 1270 1.1 mrg DONE;" 1271 1.1 mrg ) 1272 1.1 mrg 1273 1.1 mrg ;; This is the actual EH epilogue. We emit it in the pattern above, 1274 1.1 mrg ;; before reload, and convert it to a real epilogue after reload. 1275 1.1 mrg (define_insn_and_split "msp430_eh_epilogue" 1276 1.1 mrg [(eh_return)] 1277 1.1 mrg "" 1278 1.1 mrg "#" 1279 1.1 mrg "reload_completed" 1280 1.1 mrg [(const_int 0)] 1281 1.7 mrg "msp430_expand_epilogue (1); DONE;" 1282 1.7 mrg [(set_attr "length" "40")] 1283 1.1 mrg ) 1284 1.1 mrg 1285 1.1 mrg (define_insn "jump" 1286 1.1 mrg [(set (pc) 1287 1.1 mrg (label_ref (match_operand 0 "" "")))] 1288 1.1 mrg "" 1289 1.7 mrg "BR%Q0\t#%l0" 1290 1.1 mrg [(set_attr "length" "4")] 1291 1.1 mrg ) 1292 1.1 mrg 1293 1.1 mrg ;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs 1294 1.1 mrg ;; in indirect jumps (cf gcc.c-torture/compile/991213-3.c). 1295 1.1 mrg (define_insn "indirect_jump" 1296 1.1 mrg [(set (pc) 1297 1.1 mrg (match_operand 0 "nonimmediate_operand" "rYl"))] 1298 1.1 mrg "" 1299 1.7 mrg "BR%Q0\t%0" 1300 1.7 mrg [(set (attr "length") 1301 1.7 mrg (if_then_else (match_operand 0 "register_operand" "") 1302 1.7 mrg (const_int 2) 1303 1.1 mrg (const_int 4)))] 1304 1.1 mrg ) 1305 1.1 mrg 1306 1.1 mrg ;;------------------------------------------------------------ 1307 1.1 mrg ;; Various Conditionals 1308 1.1 mrg 1309 1.1 mrg (define_expand "cbranch<mode>4" 1310 1.1 mrg [(parallel [(set (pc) (if_then_else 1311 1.6 mrg (match_operator 0 "" 1312 1.1 mrg [(match_operand:QHI 1 "msp430_general_dst_nonv_operand") 1313 1.1 mrg (match_operand:QHI 2 "general_operand")]) 1314 1.1 mrg (label_ref (match_operand 3 "" "")) 1315 1.1 mrg (pc))) 1316 1.1 mrg (clobber (reg:BI CARRY))] 1317 1.1 mrg )] 1318 1.1 mrg "" 1319 1.7 mrg "msp430_fixup_compare_operands (<MODE>mode, operands);" 1320 1.1 mrg ) 1321 1.1 mrg 1322 1.1 mrg (define_insn "cbranchpsi4_real" 1323 1.1 mrg [(set (pc) (if_then_else 1324 1.6 mrg (match_operator 0 "msp430_cmp_operator" 1325 1.1 mrg [(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm") 1326 1.7 mrg (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")]) 1327 1.1 mrg (label_ref (match_operand 3 "" "")) 1328 1.1 mrg (pc))) 1329 1.1 mrg (clobber (reg:BI CARRY)) 1330 1.1 mrg ] 1331 1.1 mrg "" 1332 1.1 mrg "@ 1333 1.1 mrg CMP%Q0\t%2, %1 { J%0\t%l3 1334 1.1 mrg CMPX.A\t%2, %1 { J%0\t%l3 1335 1.7 mrg CMPX.A\t%2, %1 { J%0\t%l3" 1336 1.7 mrg [(set_attr "extra_length" "2") 1337 1.7 mrg (set_attr "type" "cmp")] 1338 1.1 mrg ) 1339 1.1 mrg 1340 1.1 mrg (define_insn "cbranchqi4_real" 1341 1.1 mrg [(set (pc) (if_then_else 1342 1.6 mrg (match_operator 0 "msp430_cmp_operator" 1343 1.6 mrg [(match_operand:QI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm") 1344 1.1 mrg (match_operand:QI 2 "general_operand" "rYsYxi,rmi")]) 1345 1.1 mrg (label_ref (match_operand 3 "" "")) 1346 1.1 mrg (pc))) 1347 1.1 mrg (clobber (reg:BI CARRY)) 1348 1.1 mrg ] 1349 1.1 mrg "" 1350 1.1 mrg "@ 1351 1.6 mrg CMP.B\t%2, %1 { J%0\t%l3 1352 1.7 mrg CMPX.B\t%2, %1 { J%0\t%l3" 1353 1.7 mrg [(set_attr "extra_length" "2") 1354 1.7 mrg (set_attr "type" "cmp")] 1355 1.1 mrg ) 1356 1.1 mrg 1357 1.1 mrg (define_insn "cbranchhi4_real" 1358 1.1 mrg [(set (pc) (if_then_else 1359 1.6 mrg (match_operator 0 "msp430_cmp_operator" 1360 1.6 mrg [(match_operand:HI 1 "msp430_general_dst_nonv_operand" "rYsYx,rm") 1361 1.1 mrg (match_operand:HI 2 "general_operand" "rYsYxi,rmi")]) 1362 1.1 mrg (label_ref (match_operand 3 "" "")) 1363 1.1 mrg (pc))) 1364 1.1 mrg (clobber (reg:BI CARRY)) 1365 1.1 mrg ] 1366 1.7 mrg "" 1367 1.7 mrg "@ 1368 1.7 mrg CMP.W\t%2, %1 { J%0\t%l3 1369 1.7 mrg CMPX.W\t%2, %1 { J%0\t%l3" 1370 1.7 mrg [(set_attr "extra_length" "2") 1371 1.7 mrg (set_attr "type" "cmp")] 1372 1.1 mrg ) 1373 1.1 mrg 1374 1.1 mrg (define_insn "cbranchpsi4_reversed" 1375 1.1 mrg [(set (pc) (if_then_else 1376 1.1 mrg (match_operator 0 "msp430_reversible_cmp_operator" 1377 1.6 mrg [(match_operand:PSI 1 "general_operand" "rLs,rYsi,rmi") 1378 1.1 mrg (match_operand:PSI 2 "msp430_general_dst_nonv_operand" "r,rYs,rm")]) 1379 1.1 mrg (label_ref (match_operand 3 "" "")) 1380 1.1 mrg (pc))) 1381 1.1 mrg (clobber (reg:BI CARRY)) 1382 1.1 mrg ] 1383 1.1 mrg "" 1384 1.1 mrg "@ 1385 1.1 mrg CMP%Q0\t%1, %2 { J%R0\t%l3 1386 1.1 mrg CMPX.A\t%1, %2 { J%R0\t%l3 1387 1.7 mrg CMPX.A\t%1, %2 { J%R0\t%l3" 1388 1.7 mrg [(set_attr "extra_length" "2") 1389 1.7 mrg (set_attr "type" "cmp")] 1390 1.1 mrg ) 1391 1.1 mrg 1392 1.1 mrg (define_insn "cbranchqi4_reversed" 1393 1.1 mrg [(set (pc) (if_then_else 1394 1.6 mrg (match_operator 0 "msp430_reversible_cmp_operator" 1395 1.6 mrg [(match_operand:QI 1 "general_operand" "rYsYxi,rmi") 1396 1.1 mrg (match_operand:QI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")]) 1397 1.1 mrg (label_ref (match_operand 3 "" "")) 1398 1.1 mrg (pc))) 1399 1.1 mrg (clobber (reg:BI CARRY)) 1400 1.1 mrg ] 1401 1.1 mrg "" 1402 1.1 mrg "@ 1403 1.6 mrg CMP.B\t%1, %2 { J%R0\t%l3 1404 1.7 mrg CMPX.B\t%1, %2 { J%R0\t%l3" 1405 1.7 mrg [(set_attr "extra_length" "2") 1406 1.7 mrg (set_attr "type" "cmp")] 1407 1.1 mrg ) 1408 1.1 mrg 1409 1.1 mrg (define_insn "cbranchhi4_reversed" 1410 1.1 mrg [(set (pc) (if_then_else 1411 1.6 mrg (match_operator 0 "msp430_reversible_cmp_operator" 1412 1.6 mrg [(match_operand:HI 1 "general_operand" "rYsYxi,rmi") 1413 1.1 mrg (match_operand:HI 2 "msp430_general_dst_nonv_operand" "rYsYx,rm")]) 1414 1.1 mrg (label_ref (match_operand 3 "" "")) 1415 1.1 mrg (pc))) 1416 1.1 mrg (clobber (reg:BI CARRY)) 1417 1.1 mrg ] 1418 1.1 mrg "" 1419 1.1 mrg "@ 1420 1.6 mrg CMP.W\t%1, %2 { J%R0\t%l3 1421 1.7 mrg CMPX.W\t%1, %2 { J%R0\t%l3" 1422 1.7 mrg [(set_attr "extra_length" "2") 1423 1.7 mrg (set_attr "type" "cmp")] 1424 1.1 mrg ) 1425 1.1 mrg 1426 1.1 mrg (define_insn "*bitbranch<mode>4" 1427 1.6 mrg [(set (pc) (if_then_else 1428 1.6 mrg (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1429 1.1 mrg (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1430 1.7 mrg (const_int 0)) 1431 1.1 mrg (label_ref (match_operand 2 "" "")) 1432 1.1 mrg (pc))) 1433 1.1 mrg (clobber (reg:BI CARRY)) 1434 1.1 mrg ] 1435 1.1 mrg "" 1436 1.1 mrg "@ 1437 1.6 mrg BIT%x0%b0\t%1, %0 { JNE\t%l2 1438 1.7 mrg BITX%b0\t%1, %0 { JNE\t%l2" 1439 1.7 mrg [(set_attr "extra_length" "2") 1440 1.7 mrg (set_attr "type" "double")] 1441 1.1 mrg ) 1442 1.1 mrg 1443 1.1 mrg (define_insn "*bitbranch<mode>4" 1444 1.6 mrg [(set (pc) (if_then_else 1445 1.6 mrg (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1446 1.1 mrg (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1447 1.7 mrg (const_int 0)) 1448 1.1 mrg (label_ref (match_operand 2 "" "")) 1449 1.1 mrg (pc))) 1450 1.1 mrg (clobber (reg:BI CARRY)) 1451 1.1 mrg ] 1452 1.6 mrg "" 1453 1.6 mrg "@ 1454 1.6 mrg BIT%x0%b0\t%1, %0 { JEQ\t%l2 1455 1.7 mrg BITX%b0\t%1, %0 { JEQ\t%l2" 1456 1.7 mrg [(set_attr "extra_length" "2") 1457 1.7 mrg (set_attr "type" "double")] 1458 1.1 mrg ) 1459 1.1 mrg 1460 1.1 mrg (define_insn "*bitbranch<mode>4" 1461 1.6 mrg [(set (pc) (if_then_else 1462 1.6 mrg (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1463 1.1 mrg (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1464 1.7 mrg (const_int 0)) 1465 1.1 mrg (pc) 1466 1.1 mrg (label_ref (match_operand 2 "" "")))) 1467 1.1 mrg (clobber (reg:BI CARRY)) 1468 1.1 mrg ] 1469 1.6 mrg "" 1470 1.6 mrg "@ 1471 1.6 mrg BIT%x0%b0\t%1, %0 { JNE\t%l2 1472 1.7 mrg BITX%b0\t%1, %0 { JNE\t%l2" 1473 1.7 mrg [(set_attr "extra_length" "2") 1474 1.7 mrg (set_attr "type" "double")] 1475 1.1 mrg ) 1476 1.1 mrg 1477 1.1 mrg (define_insn "*bitbranch<mode>4" 1478 1.6 mrg [(set (pc) (if_then_else 1479 1.6 mrg (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") 1480 1.1 mrg (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) 1481 1.7 mrg (const_int 0)) 1482 1.1 mrg (pc) 1483 1.1 mrg (label_ref (match_operand 2 "" "")))) 1484 1.1 mrg (clobber (reg:BI CARRY)) 1485 1.1 mrg ] 1486 1.6 mrg "" 1487 1.6 mrg "@ 1488 1.6 mrg BIT%x0%b0\t%1, %0 { JEQ\t%l2 1489 1.7 mrg BITX%b0\t%1, %0 { JEQ\t%l2" 1490 1.7 mrg [(set_attr "extra_length" "2") 1491 1.7 mrg (set_attr "type" "double")] 1492 1.1 mrg ) 1493 1.1 mrg 1494 1.1 mrg ;;------------------------------------------------------------ 1495 1.1 mrg ;; zero-extract versions of the above 1496 1.1 mrg 1497 1.1 mrg (define_insn "*bitbranch<mode>4_z" 1498 1.6 mrg [(set (pc) (if_then_else 1499 1.1 mrg (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rYs,rm") 1500 1.7 mrg (const_int 1) 1501 1.1 mrg (match_operand 1 "const_0_to_15_operand" "i,i")) 1502 1.7 mrg (const_int 0)) 1503 1.1 mrg (label_ref (match_operand 2 "" "")) 1504 1.1 mrg (pc))) 1505 1.1 mrg (clobber (reg:BI CARRY)) 1506 1.1 mrg ] 1507 1.1 mrg "" 1508 1.1 mrg "@ 1509 1.1 mrg BIT%x0%b0\t%p1, %0 { JNE\t%l2 1510 1.7 mrg BIT%X0%b0\t%p1, %0 { JNE\t%l2" 1511 1.7 mrg [(set_attr "extra_length" "2") 1512 1.7 mrg (set_attr "type" "double")] 1513 1.1 mrg ) 1514 1.1 mrg 1515 1.1 mrg (define_insn "*bitbranch<mode>4_z" 1516 1.6 mrg [(set (pc) (if_then_else 1517 1.1 mrg (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm") 1518 1.7 mrg (const_int 1) 1519 1.1 mrg (match_operand 1 "const_0_to_15_operand" "i")) 1520 1.7 mrg (const_int 0)) 1521 1.1 mrg (label_ref (match_operand 2 "" "")) 1522 1.1 mrg (pc))) 1523 1.1 mrg (clobber (reg:BI CARRY)) 1524 1.1 mrg ] 1525 1.6 mrg "" 1526 1.7 mrg "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" 1527 1.7 mrg [(set_attr "extra_length" "2") 1528 1.7 mrg (set_attr "type" "double")] 1529 1.1 mrg ) 1530 1.1 mrg 1531 1.1 mrg (define_insn "*bitbranch<mode>4_z" 1532 1.6 mrg [(set (pc) (if_then_else 1533 1.1 mrg (eq (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm") 1534 1.7 mrg (const_int 1) 1535 1.1 mrg (match_operand 1 "const_0_to_15_operand" "i")) 1536 1.7 mrg (const_int 0)) 1537 1.1 mrg (pc) 1538 1.1 mrg (label_ref (match_operand 2 "" "")))) 1539 1.1 mrg (clobber (reg:BI CARRY)) 1540 1.1 mrg ] 1541 1.1 mrg "" 1542 1.7 mrg "BIT%X0%b0\t%p1, %0 { JNE\t%l2" 1543 1.7 mrg [(set_attr "extra_length" "2") 1544 1.7 mrg (set_attr "type" "double")] 1545 1.1 mrg ) 1546 1.1 mrg 1547 1.1 mrg (define_insn "*bitbranch<mode>4_z" 1548 1.6 mrg [(set (pc) (if_then_else 1549 1.1 mrg (ne (zero_extract:HI (match_operand:QHI 0 "msp430_general_dst_operand" "rm") 1550 1.7 mrg (const_int 1) 1551 1.1 mrg (match_operand 1 "const_0_to_15_operand" "i")) 1552 1.7 mrg (const_int 0)) 1553 1.1 mrg (pc) 1554 1.1 mrg (label_ref (match_operand 2 "" "")))) 1555 1.1 mrg (clobber (reg:BI CARRY)) 1556 1.1 mrg ] 1557 1.1 mrg "" 1558 1.7 mrg "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" 1559 1.7 mrg [(set_attr "extra_length" "2") 1560 1.7 mrg (set_attr "type" "double")] 1561 1.1 mrg ) 1562 1.1 mrg 1563 1.1 mrg ;;------------------------------------------------------------ 1564 1.1 mrg ;; Misc 1565 1.1 mrg 1566 1.1 mrg (define_insn "nop" 1567 1.1 mrg [(const_int 0)] 1568 1.1 mrg "1" 1569 1.7 mrg "NOP" 1570 1.1 mrg [(set_attr "length" "2")] 1571 1.1 mrg ) 1572 1.1 mrg 1573 1.1 mrg (define_insn "disable_interrupts" 1574 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_DINT)] 1575 1.1 mrg "" 1576 1.7 mrg "DINT \; NOP" 1577 1.7 mrg [(set_attr "length" "2")] 1578 1.1 mrg ) 1579 1.1 mrg 1580 1.1 mrg (define_insn "enable_interrupts" 1581 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_EINT)] 1582 1.1 mrg "" 1583 1.7 mrg "EINT" 1584 1.7 mrg [(set_attr "length" "2")] 1585 1.1 mrg ) 1586 1.1 mrg 1587 1.1 mrg (define_insn "push_intr_state" 1588 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)] 1589 1.1 mrg "" 1590 1.7 mrg "PUSH\tSR" 1591 1.7 mrg [(set_attr "length" "2")] 1592 1.1 mrg ) 1593 1.1 mrg 1594 1.1 mrg (define_insn "pop_intr_state" 1595 1.1 mrg [(unspec_volatile [(const_int 0)] UNS_POP_INTR)] 1596 1.1 mrg "" 1597 1.7 mrg "POP\tSR" 1598 1.7 mrg [(set_attr "length" "2")] 1599 1.1 mrg ) 1600 1.1 mrg 1601 1.1 mrg ;; Clear bits in the copy of the status register that is currently 1602 1.1 mrg ;; saved on the stack at the top of the interrupt handler. 1603 1.1 mrg (define_insn "bic_SR" 1604 1.1 mrg [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)] 1605 1.1 mrg "" 1606 1.7 mrg "BIC.W\t%0, %O0(SP)" 1607 1.7 mrg [(set_attr "type" "single") 1608 1.7 mrg (set_attr "extra_length" "2")] 1609 1.1 mrg ) 1610 1.1 mrg 1611 1.1 mrg ;; Set bits in the copy of the status register that is currently 1612 1.1 mrg ;; saved on the stack at the top of the interrupt handler. 1613 1.1 mrg (define_insn "bis_SR" 1614 1.1 mrg [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)] 1615 1.1 mrg "" 1616 1.7 mrg "BIS.W\t%0, %O0(SP)" 1617 1.7 mrg [(set_attr "type" "single") 1618 1.7 mrg (set_attr "extra_length" "2")] 1619 1.1 mrg ) 1620 1.1 mrg 1621 1.1 mrg ;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int))) 1622 1.1 mrg ;; very late on in the compilation and not splitting it into separate 1623 1.1 mrg ;; instructions, so we provide a pattern to support it here. 1624 1.7 mrg (define_insn "andneghi3" 1625 1.7 mrg [(set (match_operand:HI 0 "register_operand" "=r,r") 1626 1.7 mrg (and:HI (neg:HI (match_operand:HI 1 "general_operand" "0,rm")) 1627 1.1 mrg (match_operand 2 "immediate_operand" "n,n")))] 1628 1.7 mrg "" 1629 1.7 mrg "@ 1630 1.7 mrg INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0 1631 1.7 mrg MOV%X1.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0" 1632 1.7 mrg [(set_attr "length" "12,14") 1633 1.7 mrg (set_attr "type" "double")] 1634 1.7 mrg ) 1635 1.1 mrg 1636 1.1 mrg 1637 1.1 mrg (define_insn "delay_cycles_start" 1638 1.1 mrg [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 1639 1.1 mrg UNS_DELAY_START)] 1640 1.1 mrg "" 1641 1.7 mrg "; Begin %J0 cycle delay" 1642 1.7 mrg [(set_attr "length" "0")] 1643 1.1 mrg ) 1644 1.1 mrg 1645 1.1 mrg (define_insn "delay_cycles_end" 1646 1.1 mrg [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 1647 1.1 mrg UNS_DELAY_END)] 1648 1.1 mrg "" 1649 1.1 mrg "; End %J0 cycle delay" 1650 1.1 mrg ) 1651 1.1 mrg 1652 1.1 mrg (define_insn "delay_cycles_32" 1653 1.1 mrg [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1654 1.1 mrg (match_operand 1 "immediate_operand" "i") 1655 1.1 mrg ] UNS_DELAY_32)] 1656 1.1 mrg "" 1657 1.1 mrg "PUSH r13 1658 1.1 mrg PUSH r14 1659 1.1 mrg MOV.W %A0, r13 1660 1.1 mrg MOV.W %B0, r14 1661 1.1 mrg 1: SUB.W #1, r13 1662 1.1 mrg SUBC.W #0, r14 1663 1.1 mrg JNE 1b 1664 1.1 mrg TST.W r13 1665 1.1 mrg JNE 1b 1666 1.1 mrg POP r14 1667 1.7 mrg POP r13" 1668 1.7 mrg [(set_attr "length" "32")] 1669 1.1 mrg ) 1670 1.1 mrg 1671 1.1 mrg (define_insn "delay_cycles_32x" 1672 1.1 mrg [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1673 1.1 mrg (match_operand 1 "immediate_operand" "i") 1674 1.1 mrg ] UNS_DELAY_32X)] 1675 1.3 mrg "" 1676 1.1 mrg "PUSHM.A #2,r14 1677 1.1 mrg MOV.W %A0, r13 1678 1.1 mrg MOV.W %B0, r14 1679 1.1 mrg 1: SUB.W #1, r13 1680 1.1 mrg SUBC.W #0, r14 1681 1.1 mrg JNE 1b 1682 1.1 mrg TST.W r13 1683 1.3 mrg JNE 1b 1684 1.7 mrg POPM.A #2,r14" 1685 1.7 mrg [(set_attr "length" "28")] 1686 1.1 mrg ) 1687 1.1 mrg 1688 1.1 mrg (define_insn "delay_cycles_16" 1689 1.1 mrg [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1690 1.1 mrg (match_operand 1 "immediate_operand" "i") 1691 1.1 mrg ] UNS_DELAY_16)] 1692 1.1 mrg "" 1693 1.1 mrg "PUSH r13 1694 1.1 mrg MOV.W %0, r13 1695 1.1 mrg 1: SUB.W #1, r13 1696 1.1 mrg JNE 1b 1697 1.7 mrg POP r13" 1698 1.7 mrg [(set_attr "length" "14")] 1699 1.1 mrg ) 1700 1.1 mrg 1701 1.1 mrg (define_insn "delay_cycles_16x" 1702 1.1 mrg [(unspec_volatile [(match_operand 0 "immediate_operand" "i") 1703 1.1 mrg (match_operand 1 "immediate_operand" "i") 1704 1.1 mrg ] UNS_DELAY_16X)] 1705 1.1 mrg "" 1706 1.1 mrg "PUSHM.A #1,r13 1707 1.1 mrg MOV.W %0, r13 1708 1.1 mrg 1: SUB.W #1, r13 1709 1.1 mrg JNE 1b 1710 1.7 mrg POPM.A #1,r13" 1711 1.7 mrg [(set_attr "length" "14")] 1712 1.1 mrg ) 1713 1.1 mrg 1714 1.1 mrg (define_insn "delay_cycles_2" 1715 1.1 mrg [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)] 1716 1.1 mrg "" 1717 1.7 mrg "JMP .+2" 1718 1.7 mrg [(set_attr "length" "2")] 1719 1.1 mrg ) 1720 1.1 mrg 1721 1.1 mrg (define_insn "delay_cycles_1" 1722 1.1 mrg [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)] 1723 1.1 mrg "" 1724 1.7 mrg "NOP" 1725 1.7 mrg [(set_attr "length" "2")] 1726 1.7 mrg ) 1727 1.7 mrg 1728 1.7 mrg (define_expand "mulhi3" 1729 1.7 mrg [(set (match_operand:HI 0 "register_operand" "=r") 1730 1.7 mrg (mult:HI (match_operand:HI 1 "register_operand" "%0") 1731 1.7 mrg (match_operand:HI 2 "register_operand" "r")))] 1732 1.7 mrg "msp430_has_hwmult ()" 1733 1.7 mrg { 1734 1.7 mrg msp430_expand_helper (operands, "__mspabi_mpyi", false); 1735 1.7 mrg DONE; 1736 1.7 mrg } 1737 1.7 mrg ) 1738 1.7 mrg 1739 1.7 mrg (define_expand "mulsi3" 1740 1.7 mrg [(set (match_operand:SI 0 "register_operand" "=r") 1741 1.7 mrg (mult:SI (match_operand:SI 1 "register_operand" "%0") 1742 1.7 mrg (match_operand:SI 2 "register_operand" "r")))] 1743 1.7 mrg "msp430_has_hwmult ()" 1744 1.7 mrg { 1745 1.7 mrg msp430_expand_helper (operands, "__mspabi_mpyl", false); 1746 1.7 mrg DONE; 1747 1.7 mrg } 1748 1.1 mrg ) 1749 1.6 mrg 1750 1.6 mrg ; libgcc helper functions for widening multiplication aren't currently 1751 1.6 mrg ; generated by gcc, so we can't catch them later and map them to the mspabi 1752 1.6 mrg ; functions. 1753 1.6 mrg ; We catch the patterns here and either generate a call to the helper function, 1754 1.6 mrg ; or emit the hardware multiply instruction sequence inline. 1755 1.6 mrg ; 1756 1.6 mrg ; If we don't have hardware multiply support, it will generally be slower and 1757 1.6 mrg ; result in larger code to call the mspabi library function to perform the 1758 1.7 mrg ; widening multiplication than just leaving GCC to widen the arguments itself. 1759 1.6 mrg 1760 1.6 mrg (define_expand "mulhisi3" 1761 1.6 mrg [(set (match_operand:SI 0 "register_operand" "=r") 1762 1.6 mrg (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1763 1.6 mrg (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1764 1.6 mrg "msp430_has_hwmult ()" 1765 1.6 mrg { 1766 1.6 mrg /* Leave the other case for the inline insn. */ 1767 1.6 mrg if (!(optimize > 2 && msp430_has_hwmult ())) 1768 1.6 mrg { 1769 1.6 mrg msp430_expand_helper (operands, "__mspabi_mpysl", false); 1770 1.6 mrg DONE; 1771 1.6 mrg } 1772 1.6 mrg } 1773 1.6 mrg ) 1774 1.6 mrg 1775 1.6 mrg (define_expand "umulhisi3" 1776 1.6 mrg [(set (match_operand:SI 0 "register_operand" "=r") 1777 1.6 mrg (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1778 1.6 mrg (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1779 1.6 mrg "msp430_has_hwmult ()" 1780 1.6 mrg { 1781 1.6 mrg /* Leave the other case for the inline insn. */ 1782 1.6 mrg if (!(optimize > 2 && msp430_has_hwmult ())) 1783 1.6 mrg { 1784 1.6 mrg msp430_expand_helper (operands, "__mspabi_mpyul", false); 1785 1.6 mrg DONE; 1786 1.6 mrg } 1787 1.6 mrg } 1788 1.6 mrg ) 1789 1.7 mrg 1790 1.7 mrg (define_expand "mulsidi3" 1791 1.7 mrg [(set (match_operand:DI 0 "register_operand" "=r") 1792 1.7 mrg (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1793 1.7 mrg (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1794 1.7 mrg "msp430_has_hwmult ()" 1795 1.7 mrg { 1796 1.7 mrg /* Leave the other case for the inline insn. */ 1797 1.7 mrg if (!(optimize > 2 && msp430_has_hwmult ())) 1798 1.7 mrg { 1799 1.7 mrg msp430_expand_helper (operands, "__mspabi_mpysll", false); 1800 1.7 mrg DONE; 1801 1.7 mrg } 1802 1.7 mrg } 1803 1.7 mrg ) 1804 1.7 mrg 1805 1.7 mrg (define_expand "umulsidi3" 1806 1.7 mrg [(set (match_operand:DI 0 "register_operand" "=r") 1807 1.7 mrg (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1808 1.7 mrg (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1809 1.7 mrg "msp430_has_hwmult ()" 1810 1.7 mrg { 1811 1.7 mrg /* Leave the other case for the inline insn. */ 1812 1.7 mrg if (!(optimize > 2 && msp430_has_hwmult ())) 1813 1.7 mrg { 1814 1.7 mrg msp430_expand_helper (operands, "__mspabi_mpyull", false); 1815 1.7 mrg DONE; 1816 1.7 mrg } 1817 1.7 mrg } 1818 1.7 mrg ) 1819 1.7 mrg 1820 1.6 mrg 1821 1.1 mrg (define_insn "*mulhisi3_inline" 1822 1.1 mrg [(set (match_operand:SI 0 "register_operand" "=r") 1823 1.1 mrg (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1824 1.6 mrg (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1825 1.1 mrg "optimize > 2 && msp430_has_hwmult ()" 1826 1.1 mrg "* 1827 1.1 mrg if (msp430_use_f5_series_hwmult ()) 1828 1.1 mrg 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\"; 1829 1.1 mrg else 1830 1.1 mrg 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\"; 1831 1.7 mrg " 1832 1.1 mrg [(set_attr "length" "24")] 1833 1.1 mrg ) 1834 1.6 mrg 1835 1.1 mrg (define_insn "*umulhisi3_inline" 1836 1.1 mrg [(set (match_operand:SI 0 "register_operand" "=r") 1837 1.1 mrg (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0")) 1838 1.6 mrg (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))] 1839 1.1 mrg "optimize > 2 && msp430_has_hwmult ()" 1840 1.1 mrg "* 1841 1.1 mrg if (msp430_use_f5_series_hwmult ()) 1842 1.1 mrg 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\"; 1843 1.1 mrg else 1844 1.1 mrg 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\"; 1845 1.7 mrg " 1846 1.1 mrg [(set_attr "length" "24")] 1847 1.1 mrg ) 1848 1.7 mrg 1849 1.1 mrg (define_insn "*mulsidi3_inline" 1850 1.1 mrg [(set (match_operand:DI 0 "register_operand" "=r") 1851 1.1 mrg (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1852 1.6 mrg (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1853 1.1 mrg "optimize > 2 && msp430_has_hwmult ()" 1854 1.1 mrg "* 1855 1.1 mrg if (msp430_use_f5_series_hwmult ()) 1856 1.1 mrg 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\"; 1857 1.1 mrg else 1858 1.1 mrg 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\"; 1859 1.7 mrg " 1860 1.1 mrg [(set_attr "length" "40")] 1861 1.1 mrg ) 1862 1.7 mrg 1863 1.1 mrg (define_insn "*umulsidi3_inline" 1864 1.1 mrg [(set (match_operand:DI 0 "register_operand" "=r") 1865 1.1 mrg (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) 1866 1.6 mrg (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))] 1867 1.1 mrg "optimize > 2 && msp430_has_hwmult ()" 1868 1.1 mrg "* 1869 1.1 mrg if (msp430_use_f5_series_hwmult ()) 1870 1.1 mrg 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\"; 1871 1.1 mrg else 1872 1.1 mrg 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\"; 1873 1.7 mrg " 1874 1.1 mrg [(set_attr "length" "40")] 1875 ) 1876