0
|
1 ;; GCC machine description for picochip
|
|
2 ;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
|
|
3 ;; Contributed by picoChip Designs Ltd (http://www.picochip.com)
|
|
4 ;; Maintained by Daniel Towner (dant@picochip.com) and Hariharan
|
|
5 ;; Sandanagobalane (hariharan@picochip.com)
|
|
6 ;;
|
|
7 ;; This file is part of GCC.
|
|
8 ;;
|
|
9 ;; GCC is free software; you can redistribute it and/or modify
|
|
10 ;; it under the terms of the GNU General Public License as published by
|
|
11 ;; the Free Software Foundation; either version 3, or (at your option)
|
|
12 ;; any later version.
|
|
13 ;;
|
|
14 ;; GCC is distributed in the hope that it will be useful,
|
|
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17 ;; GNU General Public License for more details.
|
|
18 ;;
|
|
19 ;; You should have received a copy of the GNU General Public License
|
|
20 ;; along with GCC; see the file COPYING3. If not, see
|
|
21 ;; <http://www.gnu.org/licenses/>.
|
|
22
|
|
23 ;; -------------------------------------------------------------------------
|
|
24
|
|
25 ;; In addition to the normal output operand formats, the following
|
|
26 ;; letter formats are also available:
|
|
27 ;;
|
|
28 ;; The following can be used for constants, or the constant part of a
|
|
29 ;; memory offset.
|
|
30 ;; Q - Output constant unaltered (byte mode).
|
|
31 ;; M - Alias for Q, which only works with memory operands.
|
|
32 ;; H - Divide constant by 2 (i.e., HImode is 2 bytes)
|
|
33 ;; S - Divide constant by 4 (i.e., SImode is 4 bytes)
|
|
34 ;;
|
|
35 ;; The following can be used for two part addresses (i.e., base +
|
|
36 ;; offset or base[offset]).
|
|
37 ;; o - Output offset only.
|
|
38 ;; b - Output base only.
|
|
39 ;;
|
|
40 ;; The following are used on SI registers and constants
|
|
41 ;; R - Output register pair (i.e., R[n:m])
|
|
42 ;; L - Output lower word/register
|
|
43 ;; U - Output upper word/register
|
|
44 ;;
|
|
45 ;; The following are used on DI mode registers.
|
|
46 ;; X - Output 3rd register
|
|
47 ;; Y - Output 4th register
|
|
48 ;;
|
|
49 ;; Miscellaneous
|
|
50 ;; | - Output VLIW separator
|
|
51 ;; r - Output register value of memory operand.
|
|
52 ;; I - Output an opcode (e.g., ADD for plus, LSL for lshift)
|
|
53 ;; i - Output an opcode in symbolic notation (e.g., + for plus)
|
|
54
|
|
55 ;; Define the length of an instruction. Used to allow different types
|
|
56 ;; of branches to be used for different branch offsets. Default to 6
|
|
57 ;; bytes, which is the longest possible single instruction.
|
|
58 (define_attr "length" "" (const_int 6))
|
|
59
|
|
60 ;; Define some constants which are used in conjuction with branch
|
|
61 ;; scheduling. Branches must be 10-bit signed, which equates to
|
|
62 ;; [-512,511]. However, to compensate for the lack of branch alignment
|
|
63 ;; these offsets are reduced by a factor of 2.
|
|
64
|
|
65 (define_constants
|
|
66 [
|
|
67 (MIN_BRANCH_OFFSET -256)
|
|
68 (MAX_BRANCH_OFFSET 255)
|
|
69 (SHORT_BRANCH_LENGTH 6) ; The size of a schedulable short branch.
|
|
70 (LONG_BRANCH_LENGTH 16) ; The size of an expanded JMP?? macro.
|
|
71 ]
|
|
72 )
|
|
73
|
|
74 ;; Define identifiers for various special instructions. These
|
|
75 ;; instructions may then be used in RTL expansions, or builtins.
|
|
76 (define_constants
|
|
77 [
|
|
78 ; Special instruction builtins.
|
|
79 (UNSPEC_SBC 0) ; Sign-bit count
|
|
80 (UNSPEC_ADDS 1) ; Saturating addition
|
|
81 (UNSPEC_SUBS 2) ; Saturating subtraction
|
|
82 (UNSPEC_BREV 3) ; Bit reversal
|
|
83
|
|
84 ; Special internal instructions (only used by compiler)
|
|
85 (UNSPEC_COPYSW 5) ; Get status word
|
|
86 (UNSPEC_ADDC 6) ; Add with carry.
|
|
87
|
|
88 ; Scalar port communication builtins
|
|
89 (UNSPEC_PUT 7) ; Communication (put): port[op0] := op1
|
|
90 (UNSPEC_GET 8) ; Communication (get): op0 := get_port[op1]
|
|
91 (UNSPEC_TESTPORT 9) ; Communication (test): op0 := testport[op1]
|
|
92
|
|
93 ; Array port communication builtins. These all take extra
|
|
94 ; arguments giving information about the array access being used.
|
|
95 (UNSPEC_PUT_ARRAY 10) ; Array put
|
|
96 (UNSPEC_GET_ARRAY 11) ; Array get
|
|
97 (UNSPEC_TESTPORT_ARRAY 12) ; Array test port
|
|
98
|
|
99 ;; Array port expansions
|
|
100 (UNSPEC_CALL_GET_ARRAY 13) ;
|
|
101 (UNSPEC_CALL_PUT_ARRAY 14) ;
|
|
102 (UNSPEC_CALL_TESTPORT_ARRAY 15) ;
|
|
103
|
|
104 ; Array port low-level fn calls
|
|
105 (UNSPEC_CALL_GET_FN 16)
|
|
106 (UNSPEC_CALL_TESTPORT_FN 17)
|
|
107
|
|
108 ; Halt instruction.
|
|
109 (UNSPEC_HALT 18)
|
|
110
|
|
111 ; Internal TSTPORT instruction, used to generate a single TSTPORT
|
|
112 ; instruction for use in the testport branch split.
|
|
113 (UNSPEC_INTERNAL_TESTPORT 19)
|
|
114 ]
|
|
115 )
|
|
116
|
|
117 ;; Register ID's
|
|
118 (define_constants
|
|
119 [
|
|
120 (LINK_REGNUM 12) ; Function link register.
|
|
121 (CC_REGNUM 17) ; Condition flags.
|
|
122 (ACC_REGNUM 16) ; Condition flags.
|
|
123 ]
|
|
124 )
|
|
125
|
|
126 ;;============================================================================
|
|
127 ;; Predicates and constraints
|
|
128 ;;============================================================================
|
|
129
|
|
130 (include "predicates.md")
|
|
131 (include "constraints.md")
|
|
132
|
|
133 ;;============================================================================
|
|
134 ;; First operand shifting patterns. These allow certain instructions
|
|
135 ;; (e.g., add, and, or, xor, sub) to apply a shift-by-constant to
|
|
136 ;; their first operand.
|
|
137 ;;
|
|
138 ;; Note that only the first operand is matched by the shift, to ensure
|
|
139 ;; that non-commutative instructions (like subtract) work
|
|
140 ;; properly. When a commutative instruction, with a shift in the
|
|
141 ;; second operand is found, the compiler will reorder the operands to
|
|
142 ;; match.
|
|
143 ;;============================================================================
|
|
144
|
|
145 (define_insn "*firstOpGenericAshift"
|
|
146 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
147 (match_operator:HI 1 "picochip_first_op_shift_operator"
|
|
148 [(ashift:HI
|
|
149 (match_operand:HI 2 "register_operand" "r")
|
|
150 (match_operand:HI 3 "picochip_J_operand" "J"))
|
|
151 (match_operand:HI 4 "picochip_register_or_immediate_operand" "ri")]))
|
|
152 (clobber (reg:CC CC_REGNUM))]
|
|
153 ""
|
|
154 "%I1.0 [LSL %2,%3],%4,%0\t// %0 := (%2 << %3) %i1 %4"
|
|
155 [(set_attr "type" "picoAlu")
|
|
156 ;; A long constant must be used if the operator instruction doesn't
|
|
157 ;; accept immediates, or if the constant is too big to fit the
|
|
158 ;; immediate. Note that the following condition is written in the
|
|
159 ;; way which uses the least number of predicates.
|
|
160 (set (attr "longConstant")
|
|
161 (cond [(ior (match_operand 4 "register_operand")
|
|
162 (and (match_operand 1 "picochip_first_op_shift_operator_imm")
|
|
163 (match_operand 1 "picochip_J_operand")))
|
|
164 (const_string "false")]
|
|
165 (const_string "true")))])
|
|
166
|
|
167 ;; During combine, ashift gets converted into a multiply, necessitating the following pattern.
|
|
168 ;; Note that we do a log_2(imm) to get the actual LSL operand.
|
|
169
|
|
170 (define_insn "*firstOpGenericAshift"
|
|
171 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
172 (match_operator:HI 1 "picochip_first_op_shift_operator"
|
|
173 [(mult:HI
|
|
174 (match_operand:HI 2 "register_operand" "r")
|
|
175 (match_operand:HI 3 "power_of_2_imm_operand" "n"))
|
|
176 (match_operand:HI 4 "picochip_register_or_immediate_operand" "ri")]))
|
|
177 (clobber (reg:CC CC_REGNUM))]
|
|
178 ""
|
|
179 "%I1.0 [LSL %2,%P3],%4,%0\t// %0 := (%2 << %3) %i1 %4"
|
|
180 [(set_attr "type" "picoAlu")
|
|
181 ;; A long constant must be used if the operator instruction doesn't
|
|
182 ;; accept immediates, or if the constant is too big to fit the
|
|
183 ;; immediate. Note that the following condition is written in the
|
|
184 ;; way which uses the least number of predicates.
|
|
185 (set (attr "longConstant")
|
|
186 (cond [(ior (match_operand 4 "register_operand")
|
|
187 (and (match_operand 1 "picochip_first_op_shift_operator_imm")
|
|
188 (match_operand 1 "picochip_J_operand")))
|
|
189 (const_string "false")]
|
|
190 (const_string "true")))])
|
|
191
|
|
192 (define_insn "*firstOpGenericAshiftrt"
|
|
193 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
194 (match_operator:HI 1 "picochip_first_op_shift_operator"
|
|
195 [(ashiftrt:HI
|
|
196 (match_operand:HI 2 "register_operand" "r")
|
|
197 (match_operand:HI 3 "picochip_J_operand" "J"))
|
|
198 (match_operand:HI 4 "picochip_register_or_immediate_operand" "ri")]))
|
|
199 (clobber (reg:CC CC_REGNUM))]
|
|
200 ""
|
|
201 "%I1.0 [ASR %2,%3],%4,%0\t// %0 := (%2 >>{arith} %3) %i1 %4"
|
|
202 [(set_attr "type" "picoAlu")
|
|
203 ;; A long constant must be used if the operator instruction doesn't
|
|
204 ;; accept immediates, or if the constant is too big to fit the
|
|
205 ;; immediate. Note that the following condition is written in the
|
|
206 ;; way which uses the least number of predicates.
|
|
207 (set (attr "longConstant")
|
|
208 (cond [(ior (match_operand 4 "register_operand")
|
|
209 (and (match_operand 1 "picochip_first_op_shift_operator_imm")
|
|
210 (match_operand 1 "picochip_J_operand")))
|
|
211 (const_string "false")]
|
|
212 (const_string "true")))])
|
|
213
|
|
214 (define_insn "*firstOpGenericLshiftrt"
|
|
215 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
216 (match_operator:HI 1 "picochip_first_op_shift_operator"
|
|
217 [(lshiftrt:HI
|
|
218 (match_operand:HI 2 "register_operand" "r")
|
|
219 (match_operand:HI 3 "picochip_J_operand" "J"))
|
|
220 (match_operand:HI 4 "picochip_register_or_immediate_operand" "ri")]))
|
|
221 (clobber (reg:CC CC_REGNUM))]
|
|
222 ""
|
|
223 "%I1.0 [LSR %2,%3],%4,%0\t// %0 := (%2 >> %3) %i1 %4"
|
|
224 [(set_attr "type" "picoAlu")
|
|
225 ;; A long constant must be used if the operator instruction doesn't
|
|
226 ;; accept immediates, or if the constant is too big to fit the
|
|
227 ;; immediate. Note that the following condition is written in the
|
|
228 ;; way which uses the least number of predicates.
|
|
229 (set (attr "longConstant")
|
|
230 (cond [(ior (match_operand 4 "register_operand")
|
|
231 (and (match_operand 1 "picochip_first_op_shift_operator_imm")
|
|
232 (match_operand 1 "picochip_J_operand")))
|
|
233 (const_string "false")]
|
|
234 (const_string "true")))])
|
|
235
|
|
236 ;;===========================================================================
|
|
237 ;; Jump instructions.
|
|
238 ;;===========================================================================
|
|
239
|
|
240 (define_insn "indirect_jump"
|
|
241 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
|
|
242 ""
|
|
243 "JR (%0)\t// Indirect_jump to %0 %>"
|
|
244 [(set_attr "type" "realBranch")
|
|
245 (set_attr "length" "3")])
|
|
246
|
|
247 (define_insn "jump"
|
|
248 [(set (pc)
|
|
249 (label_ref (match_operand 0 "" "")))]
|
|
250 ""
|
|
251 "* return picochip_output_jump(insn);"
|
|
252 [(set (attr "length")
|
|
253 (if_then_else
|
|
254 (and (ge (minus (match_dup 0) (pc)) (const_int MIN_BRANCH_OFFSET))
|
|
255 (le (minus (match_dup 0) (pc)) (const_int MAX_BRANCH_OFFSET)))
|
|
256 (const_int SHORT_BRANCH_LENGTH)
|
|
257 (const_int LONG_BRANCH_LENGTH)))
|
|
258 (set (attr "type")
|
|
259 (if_then_else
|
|
260 (eq_attr "length" "6")
|
|
261 (const_string "realBranch")
|
|
262 (const_string "unknown")))])
|
|
263
|
|
264 (define_insn "*fn_return"
|
|
265 [(return)
|
|
266 (use (reg:HI LINK_REGNUM))]
|
|
267 ""
|
|
268 "JR (R12)\t// Return to caller %>"
|
|
269 [(set_attr "length" "2")
|
|
270 (set_attr "type" "realBranch")
|
|
271 (set_attr "longConstant" "false")])
|
|
272
|
|
273 ;; Peephole either 2 LDWs or STWs into LDL/STL.
|
|
274 (define_peephole2
|
|
275 [(set (match_operand:HI 0 "register_operand" "")
|
|
276 (match_operand:HI 1 "memory_operand" ""))
|
|
277 (set (match_operand:HI 2 "register_operand" "")
|
|
278 (match_operand:HI 3 "memory_operand" ""))]
|
|
279 "ok_to_peephole_ldw(operands[0],operands[1],operands[2],operands[3])"
|
|
280 [(set (match_dup 4) (match_dup 5))]
|
|
281 "{
|
|
282 operands[4] = gen_min_reg(operands[0],operands[2]);
|
|
283 operands[5] = gen_SImode_mem(operands[1],operands[3]);
|
|
284 }")
|
|
285
|
|
286 (define_peephole2
|
|
287 [(set (match_operand:HI 0 "memory_operand" "")
|
|
288 (match_operand:HI 1 "register_operand" ""))
|
|
289 (set (match_operand:HI 2 "memory_operand" "")
|
|
290 (match_operand:HI 3 "register_operand" ""))]
|
|
291 "ok_to_peephole_stw(operands[0],operands[1],operands[2],operands[3])"
|
|
292 [(set (match_dup 4) (match_dup 5))]
|
|
293 "{
|
|
294 operands[4] = gen_SImode_mem(operands[0],operands[2]);
|
|
295 operands[5] = gen_min_reg(operands[1],operands[3]);
|
|
296 }")
|
|
297
|
|
298
|
|
299 ;; We have instructions like add,subtract,ior,and that set condition
|
|
300 ;; codes if they are executed on slot 0. If we have
|
|
301 ;; add a = b + c
|
|
302 ;; if (a!=0)
|
|
303 ;; {}
|
|
304 ;; We would have RTL sequence like
|
|
305 ;; add.# rb,rc,ra # will be replaced by slot no, after scheduling
|
|
306 ;; sub.0 ra,0,r15
|
|
307 ;; bnz
|
|
308 ;; Instead, we can just do
|
|
309 ;; add.0 rb,rc,ra
|
|
310 ;; bnz
|
|
311
|
|
312 (define_peephole2
|
|
313 [(parallel [(set (match_operand:HI 0 "register_operand" "")
|
|
314 (plus:HI (match_operand:HI 1 "register_operand" "")
|
|
315 (match_operand:HI 2 "general_operand" "")))
|
|
316 (clobber (reg:CC CC_REGNUM))])
|
|
317 (parallel [(set (pc)
|
|
318 (if_then_else
|
|
319 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
320 [(match_dup 0) (const_int 0)])
|
|
321 (label_ref (match_operand 6 "" ""))
|
|
322 (pc)))
|
|
323 (clobber (reg:CC CC_REGNUM))])]
|
|
324 ""
|
|
325 [(parallel [(set (match_dup 0)
|
|
326 (plus:HI (match_dup 1) (match_dup 2)))
|
|
327 (set (reg:CC CC_REGNUM)
|
|
328 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
329 (parallel [(set (pc)
|
|
330 (if_then_else
|
|
331 (match_op_dup:HI 3 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
332 (label_ref (match_dup 6))
|
|
333 (pc)))
|
|
334 (use (match_dup 7))])]
|
|
335 "{
|
|
336 operands[7] = GEN_INT(0);
|
|
337 }")
|
|
338
|
|
339 (define_peephole2
|
|
340 [(parallel [(set (match_operand:HI 0 "register_operand" "")
|
|
341 (plus:HI (match_operand:HI 1 "register_operand" "")
|
|
342 (match_operand:HI 2 "general_operand" "")))
|
|
343 (clobber (reg:CC CC_REGNUM))])
|
|
344 (set (reg:CC CC_REGNUM)
|
|
345 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
346 [(match_dup 0) (const_int 0)]))
|
|
347 (parallel [(set (pc)
|
|
348 (if_then_else
|
|
349 (match_operator 4 "comparison_operator"
|
|
350 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
351 (label_ref (match_operand 5 "" ""))
|
|
352 (pc)))
|
|
353 (use (match_operand:HI 6 "const_int_operand" ""))])]
|
|
354 ""
|
|
355 [(parallel [(set (match_dup 0)
|
|
356 (plus:HI (match_dup 1) (match_dup 2)))
|
|
357 (set (reg:CC CC_REGNUM)
|
|
358 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
359 (parallel [(set (pc)
|
|
360 (if_then_else (match_op_dup:HI 4 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
361 (label_ref (match_dup 5))
|
|
362 (pc)))
|
|
363 (use (match_dup 6))])]
|
|
364 "{
|
|
365 operands[7] = GEN_INT(0);
|
|
366 }")
|
|
367
|
|
368
|
|
369 ;; If peephole happens before the cbranch split
|
|
370
|
|
371 (define_peephole2
|
|
372 [(parallel [(set (match_operand:HI 0 "register_operand" "")
|
|
373 (minus:HI (match_operand:HI 1 "general_operand" "")
|
|
374 (match_operand:HI 2 "register_operand" "")))
|
|
375 (clobber (reg:CC CC_REGNUM))])
|
|
376 (parallel [(set (pc)
|
|
377 (if_then_else
|
|
378 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
379 [(match_dup 0) (const_int 0)])
|
|
380 (label_ref (match_operand 6 "" ""))
|
|
381 (pc)))
|
|
382 (clobber (reg:CC CC_REGNUM))])]
|
|
383 ""
|
|
384 [(parallel [(set (match_dup 0)
|
|
385 (minus:HI (match_dup 1) (match_dup 2)))
|
|
386 (set (reg:CC CC_REGNUM)
|
|
387 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
388 (parallel [(set (pc)
|
|
389 (if_then_else
|
|
390 (match_op_dup:HI 3 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
391 (label_ref (match_dup 6))
|
|
392 (pc)))
|
|
393 (use (match_dup 7))])]
|
|
394 "{
|
|
395 operands[7] = GEN_INT(0);
|
|
396 }")
|
|
397
|
|
398
|
|
399 ;; If peephole happens after the cbranch split
|
|
400
|
|
401 (define_peephole2
|
|
402 [(parallel [(set (match_operand:HI 0 "register_operand" "")
|
|
403 (minus:HI (match_operand:HI 1 "general_operand" "")
|
|
404 (match_operand:HI 2 "register_operand" "")))
|
|
405 (clobber (reg:CC CC_REGNUM))])
|
|
406 (set (reg:CC CC_REGNUM)
|
|
407 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
408 [(match_dup 0) (const_int 0)]))
|
|
409 (parallel [(set (pc)
|
|
410 (if_then_else
|
|
411 (match_operator 4 "comparison_operator"
|
|
412 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
413 (label_ref (match_operand 5 "" ""))
|
|
414 (pc)))
|
|
415 (use (match_operand:HI 6 "const_int_operand" ""))])]
|
|
416 ""
|
|
417 [(parallel [(set (match_dup 0)
|
|
418 (minus:HI (match_dup 1) (match_dup 2)))
|
|
419 (set (reg:CC CC_REGNUM)
|
|
420 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
421 (parallel [(set (pc)
|
|
422 (if_then_else (match_op_dup:HI 4 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
423 (label_ref (match_dup 5))
|
|
424 (pc)))
|
|
425 (use (match_dup 6))])]
|
|
426 "{
|
|
427 operands[7] = GEN_INT(0);
|
|
428 }")
|
|
429
|
|
430 ;; If peephole happens before the cbranch split
|
|
431
|
|
432 (define_peephole2
|
|
433 [(parallel[(set (match_operand:HI 0 "register_operand" "")
|
|
434 (and:HI (match_operand:HI 1 "register_operand" "")
|
|
435 (match_operand:HI 2 "general_operand" "")))
|
|
436 (clobber (reg:CC CC_REGNUM))])
|
|
437 (parallel [(set (pc)
|
|
438 (if_then_else
|
|
439 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
440 [(match_dup 0) (const_int 0)])
|
|
441 (label_ref (match_operand 6 "" ""))
|
|
442 (pc)))
|
|
443 (clobber (reg:CC CC_REGNUM))])]
|
|
444 ""
|
|
445 [(parallel [(set (match_dup 0)
|
|
446 (and:HI (match_dup 1) (match_dup 2)))
|
|
447 (set (reg:CC CC_REGNUM)
|
|
448 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
449 (parallel [(set (pc)
|
|
450 (if_then_else
|
|
451 (match_op_dup:HI 3 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
452 (label_ref (match_dup 6))
|
|
453 (pc)))
|
|
454 (use (match_dup 7))])]
|
|
455 "{
|
|
456 operands[7] = GEN_INT(0);
|
|
457 }")
|
|
458
|
|
459 (define_peephole2
|
|
460 [(parallel[(set (match_operand:HI 0 "register_operand" "")
|
|
461 (and:HI (match_operand:HI 1 "register_operand" "")
|
|
462 (match_operand:HI 2 "general_operand" "")))
|
|
463 (clobber (reg:CC CC_REGNUM))])
|
|
464 (set (reg:CC CC_REGNUM)
|
|
465 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
466 [(match_dup 0) (const_int 0)]))
|
|
467 (parallel [(set (pc)
|
|
468 (if_then_else
|
|
469 (match_operator 4 "comparison_operator"
|
|
470 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
471 (label_ref (match_operand 5 "" ""))
|
|
472 (pc)))
|
|
473 (use (match_operand:HI 6 "const_int_operand" ""))])]
|
|
474 ""
|
|
475 [(parallel [(set (match_dup 0)
|
|
476 (and:HI (match_dup 1) (match_dup 2)))
|
|
477 (set (reg:CC CC_REGNUM)
|
|
478 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
479 (parallel [(set (pc)
|
|
480 (if_then_else (match_op_dup:HI 4 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
481 (label_ref (match_dup 5))
|
|
482 (pc)))
|
|
483 (use (match_dup 6))])]
|
|
484 "{
|
|
485 operands[7] = GEN_INT(0);
|
|
486 }")
|
|
487
|
|
488 ;; If peephole happens before the cbranch split
|
|
489
|
|
490 (define_peephole2
|
|
491 [(parallel[(set (match_operand:HI 0 "register_operand" "")
|
|
492 (ior:HI (match_operand:HI 1 "register_operand" "")
|
|
493 (match_operand:HI 2 "general_operand" "")))
|
|
494 (clobber (reg:CC CC_REGNUM))])
|
|
495 (parallel [(set (pc)
|
|
496 (if_then_else
|
|
497 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
498 [(match_dup 0) (const_int 0)])
|
|
499 (label_ref (match_operand 6 "" ""))
|
|
500 (pc)))
|
|
501 (clobber (reg:CC CC_REGNUM))])]
|
|
502 ""
|
|
503 [(parallel [(set (match_dup 0)
|
|
504 (ior:HI (match_dup 1) (match_dup 2)))
|
|
505 (set (reg:CC CC_REGNUM)
|
|
506 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
507 (parallel [(set (pc)
|
|
508 (if_then_else
|
|
509 (match_op_dup:HI 3 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
510 (label_ref (match_dup 6))
|
|
511 (pc)))
|
|
512 (use (match_dup 7))])]
|
|
513 "{
|
|
514 operands[7] = GEN_INT(0);
|
|
515 }")
|
|
516
|
|
517 (define_peephole2
|
|
518 [(parallel[(set (match_operand:HI 0 "register_operand" "")
|
|
519 (ior:HI (match_operand:HI 1 "register_operand" "")
|
|
520 (match_operand:HI 2 "general_operand" "")))
|
|
521 (clobber (reg:CC CC_REGNUM))])
|
|
522 (set (reg:CC CC_REGNUM)
|
|
523 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
524 [(match_dup 0) (const_int 0)]))
|
|
525 (parallel [(set (pc)
|
|
526 (if_then_else
|
|
527 (match_operator 4 "comparison_operator"
|
|
528 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
529 (label_ref (match_operand 5 "" ""))
|
|
530 (pc)))
|
|
531 (use (match_operand:HI 6 "const_int_operand" ""))])]
|
|
532 ""
|
|
533 [(parallel [(set (match_dup 0)
|
|
534 (ior:HI (match_dup 1) (match_dup 2)))
|
|
535 (set (reg:CC CC_REGNUM)
|
|
536 (match_op_dup 3 [(const_int 0) (const_int 0)]))])
|
|
537 (parallel [(set (pc)
|
|
538 (if_then_else (match_op_dup:HI 4 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
539 (label_ref (match_dup 5))
|
|
540 (pc)))
|
|
541 (use (match_dup 6))])]
|
|
542 "{
|
|
543 operands[7] = GEN_INT(0);
|
|
544 }")
|
|
545
|
|
546 ;; Conditional branch (HI). This is split into separate compare and
|
|
547 ;; branch instructions if scheduling is enabled. The branch
|
|
548 ;; instruction is supplied with the type of comparison on which the
|
|
549 ;; branch should occur.
|
|
550
|
|
551 (define_insn_and_split "cbranchhi4"
|
|
552 [(set (pc)
|
|
553 (if_then_else
|
|
554 (match_operator:CC 0 "comparison_operator"
|
|
555 [(match_operand:HI 1 "register_operand" "r")
|
|
556 (match_operand:HI 2 "picochip_comparison_operand" "ri")])
|
|
557 (label_ref (match_operand 3 "" ""))
|
|
558 (pc)))
|
|
559 (clobber (reg:CC CC_REGNUM))]
|
|
560 ""
|
|
561 "* return picochip_output_cbranch(operands);"
|
|
562 "reload_completed
|
|
563 && (picochip_schedule_type != DFA_TYPE_NONE || flag_delayed_branch)"
|
|
564 [(set (reg:CC CC_REGNUM) (match_dup 0))
|
|
565 (parallel [(set (pc)
|
|
566 (if_then_else (match_op_dup:HI 0 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
567 (label_ref (match_dup 3))
|
|
568 (pc)))
|
|
569 (use (match_dup 4))])]
|
|
570 "{
|
|
571 operands[4] = GEN_INT(GET_CODE(operands[0]));
|
|
572 }")
|
|
573
|
|
574 ;; The only difference between this and the next pattern is that the next pattern
|
|
575 ;; might introduce subtracts whose first operand is a constant. This would have to
|
|
576 ;; be a longConstant. But, we know that such a situation wouldnt arise for supported
|
|
577 ;; comparison operator and hence this pattern assumes that the second constraint combo
|
|
578 ;; would still generate a normal instruction.
|
|
579
|
|
580 (define_insn "*supported_compare"
|
|
581 [(set (reg:CC CC_REGNUM)
|
|
582 (match_operator:CC 0 "picochip_supported_comparison_operator"
|
|
583 [(match_operand:HI 1 "register_operand" "r,r,r")
|
|
584 (match_operand:HI 2 "picochip_comparison_operand" "r,J,i")]))]
|
|
585 ""
|
|
586 "* return picochip_output_compare(operands);"
|
|
587 [; Must be picoAlu because it sets the condition flags.
|
|
588 (set_attr "type" "picoAlu,picoAlu,picoAlu")
|
|
589 (set_attr "longConstant" "false,false,true")
|
|
590 (set_attr "length" "2,2,4")
|
|
591 ])
|
|
592
|
|
593 (define_insn "*compare"
|
|
594 [(set (reg:CC CC_REGNUM)
|
|
595 (match_operator:CC 0 "comparison_operator"
|
|
596 [(match_operand:HI 1 "register_operand" "r,r,r")
|
|
597 (match_operand:HI 2 "picochip_comparison_operand" "r,M,i")]))]
|
|
598 ""
|
|
599 "* return picochip_output_compare(operands);"
|
|
600 [; Must be picoAlu because it sets the condition flags.
|
|
601 (set_attr "type" "picoAlu,picoAlu,picoAlu")
|
|
602 (set_attr "longConstant" "false,true,true")
|
|
603 (set_attr "length" "2,4,4")
|
|
604 ])
|
|
605
|
|
606 ; Match a branch instruction, created from a tstport/cbranch split.
|
|
607 ; We use a "use" clause so GCC doesnt try to use this pattern generally.
|
|
608 (define_insn "*branch"
|
|
609 [(set (pc)
|
|
610 (if_then_else
|
|
611 (match_operator 2 "comparison_operator"
|
|
612 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
613 (label_ref (match_operand 0 "" ""))
|
|
614 (pc)))
|
|
615 (use (match_operand:HI 1 "const_int_operand" ""))]
|
|
616 ""
|
|
617 "* return picochip_output_branch(operands, insn);"
|
|
618 [(set (attr "length")
|
|
619 (if_then_else
|
|
620 (and (ge (minus (match_dup 0) (pc)) (const_int MIN_BRANCH_OFFSET))
|
|
621 (le (minus (match_dup 0) (pc)) (const_int MAX_BRANCH_OFFSET)))
|
|
622 (const_int SHORT_BRANCH_LENGTH)
|
|
623 (const_int LONG_BRANCH_LENGTH)))
|
|
624 (set (attr "type")
|
|
625 (if_then_else
|
|
626 (eq_attr "length" "6")
|
|
627 (const_string "realBranch")
|
|
628 (const_string "unknown")))])
|
|
629
|
|
630 ;; If a movqi is used which accesses memory on a machine which doesn't
|
|
631 ;; have byte addressing, synthesise the instruction using word load/store
|
|
632 ;; operations. The movqi's that are required during reload phase are
|
|
633 ;; handled using reload_inqi/reload_outqi.
|
|
634
|
|
635 (define_expand "movqi"
|
|
636 [(set (match_operand:QI 0 "nonimmediate_operand" "")
|
|
637 (match_operand:QI 1 "general_operand" ""))]
|
|
638 ""
|
|
639 {
|
|
640
|
|
641 if (!reload_completed &&
|
|
642 !TARGET_HAS_BYTE_ACCESS &&
|
|
643 (MEM == GET_CODE(operands[0]) || MEM == GET_CODE(operands[1])))
|
|
644 {
|
|
645 rtx address;
|
|
646 rtx wordAddress;
|
|
647 rtx const1;
|
|
648 rtx shiftVal;
|
|
649 rtx loadedValue;
|
|
650 rtx addressMask;
|
|
651
|
|
652 warn_of_byte_access();
|
|
653
|
|
654 /* Load the constant 1 into a register. */
|
|
655 const1 = gen_reg_rtx(HImode);
|
|
656 emit_insn(gen_rtx_SET(HImode, const1, GEN_INT(1)));
|
|
657
|
|
658 /* Load the address mask with the bitwise complement of 1. */
|
|
659 addressMask = gen_reg_rtx(HImode);
|
|
660 emit_insn(gen_rtx_SET(HImode, addressMask, GEN_INT(-2)));
|
|
661
|
|
662 /* Handle loads first, in case we are dealing with a mem := mem
|
|
663 * instruction. */
|
|
664 if (MEM == GET_CODE(operands[1]))
|
|
665 {
|
|
666 /* Loads work as follows. The entire word containing the desired byte
|
|
667 * is loaded. The bottom bit of the address indicates which
|
|
668 * byte is required. The desired byte is moved into the most
|
|
669 * significant byte, and then an arithmetic shift right
|
|
670 * invoked to achieve sign extension. The desired byte is
|
|
671 * moved to the MSB by XOR'ing the bottom address bit by 1,
|
|
672 * multiplying the result by 8, and then shifting left by
|
|
673 * that amount. Note that shifts only operate on the bottom
|
|
674 * 4-bits of the source offset, so although the XOR may
|
|
675 * produce a value which has its upper bits set, only bit 4
|
|
676 * (i.e., the inverted, shifted bottom address bit) actually
|
|
677 * gets used.
|
|
678 */
|
|
679
|
|
680 /* Ensure the address is in a register. */
|
|
681 address = gen_reg_rtx(HImode);
|
|
682 emit_insn(gen_rtx_SET(HImode, address, XEXP(operands[1], 0)));
|
|
683
|
|
684 /* Compute the word address by masking out the bottom bit. */
|
|
685 wordAddress = gen_reg_rtx(HImode);
|
|
686 emit_insn(gen_andhi3(wordAddress, address, addressMask));
|
|
687
|
|
688 /* Compute the shift value. This is the bottom address bit,
|
|
689 * inverted, and multiplied by 8. */
|
|
690 shiftVal = gen_reg_rtx(HImode);
|
|
691 emit_insn(gen_xorhi3(shiftVal, address, const1));
|
|
692 emit_insn(gen_ashlhi3(shiftVal, shiftVal, GEN_INT(3)));
|
|
693
|
|
694 /* Emit the memory load. */
|
|
695 loadedValue = gen_reg_rtx(HImode);
|
|
696 emit_insn(gen_rtx_SET(HImode, loadedValue, gen_rtx_MEM(HImode, wordAddress)));
|
|
697
|
|
698 /* Shift the desired byte to the most significant byte. */
|
|
699 rtx topByteValue = gen_reg_rtx (HImode);
|
|
700 emit_insn (gen_ashlhi3 (topByteValue, loadedValue, shiftVal));
|
|
701
|
|
702 /* Sign extend the top-byte back into the bottom byte. */
|
|
703 rtx signExtendedValue = gen_reg_rtx(HImode);
|
|
704 emit_insn(gen_ashrhi3(signExtendedValue, topByteValue, GEN_INT(8)));
|
|
705
|
|
706 /* Final extraction of QI mode register. */
|
|
707 operands[1] = gen_rtx_SUBREG(QImode, signExtendedValue, 0);
|
|
708
|
|
709 }
|
|
710
|
|
711 if (MEM == GET_CODE(operands[0]) && GET_CODE(operands[1]) != MEM)
|
|
712 {
|
|
713 rtx zeroingByteMask;
|
|
714 rtx temp;
|
|
715 rtx tempQiMode;
|
|
716 rtx tempHiMode;
|
|
717
|
|
718 /* Get the address. */
|
|
719 address = gen_reg_rtx(HImode);
|
|
720 emit_insn(gen_rtx_SET(HImode, address, XEXP(operands[0], 0)));
|
|
721
|
|
722 /* Compute the word aligned address. */
|
|
723 wordAddress = gen_reg_rtx(HImode);
|
|
724 emit_insn(gen_andhi3(wordAddress, address, addressMask));
|
|
725
|
|
726 /* Compute the shift value. */
|
|
727 shiftVal = gen_reg_rtx(HImode);
|
|
728 emit_insn(gen_andhi3(shiftVal, address, const1));
|
|
729 emit_insn(gen_ashlhi3(shiftVal, shiftVal, GEN_INT(3)));
|
|
730
|
|
731 /* Emit the memory load. */
|
|
732 loadedValue = gen_reg_rtx(HImode);
|
|
733 emit_insn(gen_rtx_SET(HImode, loadedValue, gen_rtx_MEM(HImode, wordAddress)));
|
|
734
|
|
735 /* Zero out the destination bits by AND'ing with 0xFF00
|
|
736 * shifted appropriately. */
|
|
737 zeroingByteMask = gen_reg_rtx(HImode);
|
|
738 emit_insn(gen_rtx_SET(HImode, zeroingByteMask, GEN_INT(-256)));
|
|
739 emit_insn(gen_lshrhi3(zeroingByteMask, zeroingByteMask, shiftVal));
|
|
740 emit_insn(gen_andhi3(loadedValue, loadedValue, zeroingByteMask));
|
|
741
|
|
742 /* Grab the incoming QI register, and ensure that the top bits
|
|
743 * are zeroed out. This is because the register may be
|
|
744 * storing a signed value, in which case the top-bits will be
|
|
745 * sign bits. These must be removed to ensure that the
|
|
746 * read-modify-write (which uses an OR) doesn't pick up those
|
|
747 * bits, instead of the original memory value which is being
|
|
748 * modified.
|
|
749 */
|
|
750 /*if (register_operand(operands[1],QImode))
|
|
751 {
|
|
752 tempHiMode = XEXP(operands[1], 0);
|
|
753 }
|
|
754 else
|
|
755 {
|
|
756 tempHiMode = operands[1];
|
|
757 }*/
|
|
758 //tempHiMode = force_reg(QImode, operands[1]);
|
|
759 tempHiMode = simplify_gen_subreg(HImode, operands[1], QImode, 0);
|
|
760 temp = gen_reg_rtx(HImode);
|
|
761 emit_insn(gen_rtx_SET(HImode, temp, tempHiMode));
|
|
762 rtx lsbByteMask = gen_reg_rtx (HImode);
|
|
763 emit_insn (gen_rtx_SET (HImode, lsbByteMask, GEN_INT (0xFF)));
|
|
764 emit_insn (gen_andhi3 (temp, temp, lsbByteMask));
|
|
765
|
|
766 /* Shift the incoming byte value by the appropriate amount,
|
|
767 * and OR into the load value. */
|
|
768 emit_insn(gen_ashlhi3(temp, temp, shiftVal));
|
|
769 emit_insn(gen_iorhi3(loadedValue, loadedValue, temp));
|
|
770
|
|
771 /* Rewrite the original assignment, to assign the new value
|
|
772 * to the word address. */
|
|
773 operands[0] = gen_rtx_MEM(HImode, wordAddress);
|
|
774 operands[1] = loadedValue;
|
|
775
|
|
776 }
|
|
777
|
|
778 }
|
|
779 })
|
|
780
|
|
781 (define_insn "*movqi_sign_extend"
|
|
782 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
783 (sign_extend:HI (match_operand:QI 1 "memory_operand" "a,m")))]
|
|
784 "TARGET_HAS_BYTE_ACCESS"
|
|
785 "@
|
|
786 LDB (%a1),%0\t\t// %0 = Mem(%a1)
|
|
787 LDB %a1,%0\t\t// %0 = Mem(%M1{byte})"
|
|
788 [(set_attr "type" "mem,mem")
|
|
789 (set_attr "longConstant" "true,false")
|
|
790 (set_attr "length" "4,4")])
|
|
791
|
|
792 ;; movqi instructions for machines with and without byte access.
|
|
793 (define_insn "*movqi_byte"
|
|
794 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,r,r,a,m")
|
|
795 (match_operand:QI 1 "general_operand" "r,a,m,I,i,r,r"))]
|
|
796 "TARGET_HAS_BYTE_ACCESS"
|
|
797 "@
|
|
798 COPY.%# %1, %0\t// %0 := %1
|
|
799 LDB (%a1),%0\t\t// %0 = Mem(%a1)
|
|
800 LDB %a1,%0\t\t// %0 = Mem(%M1{byte})
|
|
801 COPY.%# %1,%0\t\t// %0 := #%1 (QI) (short constant)
|
|
802 COPY.%# %1,%0\t\t// %0 := #%1 (QI) (long constant)
|
|
803 STB %1,(%a0)\t\t// Mem(%a0) := %1
|
|
804 STB %1,%a0\t\t// Mem(%M0{byte}) := %1"
|
|
805 [(set_attr "type" "basicAlu,mem,mem,basicAlu,basicAlu,mem,mem")
|
|
806 (set_attr "longConstant" "false,true,false,false,true,true,false")
|
|
807 (set_attr "length" "2,4,4,2,4,4,4")])
|
|
808
|
|
809 ;; Machines which don't have byte access can copy registers, and load
|
|
810 ;; constants, but can't access memory. The define_expand for movqi
|
|
811 ;; should already have rewritten memory accesses using word
|
|
812 ;; operations. The exception is qi reloads, which are handled using
|
|
813 ;; the reload_? patterns.
|
|
814 (define_insn "*movqi_nobyte"
|
|
815 [(set (match_operand:QI 0 "register_operand" "=r,r")
|
|
816 (match_operand:QI 1 "picochip_register_or_immediate_operand" "r,i"))]
|
|
817 "!TARGET_HAS_BYTE_ACCESS"
|
|
818 "@
|
|
819 COPY.%# %1,%0\t// %0 := %1
|
|
820 COPY.%# %1,%0\t\t// %0 := #%1 (QI)")
|
|
821
|
|
822 (define_insn "movhi"
|
|
823 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,a,m,r,r")
|
|
824 (match_operand:HI 1 "general_operand" "r,a,m,r,r,I,i"))]
|
|
825 ""
|
|
826 "@
|
|
827 COPY.%# %1,%0\t\t// %0 := %1
|
|
828 LDW (%a1),%0\t\t// %0 := Mem(%a1)
|
|
829 LDW %a1,%0\t\t// %0 = Mem(%M1{byte})
|
|
830 STW %1,(%a0)\t\t// Mem(%a0) := %1
|
|
831 STW %1,%a0\t\t// Mem(%M0{byte}) := %1
|
|
832 COPY.%# %1,%0\t// %0 := %1 (short constant)
|
|
833 COPY.%# %1,%0\t// %0 := %1 (long constant)"
|
|
834 [(set_attr "type" "basicAlu,mem,mem,mem,mem,basicAlu,basicAlu")
|
|
835 (set_attr "longConstant" "false,true,false,true,false,false,true")
|
|
836 (set_attr "length" "2,4,4,4,4,2,4")])
|
|
837
|
|
838 (define_insn "movsi"
|
|
839 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,a,m")
|
|
840 (match_operand:SI 1 "general_operand" "r,a,m,i,r,r"))]
|
|
841 ""
|
|
842 "@
|
|
843 // %R0 := %R1 (SI)\n\tCOPY.%# %L1,%L0 %| COPY.1 %U1,%U0
|
|
844 LDL (%a1),%R0\t\t// %R0 = Mem(%a1)
|
|
845 LDL %a1,%R0\t\t// %R0 = Mem(%M1{byte})
|
|
846 // %R0 := #%1 (SI)\n\tCOPY.%# %L1,%L0 %| COPY.%# %U1,%U0
|
|
847 STL %R1,(%a0)\t\t// Mem(%a0) := %R1
|
|
848 STL %R1,%a0\t\t// Mem(%M0{byte}) := %R1"
|
|
849 [(set_attr "type" "unknown,mem,mem,unknown,mem,mem")
|
|
850 (set_attr "longConstant" "false,true,false,true,false,false")
|
|
851 (set_attr "length" "4,4,4,6,4,4")])
|
|
852
|
|
853 ; Split an SI mode register copy into separate HI mode copies, which
|
|
854 ; can be VLIW'd with other instructions. Only split the instruction
|
|
855 ; when VLIW scheduling is enabled. Splitting the instruction saves
|
|
856 ; some code space.
|
|
857 ;
|
|
858 ; This is predicated in reload_completed. This ensures that the
|
|
859 ; instructions aren't broken up too early which can result in the
|
|
860 ; SImode code being converted into inefficient HI mode code.
|
|
861
|
|
862 (define_split
|
|
863 [(set (match_operand:SI 0 "register_operand" "")
|
|
864 (match_operand:SI 1 "register_operand" ""))]
|
|
865 "reload_completed && picochip_schedule_type == DFA_TYPE_SPEED"
|
|
866 [(set (match_dup 2) (match_dup 3))
|
|
867 (set (match_dup 4) (match_dup 5))]
|
|
868 "{
|
|
869 operands[2] = gen_lowpart (HImode, operands[0]);
|
|
870 operands[3] = gen_lowpart (HImode, operands[1]);
|
|
871 operands[4] = gen_highpart (HImode, operands[0]);
|
|
872 operands[5] = gen_highpart (HImode, operands[1]);
|
|
873 }")
|
|
874
|
|
875 ; SI Mode split for load constant.
|
|
876 (define_split
|
|
877 [(set (match_operand:SI 0 "register_operand" "")
|
|
878 (match_operand:SI 1 "const_int_operand" ""))]
|
|
879 ""
|
|
880 [(set (match_dup 2) (match_dup 3))
|
|
881 (set (match_dup 4) (match_dup 5))]
|
|
882 "{
|
|
883 operands[2] = gen_lowpart (HImode, operands[0]);
|
|
884 operands[3] = picochip_get_low_const(operands[1]);
|
|
885 operands[4] = gen_highpart (HImode, operands[0]);
|
|
886 operands[5] = picochip_get_high_const(operands[1]);
|
|
887 }")
|
|
888
|
|
889 (define_insn "movsf"
|
|
890 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,m")
|
|
891 (match_operand:SF 1 "general_operand" "r,m,i,r"))]
|
|
892 ""
|
|
893 "@
|
|
894 // %R0 := %R1 (SF)\n\tCOPY.%# %L1,%L0 %| COPY.1 %U1,%U0
|
|
895 LDL %a1,%R0\t\t// %R0 :={SF} Mem(%M1{byte})
|
|
896 // %R0 := #%1 (SF)\n\tCOPY.%# %L1,%L0\n\tCOPY.%# %U1,%U0
|
|
897 STL %R1,%a0\t\t// Mem(%M0{byte}) :={SF} %R1")
|
|
898
|
|
899 ;;===========================================================================
|
|
900 ;; NOP
|
|
901 ;;===========================================================================
|
|
902
|
|
903 ;; No-operation (NOP)
|
|
904 (define_insn "nop"
|
|
905 [(const_int 0)]
|
|
906 ""
|
|
907 "NOP\t// nop"
|
|
908 [(set_attr "length" "1")])
|
|
909
|
|
910 ;;===========================================================================
|
|
911 ;; Function Calls. Define expands are used to ensure that the correct
|
|
912 ;; type of pattern is emitted, and then the define_insn's match the
|
|
913 ;; pattern using the correct types.
|
|
914 ;;
|
|
915 ;; Note: The comments output as part of these instructions are detected by
|
|
916 ;; the linker. Don't change the comments!
|
|
917 ;;===========================================================================
|
|
918
|
|
919 (define_expand "call"
|
|
920 [(parallel [(call (match_operand:QI 0 "memory_operand" "")
|
|
921 (match_operand 1 "const_int_operand" ""))
|
|
922 (clobber (reg:HI LINK_REGNUM))])]
|
|
923 ""
|
|
924 "")
|
|
925
|
|
926 (define_insn "call_for_divmod"
|
|
927 [(call (match_operand:QI 0 "memory_operand" "")
|
|
928 (match_operand 1 "const_int_operand" ""))]
|
|
929 ""
|
|
930 "JL (%M0)\t// fn_call %M0%>"
|
|
931 [(set_attr "length" "4")
|
|
932 (set_attr "type" "realBranch")
|
|
933 (set_attr "longConstant" "true")])
|
|
934
|
|
935 (define_insn "*call_using_symbol"
|
|
936 [(call (mem:QI (match_operand:HI 0 "immediate_operand" "i"))
|
|
937 (match_operand 1 "const_int_operand" ""))
|
|
938 (clobber (reg:HI LINK_REGNUM))]
|
|
939 ""
|
|
940 "JL (%M0)\t// fn_call %M0%>"
|
|
941 [(set_attr "length" "4")
|
|
942 (set_attr "type" "realBranch")
|
|
943 (set_attr "longConstant" "true")])
|
|
944
|
|
945 (define_insn "*call_using_register"
|
|
946 [(call (mem:QI (match_operand:HI 0 "register_operand" "r"))
|
|
947 (match_operand 1 "const_int_operand" ""))
|
|
948 (clobber (reg:HI LINK_REGNUM))]
|
|
949 ""
|
|
950 "JL (%r0)\t// fn_call_unknown %r0%>"
|
|
951 [(set_attr "length" "2")
|
|
952 (set_attr "type" "realBranch")
|
|
953 (set_attr "longConstant" "false")])
|
|
954
|
|
955 (define_expand "call_value"
|
|
956 [(parallel [(set (match_operand:HI 0 "" "")
|
|
957 (call:HI (match_operand:QI 1 "memory_operand" "g")
|
|
958 (match_operand 2 "const_int_operand" "")))
|
|
959 (clobber (reg:HI LINK_REGNUM))])]
|
|
960 ""
|
|
961 "")
|
|
962
|
|
963 (define_insn "*call_value_using_symbol"
|
|
964 [(set (match_operand:HI 0 "" "")
|
|
965 (call:HI (mem:QI (match_operand:HI 1 "immediate_operand" "i"))
|
|
966 (match_operand 2 "const_int_operand" "")))
|
|
967 (clobber (reg:HI LINK_REGNUM))]
|
|
968 ""
|
|
969 "JL (%M1)\t// fn_call %M1 (value return)%>"
|
|
970 [(set_attr "length" "4")
|
|
971 (set_attr "type" "realBranch")
|
|
972 (set_attr "longConstant" "true")])
|
|
973
|
|
974 (define_insn "*call_value_using_register"
|
|
975 [(set (match_operand:HI 0 "" "")
|
|
976 (call:HI (mem:QI (match_operand:HI 1 "register_operand" "r"))
|
|
977 (match_operand 2 "const_int_operand" "")))
|
|
978 (clobber (reg:HI LINK_REGNUM))]
|
|
979 ""
|
|
980 "JL (%r1)// fn_call_unknown %r1 (value return)%>"
|
|
981 [(set_attr "length" "2")
|
|
982 (set_attr "type" "realBranch")
|
|
983 (set_attr "longConstant" "false")])
|
|
984
|
|
985 ;;===========================================================================
|
|
986 ;; Addition
|
|
987 ;;===========================================================================
|
|
988
|
|
989 ;; Note that the addition of a negative value is transformed into the
|
|
990 ;; subtraction of a positive value, so that the add/sub immediate slot
|
|
991 ;; can make better use of the 4-bit range.
|
|
992
|
|
993 (define_insn "addhi3"
|
|
994 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
|
|
995 (plus:HI (match_operand:HI 1 "register_operand" "r,r,r,r")
|
|
996 (match_operand:HI 2 "general_operand" "r,M,n,i")))
|
|
997 (clobber (reg:CC CC_REGNUM))]
|
|
998 ""
|
|
999 { if (CONST_INT == GET_CODE(operands[2]) &&
|
|
1000 INTVAL(operands[2]) > -16 &&
|
|
1001 INTVAL(operands[2]) < 0)
|
|
1002 return "SUB.%# %1,-(%2),%0\t// %0 := %1 + %2 (HI)";
|
|
1003 else
|
|
1004 return "ADD.%# %1,%2,%0\t// %0 := %1 + %2 (HI)";
|
|
1005 }
|
|
1006 [(set_attr "type" "basicAlu,basicAlu,basicAlu,basicAlu")
|
|
1007 (set_attr "longConstant" "false,false,true,true")
|
|
1008 (set_attr "length" "2,2,4,4")]
|
|
1009 )
|
|
1010
|
|
1011
|
|
1012 ;; If we peepholed the compare instruction out, we need to make sure the add
|
|
1013 ;; goes in slot 0. This pattern is just to accomplish that.
|
|
1014
|
|
1015 (define_insn "addhi3_with_use_clause"
|
|
1016 [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
|
|
1017 (plus:HI (match_operand:HI 1 "register_operand" "r,r,r,r")
|
|
1018 (match_operand:HI 2 "general_operand" "r,M,n,i")))
|
|
1019 (set (reg:CC CC_REGNUM)
|
|
1020 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
1021 [(const_int 0)
|
|
1022 (const_int 0)]))]
|
|
1023 ""
|
|
1024 { if (CONST_INT == GET_CODE(operands[2]) &&
|
|
1025 INTVAL(operands[2]) > -16 &&
|
|
1026 INTVAL(operands[2]) < 0)
|
|
1027 return "SUB.0 %1,-(%2),%0\t// %0 := %1 + %2 (HI)";
|
|
1028 else
|
|
1029 return "ADD.0 %1,%2,%0\t// %0 := %1 + %2 (HI)";
|
|
1030 }
|
|
1031 [(set_attr "type" "picoAlu,picoAlu,picoAlu,picoAlu")
|
|
1032 (set_attr "longConstant" "false,false,true,true")
|
|
1033 (set_attr "length" "2,2,4,4")]
|
|
1034 )
|
|
1035
|
|
1036 ;; Match an addition in which the first operand has been shifted
|
|
1037 ;; (e.g., the comms array functions can emit such instructions).
|
|
1038 (define_insn "*addWith1stOpShift"
|
|
1039 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1040 (plus:HI (ashift:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1041 (match_operand:HI 2 "const_int_operand" ""))
|
|
1042 (match_operand:HI 3 "immediate_operand" "I,i")))
|
|
1043 (clobber (reg:CC CC_REGNUM))]
|
|
1044 ""
|
|
1045 "ADD.0 [LSL %1,%2],%3,%0\t// %0 := (%1 << %2) + %3"
|
|
1046 [(set_attr "type" "picoAlu,picoAlu")
|
|
1047 (set_attr "longConstant" "false,true")])
|
|
1048
|
|
1049 (define_insn_and_split "addsi3"
|
|
1050 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
1051 (plus:SI (match_operand:SI 1 "register_operand" "r,r")
|
|
1052 (match_operand:SI 2 "general_operand" "r,i")))
|
|
1053 (clobber (reg:CC CC_REGNUM))]
|
|
1054 ""
|
|
1055 "// %0 := %1 + %2 (SI)\n\tADD.0 %L1,%L2,%L0\n\tADDC.0 %U1,%U2,%U0"
|
|
1056 "reload_completed && picochip_schedule_type != DFA_TYPE_NONE"
|
|
1057 [(match_dup 4)
|
|
1058 (match_dup 5)]
|
|
1059 "
|
|
1060 {
|
|
1061 rtx op0_high = gen_highpart (HImode, operands[0]);
|
|
1062 rtx op1_high = gen_highpart (HImode, operands[1]);
|
|
1063 rtx op0_low = gen_lowpart (HImode, operands[0]);
|
|
1064 rtx op1_low = gen_lowpart (HImode, operands[1]);
|
|
1065 rtx op2_high, op2_low;
|
|
1066
|
|
1067 if (CONST_INT == GET_CODE(operands[2]))
|
|
1068 {
|
|
1069 op2_high = picochip_get_high_const(operands[2]);
|
|
1070 op2_low = picochip_get_low_const(operands[2]);
|
|
1071 } else {
|
|
1072 op2_high = gen_highpart (HImode, operands[2]);
|
|
1073 op2_low = gen_lowpart (HImode, operands[2]);
|
|
1074 }
|
|
1075
|
|
1076 operands[4] = gen_add_multi_lower (op0_low, op1_low, op2_low);
|
|
1077 operands[5] = gen_add_multi_upper (op0_high, op1_high, op2_high);
|
|
1078
|
|
1079 }")
|
|
1080
|
|
1081 ;; Perform the lowest part of a multi-part addition (SI/DI). This sets
|
|
1082 ;; the flags, so is an picoAlu instruction (we could use a
|
|
1083 ;; conventional addhi, but the addhi is better off being a treated as
|
|
1084 ;; a basicAlu instruction, rather than a picoAlu instruction).
|
|
1085 (define_insn "add_multi_lower"
|
|
1086 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
|
|
1087 (plus:HI (match_operand:HI 1 "register_operand" "r,r,r")
|
|
1088 (match_operand:HI 2 "general_operand" "r,M,i")))
|
|
1089 (set (reg:CC CC_REGNUM)
|
|
1090 (compare:CC (plus:HI (match_dup 1)
|
|
1091 (match_dup 2))
|
|
1092 (const_int 0)))]
|
|
1093 ""
|
|
1094 { if (CONST_INT == GET_CODE(operands[2]) &&
|
|
1095 INTVAL(operands[2]) > -16 &&
|
|
1096 INTVAL(operands[2]) < 0)
|
|
1097 return "SUB.%# %1,-(%2),%0\t// %0+carry := %1 + %2 (low multi-part)";
|
|
1098 else
|
|
1099 return "ADD.%# %1,%2,%0\t// %0+carry := %1 + %2 (low multi-part)";
|
|
1100 }
|
|
1101 [(set_attr "type" "picoAlu,picoAlu,picoAlu")
|
|
1102 (set_attr "longConstant" "false,false,true")
|
|
1103 (set_attr "length" "2,2,4")])
|
|
1104
|
|
1105 ;; Perform the central part of a multi-part addition (DI). This uses
|
|
1106 ;; the CC register, and also sets the CC register, so needs to be
|
|
1107 ;; placed in the first ALU slot. Note that the ADDC must
|
|
1108 ;; use the long constant to represent immediates.
|
|
1109 (define_insn "add_multi_mid"
|
|
1110 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1111 (plus:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1112 (plus:HI (match_operand:HI 2 "general_operand" "r,i")
|
|
1113 (reg:CC CC_REGNUM))))
|
|
1114 (set (reg:CC CC_REGNUM)
|
|
1115 (compare:CC (plus:HI (match_dup 1)
|
|
1116 (match_dup 2))
|
|
1117 (const_int 0)))]
|
|
1118 ""
|
|
1119 "ADDC.%# %1,%2,%0\t// %0+carry := carry + %1 + %2 (mid multi-part)"
|
|
1120 [(set_attr "type" "picoAlu,picoAlu")
|
|
1121 (set_attr "longConstant" "false,true")
|
|
1122 (set_attr "length" "2,4")])
|
|
1123
|
|
1124 ;; Perform the highest part of a multi-part addition (SI/DI). This
|
|
1125 ;; uses the CC register, but doesn't require any registers to be set,
|
|
1126 ;; so may be scheduled in either of the ALU's. Note that the ADDC must
|
|
1127 ;; use the long constant to represent immediates.
|
|
1128 (define_insn "add_multi_upper"
|
|
1129 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1130 (plus:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1131 (plus:HI (match_operand:HI 2 "general_operand" "r,i")
|
|
1132 (reg:CC CC_REGNUM))))
|
|
1133 (clobber (reg:CC CC_REGNUM))]
|
|
1134 ""
|
|
1135 "ADDC.%# %1,%2,%0\t// %0 := carry + %1 + %2 (high multi-part)"
|
|
1136 [(set_attr "type" "basicAlu,basicAlu")
|
|
1137 (set_attr "longConstant" "false,true")
|
|
1138 (set_attr "length" "2,4")])
|
|
1139
|
|
1140 ;; The lea instruction is a special type of add operation, which looks
|
|
1141 ;; like a movhi (reg := address). It expands into reg := fp +
|
|
1142 ;; offset. Ideally there should be two variants, which take different
|
|
1143 ;; sized offsets (i.e., using the long constant, or not, as
|
|
1144 ;; appropriate). However, the address operand may have arbitrary
|
|
1145 ;; values added to it later (i.e., the AP will be eliminated, possibly
|
|
1146 ;; converting a small offset into a long offset), so a long offset is
|
|
1147 ;; always assumed.
|
|
1148
|
|
1149 ;; Note that the lea can use an addition, and hence may modify the CC
|
|
1150 ;; register. This upsets scheduling, so instead the lea is placed in
|
|
1151 ;; ALU 1 where it cannot modify CC.
|
|
1152
|
|
1153 (define_insn "*lea_add"
|
|
1154 [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
|
|
1155 (plus:HI (match_operand:HI 1 "register_operand" "r")
|
|
1156 (match_operand:HI 2 "immediate_operand" "i")))]
|
|
1157 ""
|
|
1158 "ADD.1 %1,%2,%0\t// lea (add)")
|
|
1159
|
|
1160 ;; Note that, though this instruction looks similar to movhi pattern,
|
|
1161 ;; "p" constraint cannot be specified for operands other than
|
|
1162 ;; address_operand, hence the extra pattern below.
|
|
1163 (define_insn "*lea_move"
|
|
1164 [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
|
|
1165 (match_operand:HI 1 "address_operand" "p"))]
|
|
1166 ""
|
|
1167 {
|
|
1168 if (REG == GET_CODE(operands[1]))
|
|
1169 return "COPY.1 %1,%0\t// %0 := %1 (lea)";
|
|
1170 else
|
|
1171 return "ADD.1 %b1,%o1,%0\t\t// %0 := %b1 + %o1 (lea)";
|
|
1172 }
|
|
1173 [(set_attr "type" "nonCcAlu")
|
|
1174 (set_attr "longConstant" "true")
|
|
1175 (set_attr "length" "4")])
|
|
1176
|
|
1177
|
|
1178 ;;===========================================================================
|
|
1179 ;; Subtraction. Note that these patterns never take immediate second
|
|
1180 ;; operands, since those cases are handled by canonicalising the
|
|
1181 ;; instruction into the addition of a negative costant.
|
|
1182 ;; But, if the first operand needs to be a negative constant, it
|
|
1183 ;; is supported here.
|
|
1184 ;;===========================================================================
|
|
1185
|
|
1186 (define_insn "subhi3"
|
|
1187 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
|
|
1188 (minus:HI (match_operand:HI 1 "general_operand" "r,I,i")
|
|
1189 (match_operand:HI 2 "register_operand" "r,r,r")))
|
|
1190 (clobber (reg:CC CC_REGNUM))]
|
|
1191 ""
|
|
1192 "SUB.%# %1,%2,%0 // %0 := %1 - %2 (HI)"
|
|
1193 [(set_attr "type" "basicAlu,basicAlu,basicAlu")
|
|
1194 (set_attr "longConstant" "false,true,true")
|
|
1195 (set_attr "length" "2,4,4")])
|
|
1196
|
|
1197 ;; If we peepholed the compare instruction out, we need to make sure the
|
|
1198 ;; sub goes in slot 0. This pattern is just to accomplish that.
|
|
1199
|
|
1200 (define_insn "subhi3_with_use_clause"
|
|
1201 [(set (match_operand:HI 0 "register_operand" "=r,r,r")
|
|
1202 (minus:HI (match_operand:HI 1 "general_operand" "r,I,i")
|
|
1203 (match_operand:HI 2 "register_operand" "r,r,r")))
|
|
1204 (set (reg:CC CC_REGNUM)
|
|
1205 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
1206 [(const_int 0)
|
|
1207 (const_int 0)]))]
|
|
1208 ""
|
|
1209 "SUB.0 %1,%2,%0 // %0 := %1 - %2 (HI)"
|
|
1210 [(set_attr "type" "picoAlu,picoAlu,picoAlu")
|
|
1211 (set_attr "longConstant" "false,true,true")
|
|
1212 (set_attr "length" "2,4,4")])
|
|
1213
|
|
1214 (define_insn_and_split "subsi3"
|
|
1215 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
1216 (minus:SI (match_operand:SI 1 "general_operand" "r,i")
|
|
1217 (match_operand:SI 2 "register_operand" "r,r")))
|
|
1218 (clobber (reg:CC CC_REGNUM))]
|
|
1219 ""
|
|
1220 "// %0 := %1 - %2 (SI)\n\tSUB.%# %L1,%L2,%L0\n\tSUBB.%# %U1,%U2,%U0"
|
|
1221 "reload_completed && picochip_schedule_type != DFA_TYPE_NONE"
|
|
1222 [(match_dup 4)
|
|
1223 (match_dup 5)]
|
|
1224 "
|
|
1225 {
|
|
1226 rtx op0_high = gen_highpart (HImode, operands[0]);
|
|
1227 rtx op0_low = gen_lowpart (HImode, operands[0]);
|
|
1228 rtx op2_high = gen_highpart (HImode, operands[2]);
|
|
1229 rtx op2_low = gen_lowpart (HImode, operands[2]);
|
|
1230 rtx op1_high,op1_low;
|
|
1231
|
|
1232 if (CONST_INT == GET_CODE(operands[1]))
|
|
1233 {
|
|
1234 op1_high = picochip_get_high_const(operands[1]);
|
|
1235 op1_low = picochip_get_low_const(operands[1]);
|
|
1236 } else {
|
|
1237 op1_high = gen_highpart (HImode, operands[1]);
|
|
1238 op1_low = gen_lowpart (HImode, operands[1]);
|
|
1239 }
|
|
1240
|
|
1241
|
|
1242 operands[4] = gen_sub_multi_lower (op0_low, op1_low, op2_low);
|
|
1243 operands[5] = gen_sub_multi_upper (op0_high, op1_high, op2_high);
|
|
1244
|
|
1245 }")
|
|
1246
|
|
1247 ;; Match the patterns emitted by the multi-part subtraction splitting.
|
|
1248 ;; This sets the CC register, so it needs to go into slot 0.
|
|
1249 (define_insn "sub_multi_lower"
|
|
1250 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1251 (minus:HI (match_operand:HI 1 "general_operand" "r,i")
|
|
1252 (match_operand:HI 2 "register_operand" "r,r")))
|
|
1253 (set (reg:CC CC_REGNUM)
|
|
1254 (compare:CC (minus:HI (match_dup 1) (match_dup 2))
|
|
1255 (const_int 0)))]
|
|
1256 ""
|
|
1257 "SUB.%# %1,%2,%0\t// %0+carry := %1 - %2 (lower SI)"
|
|
1258 [(set_attr "type" "picoAlu,picoAlu")
|
|
1259 (set_attr "longConstant" "false,true")
|
|
1260 (set_attr "length" "2,4")])
|
|
1261
|
|
1262 ;; Perform the central part of a multi-part addition (DI). This uses
|
|
1263 ;; the CC register, and also sets the CC register, so needs to be
|
|
1264 ;; placed in the first ALU.
|
|
1265 (define_insn "sub_multi_mid"
|
|
1266 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1267 (minus:HI (match_operand:HI 1 "general_operand" "r,i")
|
|
1268 (minus:HI (match_operand:HI 2 "register_operand" "r,r")
|
|
1269 (reg:CC CC_REGNUM))))
|
|
1270 (set (reg:CC CC_REGNUM)
|
|
1271 (compare:CC (minus:HI (match_dup 1)
|
|
1272 (match_dup 2))
|
|
1273 (const_int 0)))]
|
|
1274 ""
|
|
1275 "SUBB.%# %1,%2,%0\t// %0+carry := carry - %1 - %2 (mid multi-part)"
|
|
1276 [(set_attr "type" "picoAlu,picoAlu")
|
|
1277 (set_attr "longConstant" "false,true")
|
|
1278 (set_attr "length" "2,4")])
|
|
1279
|
|
1280 (define_insn "sub_multi_upper"
|
|
1281 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1282 (minus:HI (match_operand:HI 1 "general_operand" "r,i")
|
|
1283 (minus:HI (match_operand:HI 2 "register_operand" "r,r")
|
|
1284 (reg:CC CC_REGNUM))))
|
|
1285 (clobber (reg:CC CC_REGNUM))]
|
|
1286 ""
|
|
1287 "SUBB.%# %1,%2,%0\t// %0 := carry - %1 - %2 (upper SI)"
|
|
1288 [(set_attr "type" "basicAlu,basicAlu")
|
|
1289 (set_attr "longConstant" "false,true")
|
|
1290 (set_attr "length" "2,4")])
|
|
1291
|
|
1292 ;;===========================================================================
|
|
1293 ;; Multiplication (signed)
|
|
1294 ;;===========================================================================
|
|
1295
|
|
1296 (define_insn "multiply_machi"
|
|
1297 [(set (reg:HI ACC_REGNUM)
|
|
1298 (mult:HI (match_operand:HI 0 "register_operand" "r,r")
|
|
1299 (match_operand:HI 1
|
|
1300 "picochip_register_or_immediate_operand" "r,i")))]
|
|
1301 "TARGET_HAS_MAC_UNIT"
|
|
1302 "MUL %0,%1,acc0\t// acc0 := %0 * %1 (signed)"
|
|
1303 [(set_attr "length" "3,5")
|
|
1304 (set_attr "type" "mac,mac")
|
|
1305 (set_attr "longConstant" "false,true")])
|
|
1306
|
|
1307 (define_expand "mulhi3"
|
|
1308 [(set (match_operand:HI 0 "register_operand" "")
|
|
1309 (mult:HI (match_operand:HI 1 "register_operand" "")
|
|
1310 (match_operand:HI 2 "picochip_register_or_immediate_operand" "")))]
|
|
1311 "TARGET_HAS_MULTIPLY"
|
|
1312 "")
|
|
1313
|
|
1314 ;; Different types of mulhi, depending on the AE type. If the AE has MUL unit,
|
|
1315 ;; use the following pattern.
|
|
1316 (define_insn "*mulhi3_mul"
|
|
1317 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1318 (mult:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1319 (match_operand:HI 2
|
|
1320 "picochip_register_or_immediate_operand" "r,i")))]
|
|
1321 "TARGET_HAS_MUL_UNIT"
|
|
1322 "MULL %1,%2,%0 // %0 := %1 * %2 (HI)"
|
|
1323 [(set_attr "length" "3,5")
|
|
1324 (set_attr "type" "mul,mul")
|
|
1325 (set_attr "longConstant" "false,true")])
|
|
1326
|
|
1327 ;; If the AE has MAC unit, instead, use the following pattern.
|
|
1328 (define_insn_and_split "*mulhi3_mac"
|
|
1329 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1330 (mult:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1331 (match_operand:HI 2
|
|
1332 "picochip_register_or_immediate_operand" "r,i")))]
|
|
1333 "TARGET_HAS_MAC_UNIT"
|
|
1334 "// %0 := %1 * %2\n\tMUL %1,%2,acc0\n\tREADACC acc0,frac,%0"
|
|
1335 "TARGET_HAS_MAC_UNIT && reload_completed"
|
|
1336 [(match_dup 3)
|
|
1337 (match_dup 4)]
|
|
1338 "
|
|
1339 {
|
|
1340 rtx const_rtx = GEN_INT(0);
|
|
1341 operands[3] = (gen_multiply_machi(operands[1], operands[2]));
|
|
1342 operands[4] = (gen_movhi_mac(operands[0],const_rtx));
|
|
1343 } "
|
|
1344 )
|
|
1345
|
|
1346 (define_insn "umultiply_machisi"
|
|
1347 [(set (reg:SI ACC_REGNUM)
|
|
1348 (mult:SI (zero_extend:SI (match_operand:HI 0 "register_operand" "r"))
|
|
1349 (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))))]
|
|
1350 "TARGET_HAS_MAC_UNIT"
|
|
1351 "MULUU %0,%1,acc0\t// acc0 := %0 * %1 (unsigned)"
|
|
1352 [(set_attr "length" "3")
|
|
1353 (set_attr "type" "mac")
|
|
1354 (set_attr "longConstant" "false")])
|
|
1355
|
|
1356 (define_insn "multiply_machisi"
|
|
1357 [(set (reg:SI ACC_REGNUM)
|
|
1358 (mult:SI (sign_extend:SI (match_operand:HI 0 "register_operand" "r,r"))
|
|
1359 (sign_extend:SI (match_operand:HI 1
|
|
1360 "picochip_register_or_immediate_operand" "r,i"))))]
|
|
1361 "TARGET_HAS_MAC_UNIT"
|
|
1362 "MUL %0,%1,acc0\t// acc0 := %0 * %1 (signed)"
|
|
1363 [(set_attr "length" "3,5")
|
|
1364 (set_attr "type" "mac,mac")
|
|
1365 (set_attr "longConstant" "false,true")])
|
|
1366
|
|
1367 ;; We want to prevent GCC from thinking ACC is a normal register and using
|
|
1368 ;; this pattern. We want it to be used only when you use MAC unit
|
|
1369 ;; multiplication. Added a "use" clause for that sake.
|
|
1370 (define_insn "movsi_mac"
|
|
1371 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
1372 (reg:SI ACC_REGNUM))
|
|
1373 (use (match_operand:SI 1 "const_int_operand" ""))]
|
|
1374 "TARGET_HAS_MAC_UNIT"
|
|
1375 "READACC32 acc0,%R0 \t// %0 := acc0 "
|
|
1376 [(set_attr "length" "3")
|
|
1377 (set_attr "type" "mac")
|
|
1378 (set_attr "longConstant" "false")])
|
|
1379
|
|
1380 ;; We want to prevent GCC from thinking ACC is a normal register and using
|
|
1381 ;; this pattern. We want it to be used only when you use MAC unit
|
|
1382 ;; multiplication. Added a "use" clause for that sake.
|
|
1383 (define_insn "movhi_mac"
|
|
1384 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
1385 (reg:HI ACC_REGNUM) )
|
|
1386 (use (match_operand:HI 1 "const_int_operand" ""))]
|
|
1387 "TARGET_HAS_MAC_UNIT"
|
|
1388 "READACC acc0,frac,%0 \t// %0 := acc0 "
|
|
1389 [(set_attr "length" "3")
|
|
1390 (set_attr "type" "mac")
|
|
1391 (set_attr "longConstant" "false")])
|
|
1392
|
|
1393 ;; 16-bit to 32-bit widening signed multiplication.
|
|
1394 (define_expand "mulhisi3"
|
|
1395 [(set (match_operand:SI 0 "register_operand" "=&r")
|
|
1396 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1397 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
|
1398 "TARGET_HAS_MULTIPLY"
|
|
1399 ""
|
|
1400 )
|
|
1401
|
|
1402 (define_insn_and_split "*mulhisi3_mul"
|
|
1403 [(set (match_operand:SI 0 "register_operand" "=&r")
|
|
1404 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1405 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
|
1406 "TARGET_HAS_MUL_UNIT"
|
|
1407 "// %0 := %1 * %2 (HI->SI)\;MULL %1,%2,%L0\;MULH %1,%2,%U0";
|
|
1408 "TARGET_HAS_MUL_UNIT && reload_completed && picochip_schedule_type != DFA_TYPE_NONE"
|
|
1409 [(match_dup 3)
|
|
1410 (match_dup 4)]
|
|
1411 "
|
|
1412 {
|
|
1413 rtx op0_high = gen_highpart (HImode, operands[0]);
|
|
1414 rtx op0_low = gen_lowpart (HImode, operands[0]);
|
|
1415 operands[3] = gen_mulhisi3_mul_lower(op0_low,operands[1],operands[2]);
|
|
1416 operands[4] = gen_mulhisi3_mul_higher(op0_high,operands[1],operands[2]);
|
|
1417 }
|
|
1418 "
|
|
1419 )
|
|
1420
|
|
1421 (define_insn "mulhisi3_mul_lower"
|
|
1422 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1423 (subreg:HI
|
|
1424 (mult:SI
|
|
1425 (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1426 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))) 0))]
|
|
1427 "TARGET_HAS_MUL_UNIT"
|
|
1428 "MULL %1,%2,%0"
|
|
1429 [(set_attr "length" "3")
|
|
1430 (set_attr "type" "mul")
|
|
1431 (set_attr "longConstant" "false")])
|
|
1432
|
|
1433 (define_insn "mulhisi3_mul_higher"
|
|
1434 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1435 (subreg:HI
|
|
1436 (mult:SI
|
|
1437 (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1438 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))) 2))]
|
|
1439 "TARGET_HAS_MUL_UNIT"
|
|
1440 "MULH %1,%2,%0"
|
|
1441 [(set_attr "length" "3")
|
|
1442 (set_attr "type" "mul")
|
|
1443 (set_attr "longConstant" "false")])
|
|
1444
|
|
1445 (define_insn_and_split "*mulhisi3_mac"
|
|
1446 [(set (match_operand:SI 0 "register_operand" "=&r")
|
|
1447 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1448 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
|
1449 "TARGET_HAS_MAC_UNIT"
|
|
1450 "// %0 := %1 * %2 (HI->SI) STAN2\;MUL %1,%2,acc0\;READACC32 acc0,%R0";
|
|
1451 "TARGET_HAS_MAC_UNIT && reload_completed"
|
|
1452 [(match_dup 3)
|
|
1453 (match_dup 4)]
|
|
1454 "
|
|
1455 {
|
|
1456 rtx const_rtx = gen_int_mode(0,SImode);
|
|
1457 operands[3] = (gen_multiply_machisi(operands[1], operands[2]));
|
|
1458 operands[4] = (gen_movsi_mac(operands[0],const_rtx));
|
|
1459 } "
|
|
1460 )
|
|
1461
|
|
1462 ;;===========================================================================
|
|
1463 ;; Widening multiplication (unsigned)
|
|
1464 ;;===========================================================================
|
|
1465
|
|
1466 (define_expand "umulhisi3"
|
|
1467 [(set (match_operand:SI 0 "register_operand" "=&r")
|
|
1468 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1469 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
|
1470 "TARGET_HAS_MULTIPLY"
|
|
1471 ""
|
|
1472 )
|
|
1473
|
|
1474 (define_insn_and_split "*umulhisi3_mul"
|
|
1475 [(set (match_operand:SI 0 "register_operand" "=&r")
|
|
1476 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1477 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
|
1478 "TARGET_HAS_MUL_UNIT"
|
|
1479 "// %0 := %1 * %2 (uHI->uSI Type 1)\;MULUL %1,%2,%L0\n\tMULUH %1,%2,%U0";
|
|
1480 "TARGET_HAS_MUL_UNIT && reload_completed && picochip_schedule_type != DFA_TYPE_NONE"
|
|
1481 [(match_dup 3)
|
|
1482 (match_dup 4)]
|
|
1483 "
|
|
1484 {
|
|
1485 rtx op0_high = gen_highpart (HImode, operands[0]);
|
|
1486 rtx op0_low = gen_lowpart (HImode, operands[0]);
|
|
1487 operands[3] = gen_umulhisi3_mul_lower(op0_low,operands[1],operands[2]);
|
|
1488 operands[4] = gen_umulhisi3_mul_higher(op0_high,operands[1],operands[2]);
|
|
1489 }
|
|
1490 "
|
|
1491 )
|
|
1492
|
|
1493 (define_insn "umulhisi3_mul_lower"
|
|
1494 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1495 (subreg:HI
|
|
1496 (mult:SI
|
|
1497 (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1498 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))) 0))]
|
|
1499 "TARGET_HAS_MUL_UNIT"
|
|
1500 "MULUL %1,%2,%0"
|
|
1501 [(set_attr "length" "3")
|
|
1502 (set_attr "type" "mul")
|
|
1503 (set_attr "longConstant" "false")])
|
|
1504
|
|
1505 (define_insn "umulhisi3_mul_higher"
|
|
1506 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1507 (subreg:HI
|
|
1508 (mult:SI
|
|
1509 (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1510 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))) 2))]
|
|
1511 "TARGET_HAS_MUL_UNIT"
|
|
1512 "MULUH %1,%2,%0"
|
|
1513 [(set_attr "length" "3")
|
|
1514 (set_attr "type" "mul")
|
|
1515 (set_attr "longConstant" "false")])
|
|
1516
|
|
1517 (define_insn_and_split "*umulhisi3_mac"
|
|
1518 [(set (match_operand:SI 0 "register_operand" "=&r")
|
|
1519 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
|
|
1520 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
|
1521 "TARGET_HAS_MAC_UNIT"
|
|
1522 "// %0 := %1 * %2 (uHI->uSI Type 3)\;MULUU %1,%2,acc0\;READACC32 acc0,%R0";
|
|
1523 "TARGET_HAS_MAC_UNIT && reload_completed"
|
|
1524 [(match_dup 3)
|
|
1525 (match_dup 4)]
|
|
1526 "
|
|
1527 {
|
|
1528 rtx const_rtx = gen_int_mode(0,SImode);
|
|
1529 operands[3] = (gen_umultiply_machisi(operands[1], operands[2]));
|
|
1530 operands[4] = (gen_movsi_mac(operands[0],const_rtx));
|
|
1531 } "
|
|
1532 )
|
|
1533
|
|
1534 ;;===========================================================================
|
|
1535 ;; Division (signed)
|
|
1536 ;;===========================================================================
|
|
1537
|
|
1538 ;; Perform a divmod operation as a function call. This results in some
|
|
1539 ;; registers being clobbered (r0-6, r12 - ignore r13,14 as these are
|
|
1540 ;; known not to be affected).
|
|
1541 (define_expand "divmodhi4"
|
|
1542 [
|
|
1543 ; Copy the inputs to r0 and r1.
|
|
1544 (set (reg:HI 0) (match_operand:HI 1 "register_operand" ""))
|
|
1545 (set (reg:HI 1) (match_operand:HI 2 "register_operand" ""))
|
|
1546 ; Make the function call - note that r12 (link) is clobbered. Note also
|
|
1547 ; that an explicit call is generated. This ensures that gcc notices that
|
|
1548 ; any function containing a div/mod is not a leaf function.
|
|
1549 (parallel [(match_dup 4)
|
|
1550 (set (reg:HI 0) (div:HI (reg:HI 0) (reg:HI 1)))
|
|
1551 (set (reg:HI 1) (mod:HI (reg:HI 0) (reg:HI 1)))
|
|
1552 (clobber (reg:HI 2))
|
|
1553 (clobber (reg:HI 3))
|
|
1554 (clobber (reg:HI 4))
|
|
1555 (clobber (reg:HI 5))
|
|
1556 (clobber (reg:HI 12))
|
|
1557 (clobber (reg:CC CC_REGNUM))
|
|
1558 ])
|
|
1559 ; Set the quotient (returned in register 0)
|
|
1560 (set (match_operand:HI 0 "register_operand" "") (reg:HI 0))
|
|
1561 ; Set the remainder (returned in register 1)
|
|
1562 (set (match_operand:HI 3 "register_operand" "") (reg:HI 1))]
|
|
1563 ""
|
|
1564 {
|
|
1565 rtx fnName = gen_rtx_SYMBOL_REF (HImode, "_divmodhi4");
|
|
1566 operands[4] = gen_call_for_divmod (gen_rtx_MEM (QImode, fnName), GEN_INT(0));
|
|
1567 })
|
|
1568
|
|
1569 ; Match a call to divmodhi4. As this is a call, the link register
|
|
1570 ; (r12), and registers r0-5 must be clobbered. Ignore clobbering of
|
|
1571 ; r13/4 as these aren't used by the divide function).
|
|
1572 (define_insn "*divmodhi4_call"
|
|
1573 [(call (mem:QI (match_operand:HI 0 "immediate_operand" "i"))
|
|
1574 (match_operand 1 "const_int_operand" ""))
|
|
1575 (set (reg:HI 0) (div:HI (reg:HI 0) (reg:HI 1)))
|
|
1576 (set (reg:HI 1) (mod:HI (reg:HI 0) (reg:HI 1)))
|
|
1577 (clobber (reg:HI 2))
|
|
1578 (clobber (reg:HI 3))
|
|
1579 (clobber (reg:HI 4))
|
|
1580 (clobber (reg:HI 5))
|
|
1581 (clobber (reg:HI 12))
|
|
1582 (clobber (reg:CC CC_REGNUM))
|
|
1583 ]
|
|
1584 ""
|
|
1585 "JL (%0)\t// call %0%>"
|
|
1586 [(set_attr "length" "4")
|
|
1587 (set_attr "longConstant" "true")
|
|
1588 (set_attr "type" "call")])
|
|
1589
|
|
1590 ;; Perform a udivmod operation as a function call. This results in some
|
|
1591 ;; registers being clobbered (r0-6, r12 - ignore r13,14 as these are
|
|
1592 ;; known not to be affected).
|
|
1593 (define_expand "udivmodhi4"
|
|
1594 [
|
|
1595 ; Copy the inputs to r0 and r1.
|
|
1596 (set (reg:HI 0) (match_operand:HI 1 "register_operand" ""))
|
|
1597 (set (reg:HI 1) (match_operand:HI 2 "register_operand" ""))
|
|
1598 ; Make the function call - note that r12 (link) is clobbered. Note also
|
|
1599 ; that an explicit call is generated. This ensures that gcc notices that
|
|
1600 ; any function containing a div/mod is not a leaf function.
|
|
1601 (parallel [(match_dup 4)
|
|
1602 (set (reg:HI 0) (udiv:HI (reg:HI 0) (reg:HI 1)))
|
|
1603 (set (reg:HI 1) (umod:HI (reg:HI 0) (reg:HI 1)))
|
|
1604 (clobber (reg:HI 2))
|
|
1605 (clobber (reg:HI 3))
|
|
1606 (clobber (reg:HI 4))
|
|
1607 (clobber (reg:HI 5))
|
|
1608 (clobber (reg:HI 12))
|
|
1609 (clobber (reg:CC CC_REGNUM))
|
|
1610 ])
|
|
1611 ; Set the quotient (returned in register 0)
|
|
1612 (set (match_operand:HI 0 "register_operand" "") (reg:HI 0))
|
|
1613 ; Set the remainder (returned in register 1)
|
|
1614 (set (match_operand:HI 3 "register_operand" "") (reg:HI 1))]
|
|
1615 ""
|
|
1616 {
|
|
1617 rtx fnName = gen_rtx_SYMBOL_REF (HImode, "_udivmodhi4");
|
|
1618 operands[4] = gen_call_for_divmod (gen_rtx_MEM (QImode, fnName), GEN_INT(0));
|
|
1619 })
|
|
1620
|
|
1621 ; Match a call to udivmodhi4. As this is a call, the link register
|
|
1622 ; (r12), and registers r0-5 must be clobbered. Ignore clobbering of
|
|
1623 ; r13/4 as these aren't used by the divide function).
|
|
1624 (define_insn "*udivmodhi4_call"
|
|
1625 [(call (mem:QI (match_operand:HI 0 "immediate_operand" "i"))
|
|
1626 (match_operand 1 "const_int_operand" ""))
|
|
1627 (set (reg:HI 0) (udiv:HI (reg:HI 0) (reg:HI 1)))
|
|
1628 (set (reg:HI 1) (umod:HI (reg:HI 0) (reg:HI 1)))
|
|
1629 (clobber (reg:HI 2))
|
|
1630 (clobber (reg:HI 3))
|
|
1631 (clobber (reg:HI 4))
|
|
1632 (clobber (reg:HI 5))
|
|
1633 (clobber (reg:HI 12))
|
|
1634 (clobber (reg:CC CC_REGNUM))]
|
|
1635 ""
|
|
1636 "JL (%0)\t// call %0%>"
|
|
1637 [(set_attr "length" "4")
|
|
1638 (set_attr "longConstant" "true")
|
|
1639 (set_attr "type" "call")])
|
|
1640
|
|
1641 (define_expand "udivmodsi4"
|
|
1642 [
|
|
1643 ; Make the function call
|
|
1644 (set (reg:SI 0) (match_operand:SI 1 "register_operand" ""))
|
|
1645 (set (reg:SI 2) (match_operand:SI 2 "register_operand" ""))
|
|
1646 (parallel [
|
|
1647 (match_dup 4)
|
|
1648 (set (reg:SI 4) (udiv:SI (reg:SI 0) (reg:SI 2)))
|
|
1649 (set (reg:SI 6) (umod:SI (reg:SI 0) (reg:SI 2)))
|
|
1650 (clobber (reg:SI 0))
|
|
1651 (clobber (reg:SI 2))
|
|
1652 (clobber (reg:HI 12))
|
|
1653 (clobber (reg:CC CC_REGNUM))])
|
|
1654 (set (match_operand:SI 0 "register_operand" "") (reg:SI 4))
|
|
1655 (set (match_operand:SI 3 "register_operand" "") (reg:SI 6))]
|
|
1656 ""
|
|
1657 {
|
|
1658 rtx fnName = gen_rtx_SYMBOL_REF (HImode, "_udivmodsi4");
|
|
1659 operands[4] = gen_call_for_divmod (gen_rtx_MEM (QImode, fnName), GEN_INT(0));
|
|
1660 })
|
|
1661
|
|
1662 (define_insn "*udivmodsi4_call"
|
|
1663 [(call (mem:QI (match_operand:HI 0 "immediate_operand" "i"))
|
|
1664 (match_operand 1 "const_int_operand" ""))
|
|
1665 (set (reg:SI 4) (udiv:SI (reg:SI 0) (reg:SI 2)))
|
|
1666 (set (reg:SI 6) (umod:SI (reg:SI 0) (reg:SI 2)))
|
|
1667 (clobber (reg:SI 0))
|
|
1668 (clobber (reg:SI 2))
|
|
1669 (clobber (reg:HI 12))
|
|
1670 (clobber (reg:CC CC_REGNUM))]
|
|
1671 ""
|
|
1672 "JL (%0)\t// call %0%>"
|
|
1673 [(set_attr "length" "4")
|
|
1674 (set_attr "longConstant" "true")
|
|
1675 (set_attr "type" "call")])
|
|
1676
|
|
1677 (define_expand "divmodsi4"
|
|
1678 [
|
|
1679 ; Make the function call
|
|
1680 (set (reg:SI 0) (match_operand:SI 1 "register_operand" ""))
|
|
1681 (set (reg:SI 2) (match_operand:SI 2 "register_operand" ""))
|
|
1682 (parallel [
|
|
1683 (match_dup 4)
|
|
1684 (set (reg:SI 4) (div:SI (reg:SI 0) (reg:SI 2)))
|
|
1685 (set (reg:SI 6) (mod:SI (reg:SI 0) (reg:SI 2)))
|
|
1686 (clobber (reg:SI 0))
|
|
1687 (clobber (reg:SI 2))
|
|
1688 (clobber (reg:HI 12))
|
|
1689 (clobber (reg:CC CC_REGNUM))])
|
|
1690 (set (match_operand:SI 0 "register_operand" "") (reg:SI 4))
|
|
1691 (set (match_operand:SI 3 "register_operand" "") (reg:SI 6))]
|
|
1692 ""
|
|
1693 {
|
|
1694 rtx fnName = gen_rtx_SYMBOL_REF (HImode, "_divmodsi4");
|
|
1695 operands[4] = gen_call_for_divmod (gen_rtx_MEM (QImode, fnName), GEN_INT(0));
|
|
1696 })
|
|
1697
|
|
1698 (define_insn "*divmodsi4_call"
|
|
1699 [(call (mem:QI (match_operand:HI 0 "immediate_operand" "i"))
|
|
1700 (match_operand 1 "const_int_operand" ""))
|
|
1701 (set (reg:SI 4) (div:SI (reg:SI 0) (reg:SI 2)))
|
|
1702 (set (reg:SI 6) (mod:SI (reg:SI 0) (reg:SI 2)))
|
|
1703 (clobber (reg:SI 0))
|
|
1704 (clobber (reg:SI 2))
|
|
1705 (clobber (reg:HI 12))
|
|
1706 (clobber (reg:CC CC_REGNUM))]
|
|
1707 ""
|
|
1708 "JL (%0)\t// call %0%>"
|
|
1709 [(set_attr "length" "4")
|
|
1710 (set_attr "longConstant" "true")
|
|
1711 (set_attr "type" "call")])
|
|
1712
|
|
1713 ;;===========================================================================
|
|
1714 ;; Bitwise AND. The QI/SI mode instructions are automatically
|
|
1715 ;; synthesised from the HI mode instruction.
|
|
1716 ;;===========================================================================
|
|
1717
|
|
1718 (define_insn "andhi3"
|
|
1719 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1720 (and:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1721 (match_operand:HI 2 "general_operand" "r,n")))
|
|
1722 (clobber (reg:CC CC_REGNUM))]
|
|
1723 ""
|
|
1724 "AND.%# %1,%2,%0 // %0 := %1 AND %2 (HI)"
|
|
1725 [(set_attr "type" "basicAlu,basicAlu")
|
|
1726 (set_attr "longConstant" "false,true")
|
|
1727 (set_attr "length" "3,5")])
|
|
1728
|
|
1729 ;; If we peepholed the compare instruction out, we need to make sure the
|
|
1730 ;; "and" goes in slot 0. This pattern is just to accomplish that.
|
|
1731
|
|
1732 (define_insn "andhi3_with_use_clause"
|
|
1733 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1734 (and:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1735 (match_operand:HI 2 "general_operand" "r,n")))
|
|
1736 (set (reg:CC CC_REGNUM)
|
|
1737 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
1738 [(const_int 0)
|
|
1739 (const_int 0)]))]
|
|
1740 ""
|
|
1741 "AND.0 %1,%2,%0 // %0 := %1 AND %2 (HI)"
|
|
1742 [(set_attr "type" "picoAlu,picoAlu")
|
|
1743 (set_attr "longConstant" "false,true")
|
|
1744 (set_attr "length" "3,5")])
|
|
1745
|
|
1746 ;;===========================================================================
|
|
1747 ;; Bitwise inclusive-OR. The QI mode instruction is automatically
|
|
1748 ;; synthesised from the HI mode instruction.
|
|
1749 ;;===========================================================================
|
|
1750
|
|
1751 (define_insn "iorhi3"
|
|
1752 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1753 (ior:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1754 (match_operand:HI 2 "register_operand" "r,n")))
|
|
1755 (clobber (reg:CC CC_REGNUM))]
|
|
1756 ""
|
|
1757 "OR.%# %1,%2,%0 // %0 := %1 IOR %2 (HI)"
|
|
1758 [(set_attr "type" "basicAlu,basicAlu")
|
|
1759 (set_attr "longConstant" "false,true")
|
|
1760 (set_attr "length" "3,5")])
|
|
1761
|
|
1762 (define_insn "iorhi3_with_use_clause"
|
|
1763 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1764 (ior:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1765 (match_operand:HI 2 "general_operand" "r,n")))
|
|
1766 (set (reg:CC CC_REGNUM)
|
|
1767 (match_operator:CC 3 "picochip_peephole_comparison_operator"
|
|
1768 [(const_int 0)
|
|
1769 (const_int 0)]))]
|
|
1770 ""
|
|
1771 "OR.0 %1,%2,%0 // %0 := %1 IOR %2 (HI)"
|
|
1772 [(set_attr "type" "picoAlu,picoAlu")
|
|
1773 (set_attr "longConstant" "false,true")
|
|
1774 (set_attr "length" "3,5")])
|
|
1775
|
|
1776 ;;===========================================================================
|
|
1777 ;; Bitwise exclusive-OR. The QI/SI mode instructions are automatically
|
|
1778 ;; synthesised from the HI mode instruction.
|
|
1779 ;;===========================================================================
|
|
1780
|
|
1781 (define_insn "xorhi3"
|
|
1782 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1783 (xor:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1784 (match_operand:HI 2 "picochip_register_or_immediate_operand" "r,n")))
|
|
1785 (clobber (reg:CC CC_REGNUM))]
|
|
1786 ""
|
|
1787 "XOR.%# %1,%2,%0 // %0 := %1 XOR %2 (HI)"
|
|
1788 [(set_attr "type" "basicAlu,basicAlu")
|
|
1789 (set_attr "longConstant" "false,true")
|
|
1790 (set_attr "length" "3,5")])
|
|
1791
|
|
1792 ;;===========================================================================
|
|
1793 ;; Arithmetic shift left.
|
|
1794 ;;===========================================================================
|
|
1795
|
|
1796 (define_insn "ashlhi3"
|
|
1797 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1798 (ashift:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1799 (match_operand:HI 2 "general_operand" "r,J")))]
|
|
1800 ""
|
|
1801 "LSL.%# %1,%2,%0 // %0 := %1 << %2"
|
|
1802 [(set_attr "type" "picoAlu,basicAlu")
|
|
1803 (set_attr "length" "3,3")])
|
|
1804
|
|
1805 ;;===========================================================================
|
|
1806 ;; Arithmetic shift right.
|
|
1807 ;;===========================================================================
|
|
1808
|
|
1809 (define_insn "builtin_asri"
|
|
1810 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
1811 (ashiftrt:HI (match_operand:HI 1 "register_operand" "r")
|
|
1812 (match_operand:HI 2 "immediate_operand" "")))
|
|
1813 (clobber (reg:CC CC_REGNUM))]
|
|
1814 ""
|
|
1815 "ASR.%# %1,%2,%0\t// %0 = %1 >>{arith} %2"
|
|
1816 [(set_attr "type" "basicAlu")
|
|
1817 (set_attr "length" "3")])
|
|
1818
|
|
1819 ;; The picoChip ISA doesn't have a variable arithmetic shift right, so
|
|
1820 ;; synthesise it. Shifts by constants are directly supported.
|
|
1821
|
|
1822 (define_expand "ashrhi3"
|
|
1823 [(match_operand:HI 0 "register_operand" "")
|
|
1824 (match_operand:HI 1 "register_operand" "")
|
|
1825 (match_operand:HI 2 "picochip_register_or_immediate_operand" "")]
|
|
1826 ""
|
|
1827 {
|
|
1828 if (GET_CODE(operands[2]) == CONST_INT)
|
|
1829 /* Shift by constant is easy. */
|
|
1830 emit_insn (gen_builtin_asri (operands[0], operands[1], operands[2]));
|
|
1831 else
|
|
1832 {
|
|
1833 /* Synthesise a variable shift. */
|
|
1834
|
|
1835 /* Fill a temporary with the sign bits. */
|
|
1836 rtx tmp1 = gen_reg_rtx (HImode);
|
|
1837 emit_insn (gen_builtin_asri (tmp1, operands[1], GEN_INT(15)));
|
|
1838
|
|
1839 /* Shift the unsigned value. */
|
|
1840 rtx tmp2 = gen_reg_rtx (HImode);
|
|
1841 emit_insn (gen_lshrhi3 (tmp2, operands[1], operands[2]));
|
|
1842
|
|
1843 /* The word of sign bits must be shifted back to the left, to zero
|
|
1844 * out the unwanted lower bits. The amount to shift left by is (15 -
|
|
1845 * count). Since the shifts are computed modulo 16 (i.e., only the
|
|
1846 * lower 4 bits of the count are used), the shift amount (15 - count)
|
|
1847 * is equivalent to !count. */
|
|
1848 rtx tmp3 = gen_reg_rtx (HImode);
|
|
1849 rtx tmp3_1 = GEN_INT (-1);
|
|
1850 emit_insn (gen_xorhi3 (tmp3, operands[2], tmp3_1));
|
|
1851 rtx tmp4 = gen_reg_rtx (HImode);
|
|
1852 emit_insn (gen_ashlhi3 (tmp4, tmp1, tmp3));
|
|
1853
|
|
1854 /* Combine the sign bits with the shifted value. */
|
|
1855 emit_insn (gen_iorhi3 (operands[0], tmp2, tmp4));
|
|
1856
|
|
1857 }
|
|
1858 DONE;
|
|
1859 })
|
|
1860
|
|
1861 ;;===========================================================================
|
|
1862 ;; Logical shift right.
|
|
1863 ;;===========================================================================
|
|
1864
|
|
1865 (define_insn "lshrhi3"
|
|
1866 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
1867 (lshiftrt:HI (match_operand:HI 1 "register_operand" "r,r")
|
|
1868 (match_operand:HI 2 "general_operand" "r,J")))]
|
|
1869 ""
|
|
1870 "LSR.%# %1,%2,%0 // %0 := %1 >> %2"
|
|
1871 [(set_attr "type" "picoAlu,basicAlu")
|
|
1872 (set_attr "length" "3,3")])
|
|
1873
|
|
1874 ;;===========================================================================
|
|
1875 ;; Negate.
|
|
1876 ;;===========================================================================
|
|
1877
|
|
1878 ;; Negations are performed by subtracting from the constant 0, which
|
|
1879 ;; is loaded into a register. By using a register containing 0, the
|
|
1880 ;; chances of being able to CSE with another 0 value are increased.
|
|
1881
|
|
1882 (define_expand "neghi2"
|
|
1883 [(set (match_dup 2) (match_dup 3))
|
|
1884 (parallel [(set (match_operand:HI 0 "register_operand" "=r")
|
|
1885 (minus:HI (match_dup 2)
|
|
1886 (match_operand:HI 1 "register_operand" "r")))
|
|
1887 (clobber (reg:CC CC_REGNUM))])]
|
|
1888 ""
|
|
1889 "operands[2] = gen_reg_rtx(HImode);
|
|
1890 operands[3] = GEN_INT(0x00000000);")
|
|
1891
|
|
1892 (define_expand "negsi2"
|
|
1893 [(set (match_dup 2) (match_dup 3))
|
|
1894 (parallel [(set (match_operand:SI 0 "register_operand" "=r")
|
|
1895 (minus:SI (match_dup 2)
|
|
1896 (match_operand:SI 1 "register_operand" "r")))
|
|
1897 (clobber (reg:CC CC_REGNUM))])]
|
|
1898 ""
|
|
1899 "operands[2] = gen_reg_rtx(SImode);
|
|
1900 operands[3] = GEN_INT(0x00000000);")
|
|
1901
|
|
1902 ;;===========================================================================
|
|
1903 ;; Absolute value. Taken from the Hacker's Delight, page 17. The second of the
|
|
1904 ;; four options given there produces the smallest, fastest code.
|
|
1905 ;;===========================================================================
|
|
1906
|
|
1907 (define_insn_and_split "abshi2"
|
|
1908 [(set (match_operand:HI 0 "register_operand" "")
|
|
1909 (abs:HI (match_operand:HI 1 "register_operand" "")))]
|
|
1910 ""
|
|
1911 "#"
|
|
1912 ""
|
|
1913 [(parallel [(set (match_dup 2)
|
|
1914 (plus:HI (ashiftrt:HI (match_dup 1) (const_int 15))
|
|
1915 (match_dup 1)))
|
|
1916 (clobber (reg:CC CC_REGNUM))])
|
|
1917 (parallel [(set (match_dup 0)
|
|
1918 (xor:HI (ashiftrt:HI (match_dup 1) (const_int 15))
|
|
1919 (match_dup 2)))
|
|
1920 (clobber (reg:CC CC_REGNUM))])]
|
|
1921 {
|
|
1922 operands[2] = gen_reg_rtx (HImode);
|
|
1923 })
|
|
1924
|
|
1925 ;;===========================================================================
|
|
1926 ;; Bitwise complement. Use auto-synthesised variant for SI mode. Though this
|
|
1927 ;; internally uses xor, the compiler doesnt automatically synthesize it using
|
|
1928 ;; xor, if this pattern was removed.
|
|
1929 ;;===========================================================================
|
|
1930
|
|
1931 (define_insn "one_cmplhi2"
|
|
1932 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
1933 (not:HI (match_operand:HI 1 "register_operand" "0")))
|
|
1934 (clobber (reg:CC CC_REGNUM))]
|
|
1935 ""
|
|
1936 "XOR.%# %1,-1,%0 // %0 := ~%1"
|
|
1937 [(set_attr "type" "basicAlu")
|
|
1938 (set_attr "longConstant" "true")
|
|
1939 (set_attr "length" "5")])
|
|
1940
|
|
1941 ;;===========================================================================
|
|
1942 ;; Count leading zeros. The special sign-bit-count instruction can be used
|
|
1943 ;; to help us here.
|
|
1944 ;; op1:=clz(op1)
|
|
1945 ;; The code works by checking to see if the top bit is set. If it is,
|
|
1946 ;; then there are no leading zeros. If the top bit is cleared, then
|
|
1947 ;; the SBC instruction is used to determine how many more leading
|
|
1948 ;; zeros are present, and adding one more for the initial zero.
|
|
1949 ;;===========================================================================
|
|
1950
|
|
1951 (define_insn "clzhi2"
|
|
1952 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1953 (clz:HI (match_operand:HI 1 "register_operand" "r")))]
|
|
1954 ""
|
|
1955 "// Count leading zeros\;SBC %1,%0\;ASR.0 %1,15,r15 %| ADD.1 %0,1,%0\;COPYNE 0,%0"
|
|
1956 [(set_attr "length" "11")])
|
|
1957
|
|
1958 ;;===========================================================================
|
|
1959 ;; Count trailing zeros. This can be achieved efficiently by reversing
|
|
1960 ;; using the bitrev instruction, and then counting the leading zeros as
|
|
1961 ;; described above.
|
|
1962 ;;===========================================================================
|
|
1963
|
|
1964 (define_insn "ctzhi2"
|
|
1965 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1966 (ctz:HI (match_operand:HI 1 "register_operand" "r")))]
|
|
1967 ""
|
|
1968 "// Count trailing zeros\;BREV %1,%0\;SBC %0,%0\;AND.0 %1,0x0001,r15 %| ADD.1 %0,1,%0\;COPYNE 0,%0"
|
|
1969 [(set_attr "length" "15")])
|
|
1970
|
|
1971 ;;===========================================================================
|
|
1972 ;; Find the first set bit, starting from the least significant bit position.
|
|
1973 ;; This is very similar to the ctz function, except that the bit index is one
|
|
1974 ;; greater than the number of trailing zeros (i.e., SBC + 2), and the
|
|
1975 ;; result of ffs on the zero value is defined.
|
|
1976 ;;===========================================================================
|
|
1977
|
|
1978 (define_insn "ffshi2"
|
|
1979 [(set (match_operand:HI 0 "register_operand" "=&r")
|
|
1980 (ffs:HI (match_operand:HI 1 "register_operand" "r")))]
|
|
1981 ""
|
|
1982 "// First first bit\;BREV %1,%0\;SBC %0,%0\;AND.0 %1,0x0001,r15 %| ADD.1 %0,2,%0\;COPYNE 1,%0\;SUB.0 %1,0x0000,r15\;COPYEQ 0,%0"
|
|
1983 [(set_attr "length" "20")])
|
|
1984
|
|
1985 ;;===========================================================================
|
|
1986 ;; Tablejump Instruction. Jump to an absolute address.
|
|
1987 ;;===========================================================================
|
|
1988
|
|
1989 (define_insn "tablejump"
|
|
1990 [(set (pc) (unspec:HI [(match_operand:HI 0 "register_operand" "r")] 1))
|
|
1991 (use (label_ref (match_operand 1 "" "")))
|
|
1992 (clobber (match_dup 0))]
|
|
1993 ""
|
|
1994 "JR (%0)\t // Table jump to %0 %>"
|
|
1995 [(set_attr "length" "2")
|
|
1996 (set_attr "type" "realBranch")])
|
|
1997
|
|
1998 ;; Given the memory address of a QImode value, and a scratch register,
|
|
1999 ;; store the memory operand into the given output operand. The scratch
|
|
2000 ;; operand will not conflict with either of the operands. The other
|
|
2001 ;; two operands may conflict with each other.
|
|
2002
|
|
2003 (define_insn "synthesised_loadqi_unaligned"
|
|
2004 [(set (match_operand:QI 0 "register_operand" "=r")
|
|
2005 (match_operand:QI 1 "memory_operand" "m"))
|
|
2006 (clobber (match_operand:HI 2 "register_operand" "=&r"))
|
|
2007 (clobber (reg:CC CC_REGNUM))]
|
|
2008 ""
|
|
2009 "// Synthesised loadqi %0 = Mem(%1) (Scratch %2)\n\tAND.0 %1,-2,%2\n\tLDW (%2)0,%0 %| AND.0 %1,1,%2\n\tLSL.0 %2,3,%2\n\tSUB.0 8,%2,%2\n\tLSL.0 %0,%2,%0\n\tASR.0 %0,8,%0"
|
|
2010 ; Approximate length only. Probably a little shorter than this.
|
|
2011 [(set_attr "length" "40")])
|
|
2012
|
|
2013 ;; Given a memory operand whose alignment is known (the HImode aligned
|
|
2014 ;; base is operand 0, and the number of bits by which to shift is in
|
|
2015 ;; operand 5),
|
|
2016 (define_expand "synthesised_storeqi_aligned"
|
|
2017 [; s1 = mem_op
|
|
2018 (set (match_operand:HI 2 "register_operand" "")
|
|
2019 (match_operand:HI 0 "memory_operand" ""))
|
|
2020 ; s1 = s1 and mask
|
|
2021 (parallel [(set (match_dup 2) (and:HI (match_dup 2) (match_dup 5)))
|
|
2022 (clobber (reg:CC CC_REGNUM))])
|
|
2023 ; s2 = source << bitShift
|
|
2024 (set (match_dup 3)
|
|
2025 (ashift:HI (subreg:HI (match_operand:QI 1 "register_operand" "") 0)
|
|
2026 (match_operand:HI 4 "const_int_operand" "")))
|
|
2027 ; s1 = s1 or s2
|
|
2028 (parallel [(set (match_dup 2) (ior:HI (match_dup 2) (match_dup 3)))
|
|
2029 (clobber (reg:CC CC_REGNUM))])
|
|
2030 ; mem_op = s1
|
|
2031 (set (match_dup 0) (match_dup 2))]
|
|
2032 "!TARGET_HAS_BYTE_ACCESS"
|
|
2033 {
|
|
2034 /* Create the byte mask 0xFF00. */
|
|
2035 operands[5] = gen_int_mode(((~0xFF) >> INTVAL (operands[4])), HImode);
|
|
2036 })
|
|
2037
|
|
2038 ;; Reload instructions. See picochip_secondary_reload for an
|
|
2039 ;; explanation of why an SI mode register is used as a scratch. The
|
|
2040 ;; memory operand must be stored in a register (i.e., it can't be an
|
|
2041 ;; offset to another register - this would require another scratch
|
|
2042 ;; register into which the address of the offset could be computed).
|
|
2043
|
|
2044 (define_expand "reload_inqi"
|
|
2045 [(parallel [(match_operand:QI 0 "register_operand" "=&r")
|
|
2046 (match_operand:QI 1 "memory_operand" "m")
|
|
2047 (match_operand:SI 2 "register_operand" "=&r")])]
|
|
2048 "!TARGET_HAS_BYTE_ACCESS"
|
|
2049 {
|
|
2050 rtx scratch, seq;
|
|
2051
|
|
2052 /* Get the scratch register. Given an SI mode value, we have a
|
|
2053 choice of two HI mode scratch registers, so we can be sure that at
|
|
2054 least one of the scratch registers will be different to the output
|
|
2055 register, operand[0]. */
|
|
2056
|
|
2057 if (REGNO (operands[0]) == REGNO (operands[2]))
|
|
2058 scratch = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
|
|
2059 else
|
|
2060 scratch = gen_rtx_REG (HImode, REGNO (operands[2]));
|
|
2061
|
|
2062 /* Ensure that the scratch doesn't overlap either of the other
|
|
2063 two operands - however, the other two may overlap each
|
|
2064 other. */
|
|
2065 gcc_assert (REGNO(scratch) != REGNO(operands[0]));
|
|
2066 gcc_assert (REGNO(scratch) != REGNO(operands[1]));
|
|
2067
|
|
2068 gcc_assert (GET_CODE (operands[1]) == MEM);
|
|
2069
|
|
2070 if (picochip_word_aligned_memory_reference(XEXP(operands[1], 0)))
|
|
2071 {
|
|
2072 /* Aligned reloads are easy, since they can use word-loads. */
|
|
2073 seq = gen_synthesised_loadqi_aligned(operands[0], operands[1], scratch);
|
|
2074 }
|
|
2075 else
|
|
2076 {
|
|
2077 /* Emit the instruction using a define_insn. */
|
|
2078 seq = gen_synthesised_loadqi_unaligned(operands[0], operands[1], scratch);
|
|
2079 }
|
|
2080 emit_insn (seq);
|
|
2081
|
|
2082 DONE;
|
|
2083
|
|
2084 })
|
|
2085
|
|
2086 (define_expand "reload_outqi"
|
|
2087 [(parallel [(match_operand 0 "memory_operand" "=m")
|
|
2088 (match_operand:QI 1 "register_operand" "r")
|
|
2089 (match_operand:SI 2 "register_operand" "=&r")])]
|
|
2090 "!TARGET_HAS_BYTE_ACCESS"
|
|
2091 {
|
|
2092 rtx scratch1 = gen_rtx_REG(HImode, REGNO(operands[2]));
|
|
2093 rtx scratch2 = gen_rtx_REG(HImode, REGNO(operands[2]) + 1);
|
|
2094 rtx seq;
|
|
2095
|
|
2096 gcc_assert (GET_CODE (operands[0]) == MEM);
|
|
2097
|
|
2098 if (picochip_word_aligned_memory_reference(XEXP(operands[0], 0)))
|
|
2099 {
|
|
2100 rtx alignedAddr, bitShift;
|
|
2101
|
|
2102 /* Convert the address of the known alignment into two operands
|
|
2103 * representing the aligned base address, and the number of shift bits
|
|
2104 * required to access the required value. */
|
|
2105 picochip_get_hi_aligned_mem(operands[0], &alignedAddr, &bitShift);
|
|
2106
|
|
2107 /* Emit an aligned store of the source, with the given bit offset. */
|
|
2108 seq = gen_synthesised_storeqi_aligned(alignedAddr, operands[1], scratch1, scratch2, bitShift);
|
|
2109
|
|
2110 }
|
|
2111 else
|
|
2112 {
|
|
2113 /* This isnt exercised at all. Moreover, with new devices, byte access
|
|
2114 is available in all variants. */
|
|
2115 gcc_unreachable();
|
|
2116 }
|
|
2117
|
|
2118 emit_insn (seq);
|
|
2119 DONE;
|
|
2120
|
|
2121 })
|
|
2122
|
|
2123 ;; Perform a byte load of an alignable memory operand.
|
|
2124 ; op0 = register to load. op1 = memory operand from which to load
|
|
2125 ; op2 = op1, aligned to HI, op3 = const bit shift required to extract byte,
|
|
2126 ; op4 = INTVAL(8 - op3)
|
|
2127 (define_expand "synthesised_loadqi_aligned"
|
|
2128 [; Load memory operand into register
|
|
2129 (set (match_operand:HI 2 "register_operand" "=r")
|
|
2130 (match_dup 3))
|
|
2131 ; Shift required byte into top byte of word.
|
|
2132 (set (match_dup 2)
|
|
2133 (ashift:HI (match_dup 2)
|
|
2134 (match_dup 4)))
|
|
2135 ; Arithmetic shift of byte to sign extend, and move to lowest register.
|
|
2136 (parallel[(set (subreg:HI (match_dup 0) 0)
|
|
2137 (ashiftrt:HI (match_dup 2)
|
|
2138 (const_int 8)))
|
|
2139 (clobber (reg:CC CC_REGNUM))])
|
|
2140 (use (match_operand:QI 1 "picochip_alignable_memory_operand" "g"))]
|
|
2141 "!TARGET_HAS_BYTE_ACCESS"
|
|
2142 {
|
|
2143 rtx alignedAddr, bitShift;
|
|
2144
|
|
2145 /* Convert the address of the known alignment into two operands
|
|
2146 * representing the aligned base address, and the number of shift bits
|
|
2147 * required to access the required value. */
|
|
2148 picochip_get_hi_aligned_mem(operands[1], &alignedAddr, &bitShift);
|
|
2149
|
|
2150 operands[3] = alignedAddr;
|
|
2151 operands[4] = GEN_INT(8 - INTVAL(bitShift));
|
|
2152 })
|
|
2153
|
|
2154 ;;============================================================================
|
|
2155 ;; Special instructions.
|
|
2156 ;;============================================================================
|
|
2157
|
|
2158 ; Count sign-bits.
|
|
2159 (define_insn "sbc"
|
|
2160 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2161 (unspec:HI [(match_operand:HI 1 "register_operand" "r")]
|
|
2162 UNSPEC_SBC))]
|
|
2163 ""
|
|
2164 "SBC %1,%0\t\t// %0 := SBC(%1)"
|
|
2165 [(set_attr "type" "picoAlu")
|
|
2166 (set_attr "length" "2")])
|
|
2167
|
|
2168 ; Bit reversal.
|
|
2169 (define_insn "brev"
|
|
2170 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2171 (unspec:HI [(match_operand:HI 1 "register_operand" "r")]
|
|
2172 UNSPEC_BREV))]
|
|
2173 ""
|
|
2174 "BREV %1,%0\t\t// %0 := BREV(%1)"
|
|
2175 [(set_attr "length" "2")
|
|
2176 (set_attr "type" "picoAlu")])
|
|
2177
|
|
2178 ; Byte swap.
|
|
2179 (define_insn "bswaphi2"
|
|
2180 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2181 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
|
|
2182 ""
|
|
2183 "BYTESWAP %1,%0\t\t// %0 := ByteSwap(%1)"
|
|
2184 [(set_attr "length" "2")
|
|
2185 (set_attr "type" "picoAlu")])
|
|
2186
|
|
2187 ; Read status word.
|
|
2188 (define_insn "copysw"
|
|
2189 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2190 (unspec_volatile:HI [(reg:CC CC_REGNUM)] UNSPEC_COPYSW))]
|
|
2191 ""
|
|
2192 "COPYSW.%# %0\t// %0 := Flags"
|
|
2193 [(set_attr "type" "basicAlu")
|
|
2194 (set_attr "length" "2")])
|
|
2195
|
|
2196 ; Saturating addition.
|
|
2197 (define_insn "sataddhi3"
|
|
2198 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2199 (unspec:HI [(match_operand:HI 1 "register_operand" "r")
|
|
2200 (match_operand:HI 2 "register_operand" "r")]
|
|
2201 UNSPEC_ADDS))
|
|
2202 (clobber (reg:CC CC_REGNUM))]
|
|
2203 ""
|
|
2204 "ADDS %1,%2,%0\t// %0 := sat(%1 + %2)"
|
|
2205 [(set_attr "type" "picoAlu")
|
|
2206 (set_attr "length" "3")])
|
|
2207
|
|
2208 ; Saturating subtraction.
|
|
2209 (define_insn "satsubhi3"
|
|
2210 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2211 (unspec:HI [(match_operand:HI 1 "register_operand" "r")
|
|
2212 (match_operand:HI 2 "register_operand" "r")]
|
|
2213 UNSPEC_SUBS))
|
|
2214 (clobber (reg:CC CC_REGNUM))]
|
|
2215 ""
|
|
2216 "SUBS %1,%2,%0\t// %0 := sat(%1 - %2)"
|
|
2217 [(set_attr "type" "picoAlu")
|
|
2218 (set_attr "length" "3")])
|
|
2219
|
|
2220 (define_insn "halt"
|
|
2221 [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "i")]
|
|
2222 UNSPEC_HALT)]
|
|
2223 ""
|
|
2224 "HALT\t// (id %0)"
|
|
2225 [(set_attr "length" "1")
|
|
2226 (set_attr "type" "unknown")])
|
|
2227
|
|
2228 (define_insn "internal_testport"
|
|
2229 [(set (reg:CC CC_REGNUM)
|
|
2230 (unspec_volatile:CC [(match_operand:HI 0 "const_int_operand" "i")]
|
|
2231 UNSPEC_INTERNAL_TESTPORT))]
|
|
2232 ""
|
|
2233 "TSTPORT %0"
|
|
2234 [(set_attr "length" "2")
|
|
2235 (set_attr "longConstant" "false")
|
|
2236 (set_attr "type" "picoAlu")])
|
|
2237
|
|
2238 ;;============================================================================
|
|
2239 ;; Communications builtins.
|
|
2240 ;;
|
|
2241 ;; Each builtin comes in two forms: a single port version, which maps
|
|
2242 ;; to a single instruction, and an array port version. The array port
|
|
2243 ;; version is treated as a special type of instruction, which is then
|
|
2244 ;; split into a number of smaller instructions, if the index of the
|
|
2245 ;; port can't be converted into a constant. When the RTL split is
|
|
2246 ;; performed, a function call is emitted, in which the index of the
|
|
2247 ;; port to use is used to compute the address of the function to call
|
|
2248 ;; (i.e., each array port is a function in its own right, and the
|
|
2249 ;; functions are stored as an array which is then indexed to determine
|
|
2250 ;; the correct function). The communication function port array is
|
|
2251 ;; created by the linker if and only if it is required (in a
|
|
2252 ;; collect2-like manner).
|
|
2253 ;;============================================================================
|
|
2254
|
|
2255 ; Simple scalar get.
|
|
2256 (define_insn "commsGet"
|
|
2257 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
2258 (unspec_volatile:SI
|
|
2259 [(match_operand:HI 1 "immediate_operand" "n")]
|
|
2260 UNSPEC_GET))]
|
|
2261 ""
|
|
2262 "GET %1,%R0\t// %R0 := PORT(%1)"
|
|
2263 [(set_attr "type" "comms")
|
|
2264 (set_attr "length" "2")])
|
|
2265
|
|
2266 ; Entry point for array get (the actual port index is computed as the
|
|
2267 ; sum of the index, and the base).
|
|
2268 ;
|
|
2269 ; op0 - Destination
|
|
2270 ; op1 - Requested port index
|
|
2271 ; op2 - size of port array (constant)
|
|
2272 ; op3 - base index of port array (constant)
|
|
2273
|
|
2274 (define_expand "commsArrayGet"
|
|
2275 [(parallel
|
|
2276 [(set (reg:SI 0)
|
|
2277 (unspec_volatile:SI [(match_operand:HI 1 "general_operand" "")
|
|
2278 (match_operand:HI 2 "immediate_operand" "")
|
|
2279 (match_operand:HI 3 "immediate_operand" "")]
|
|
2280 UNSPEC_CALL_GET_ARRAY))
|
|
2281 (clobber (reg:HI LINK_REGNUM))])
|
|
2282 (set (match_operand:SI 0 "register_operand" "") (reg:SI 0))]
|
|
2283 ""
|
|
2284 "")
|
|
2285
|
|
2286 ;; The actual array get instruction. When the array index is a constant,
|
|
2287 ;; an exact instruction may be generated. When the index is variable,
|
|
2288 ;; a call to a special function is generated. This code could be
|
|
2289 ;; split into individual RTL instructions, but it is so rarely
|
|
2290 ;; used, that we won't bother.
|
|
2291 (define_insn "*commsArrayGetInstruction"
|
|
2292 [(set (reg:SI 0)
|
|
2293 (unspec_volatile:SI [(match_operand:HI 0 "general_operand" "r,i")
|
|
2294 (match_operand:HI 1 "immediate_operand" "")
|
|
2295 (match_operand:HI 2 "immediate_operand" "")]
|
|
2296 UNSPEC_CALL_GET_ARRAY))
|
|
2297 (clobber (reg:HI LINK_REGNUM))]
|
|
2298 ""
|
|
2299 {
|
|
2300 return picochip_output_get_array (which_alternative, operands);
|
|
2301 })
|
|
2302
|
|
2303 ; Scalar Put instruction.
|
|
2304 (define_insn "commsPut"
|
|
2305 [(unspec_volatile [(match_operand:HI 0 "const_int_operand" "")
|
|
2306 (match_operand:SI 1 "register_operand" "r")]
|
|
2307 UNSPEC_PUT)]
|
|
2308 ""
|
|
2309 "PUT %R1,%0\t// PORT(%0) := %R1"
|
|
2310 [(set_attr "type" "comms")
|
|
2311 (set_attr "length" "2")])
|
|
2312
|
|
2313 ; Entry point for array put. The operands accepted are:
|
|
2314 ; op0 - Value to put
|
|
2315 ; op1 - Requested port index
|
|
2316 ; op2 - size of port array
|
|
2317 ; op3 - base index of port array
|
|
2318 ; The arguments are marshalled into the fixed registers, so that
|
|
2319 ; the actual put instruction can expand into a call if necessary
|
|
2320 ; (e.g., if the index is variable at run-time).
|
|
2321
|
|
2322 (define_expand "commsArrayPut"
|
|
2323 [(set (reg:SI 0) (match_operand:SI 0 "general_operand" ""))
|
|
2324 (parallel
|
|
2325 [(unspec_volatile [(match_operand:HI 1 "general_operand" "")
|
|
2326 (match_operand:HI 2 "immediate_operand" "")
|
|
2327 (match_operand:HI 3 "immediate_operand" "")]
|
|
2328 UNSPEC_CALL_PUT_ARRAY)
|
|
2329 (use (reg:SI 0))
|
|
2330 (clobber (reg:HI LINK_REGNUM))])]
|
|
2331 ""
|
|
2332 "")
|
|
2333
|
|
2334 ;; The actual array put instruction. When the array index is a constant,
|
|
2335 ;; an exact instruction may be generated. When the index is variable,
|
|
2336 ;; a call to a special function is generated. This code could be
|
|
2337 ;; split into individual RTL instructions, but it is so rarely
|
|
2338 ;; used, that we won't bother.
|
|
2339 (define_insn "*commsArrayPutInstruction"
|
|
2340 [(unspec_volatile [(match_operand:HI 0 "general_operand" "r,i")
|
|
2341 (match_operand:HI 1 "immediate_operand" "")
|
|
2342 (match_operand:HI 2 "immediate_operand" "")]
|
|
2343 UNSPEC_CALL_PUT_ARRAY)
|
|
2344 (use (reg:SI 0))
|
|
2345 (clobber (reg:HI LINK_REGNUM))]
|
|
2346 ""
|
|
2347 {
|
|
2348 return picochip_output_put_array (which_alternative, operands);
|
|
2349 })
|
|
2350
|
|
2351 ;; Scalar test port instruction.
|
|
2352 (define_insn "commsTestPort"
|
|
2353 [(set (match_operand:HI 0 "register_operand" "=r")
|
|
2354 (unspec_volatile:HI [(match_operand:HI 1 "const_int_operand" "")]
|
|
2355 UNSPEC_TESTPORT))
|
|
2356 (clobber (reg:CC CC_REGNUM))]
|
|
2357 ""
|
|
2358 "// %0 := TestPort(%1)\;TSTPORT %1\;COPYSW.0 %0\;AND.0 %0,8,%0"
|
|
2359 [(set_attr "length" "9")])
|
|
2360
|
|
2361 ; Entry point for array tstport (the actual port index is computed as the
|
|
2362 ; sum of the index, and the base).
|
|
2363 ;
|
|
2364 ; op0 - Test value.
|
|
2365 ; op1 - Requested port index
|
|
2366 ; op2 - size of port array (constant)
|
|
2367 ; op3 - base index of port array (constant)
|
|
2368
|
|
2369 (define_expand "commsArrayTestPort"
|
|
2370 [(parallel
|
|
2371 [(set (match_operand:HI 0 "register_operand" "")
|
|
2372 (unspec_volatile:HI [(match_operand:HI 1 "general_operand" "")
|
|
2373 (match_operand:HI 2 "immediate_operand" "")
|
|
2374 (match_operand:HI 3 "immediate_operand" "")]
|
|
2375 UNSPEC_CALL_TESTPORT_ARRAY))
|
|
2376 (clobber (reg:HI LINK_REGNUM))])]
|
|
2377 ""
|
|
2378 "")
|
|
2379
|
|
2380 ;; The actual array testport instruction. When the array index is a constant,
|
|
2381 ;; an exact instruction may be generated. When the index is variable,
|
|
2382 ;; a call to a special function is generated. This code could be
|
|
2383 ;; split into individual RTL instructions, but it is so rarely
|
|
2384 ;; used, that we won't bother.
|
|
2385 (define_insn "*commsArrayTestportInstruction"
|
|
2386 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
2387 (unspec_volatile:HI [(match_operand:HI 1 "general_operand" "r,i")
|
|
2388 (match_operand:HI 2 "immediate_operand" "")
|
|
2389 (match_operand:HI 3 "immediate_operand" "")]
|
|
2390 UNSPEC_CALL_TESTPORT_ARRAY))
|
|
2391 (clobber (reg:HI LINK_REGNUM))]
|
|
2392 ""
|
|
2393 {
|
|
2394 return picochip_output_testport_array (which_alternative, operands);
|
|
2395 })
|
|
2396
|
|
2397 ;; Merge a TSTPORT instruction with the branch to which it
|
|
2398 ;; relates. Often the TSTPORT function (generated by a built-in), is
|
|
2399 ;; used to control conditional execution. The normal sequence of
|
|
2400 ;; instructions would be:
|
|
2401 ;; TSTPORT p
|
|
2402 ;; COPYSW temp
|
|
2403 ;; AND temp, 0x0008, temp
|
|
2404 ;; SUB temp,0,discard
|
|
2405 ;; BEQ label
|
|
2406 ;; This can be made more efficient by detecting the special case where
|
|
2407 ;; the result of a TSTPORT is used to branch, to allow the following
|
|
2408 ;; RTL sequence to be generated instead:
|
|
2409 ;; TSTPORT p
|
|
2410 ;; BEQ label
|
|
2411 ;; A big saving in cycles and bytes!
|
|
2412
|
|
2413 (define_insn_and_split "tstport_branch"
|
|
2414 [(set (pc)
|
|
2415 (if_then_else
|
|
2416 (match_operator 0 "comparison_operator"
|
|
2417 [(unspec_volatile:HI
|
|
2418 [(match_operand:HI 1 "const_int_operand" "")]
|
|
2419 UNSPEC_TESTPORT)
|
|
2420 (const_int 0)])
|
|
2421 (label_ref (match_operand 2 "" ""))
|
|
2422 (pc)))
|
|
2423 (clobber (reg:CC CC_REGNUM))]
|
|
2424 ""
|
|
2425 "#"
|
|
2426 ""
|
|
2427 [(set (reg:CC CC_REGNUM)
|
|
2428 (unspec_volatile:CC [(match_dup 1)] UNSPEC_INTERNAL_TESTPORT))
|
|
2429 (parallel [(set (pc)
|
|
2430 (if_then_else
|
|
2431 (match_op_dup:HI 4 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
2432 (label_ref (match_dup 2))
|
|
2433 (pc)))
|
|
2434 (use (match_dup 3))])]
|
|
2435 "{
|
|
2436 /* Note that the sense of the branch is reversed, since we are
|
|
2437 * comparing flag != 0. */
|
|
2438 gcc_assert (GET_CODE(operands[0]) == NE || GET_CODE(operands[0]) == EQ);
|
|
2439 operands[4] = gen_rtx_fmt_ee(reverse_condition(GET_CODE(operands[0])),
|
|
2440 GET_MODE(operands[0]), XEXP(operands[0], 0), XEXP(operands[0], 1));
|
|
2441 operands[3] = GEN_INT (0);
|
|
2442 }")
|
|
2443
|
|
2444 ;;============================================================================
|
|
2445 ;; Epilogue/Epilogue expansion.
|
|
2446 ;;============================================================================
|
|
2447
|
|
2448 (define_expand "prologue"
|
|
2449 [(clobber (const_int 0))]
|
|
2450 ""
|
|
2451 {
|
|
2452 picochip_expand_prologue ();
|
|
2453 DONE;
|
|
2454 })
|
|
2455
|
|
2456 (define_expand "epilogue"
|
|
2457 [(use (const_int 0))]
|
|
2458 ""
|
|
2459 {
|
|
2460 picochip_expand_epilogue (FALSE);
|
|
2461 DONE;
|
|
2462 })
|
|
2463
|
|
2464 ;;============================================================================
|
|
2465 ;; Trap instruction. This is used to indicate an error. For the
|
|
2466 ;; picoChip processors this is handled by calling a HALT instruction,
|
|
2467 ;; which stops the processor.
|
|
2468 ;;============================================================================
|
|
2469
|
|
2470 (define_insn "trap"
|
|
2471 [(trap_if (const_int 1) (const_int 6))]
|
|
2472 ""
|
|
2473 "HALT\t// (Trap)"
|
|
2474 [(set_attr "length" "2")])
|
|
2475
|
|
2476 ;;============================================================================
|
|
2477 ;; Conditional copy instructions. Only equal/not-equal comparisons are
|
|
2478 ;; supported. All other types of comparison remain as branch
|
|
2479 ;; sequences.
|
|
2480 ;;============================================================================
|
|
2481
|
|
2482 ;; Define expand seems to consider the resulting two instructions to be
|
|
2483 ;; independent. It was moving the actual copy instruction further down
|
|
2484 ;; with a call instruction in between. The call was clobbering the CC
|
|
2485 ;; and hence the cond_copy was wrong. With a split, it works correctly.
|
|
2486 (define_expand "movhicc"
|
|
2487 [(set (reg:CC CC_REGNUM) (match_operand 1 "comparison_operator" ""))
|
|
2488 (parallel [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
2489 (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
2490 (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0")
|
|
2491 (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))
|
|
2492 (use (match_dup 4))])]
|
|
2493 ""
|
|
2494 {if (!picochip_check_conditional_copy (operands))
|
|
2495 FAIL;
|
|
2496 operands[4] = GEN_INT(GET_CODE(operands[1]));
|
|
2497 })
|
|
2498
|
|
2499 ;; We dont do any checks here. But this pattern is used only when movhicc
|
|
2500 ;; was checked. Put a "use" clause to make sure.
|
|
2501 (define_insn "*conditional_copy"
|
|
2502 [(set (match_operand:HI 0 "register_operand" "=r,r")
|
|
2503 (if_then_else:HI
|
|
2504 (match_operator:HI 4 "picochip_peephole_comparison_operator"
|
|
2505 [(reg:CC CC_REGNUM) (const_int 0)])
|
|
2506 (match_operand:HI 1 "picochip_register_or_immediate_operand" "0,0")
|
|
2507 (match_operand:HI 2 "picochip_register_or_immediate_operand" "r,i")))
|
|
2508 (use (match_operand:HI 3 "const_int_operand" ""))]
|
|
2509 ""
|
|
2510 {
|
|
2511
|
|
2512 gcc_assert (GET_CODE(operands[4]) == EQ || GET_CODE(operands[4]) == NE);
|
|
2513 /* Note that the comparison is reversed as the pattern matches
|
|
2514 the *else* part of the if_then_else */
|
|
2515 switch (GET_CODE(operands[4]))
|
|
2516 {
|
|
2517 case EQ: return "COPYNE %2,%0\t// if (NE) %0 := %2";
|
|
2518 case NE: return "COPYEQ %2,%0\t// if (EQ) %0 := %2";
|
|
2519 default:
|
|
2520 gcc_unreachable();
|
|
2521 }
|
|
2522 }
|
|
2523 [(set_attr "length" "2")
|
|
2524 (set_attr "type" "picoAlu,picoAlu")
|
|
2525 (set_attr "longConstant" "false,true")])
|
|
2526
|
|
2527 ;; cmphi - This needs to be defined, to ensure that the conditional
|
|
2528 ;; move works properly (because the if-cvt code uses this pattern to
|
|
2529 ;; build the conditional move, even though normally we use cbranch to
|
|
2530 ;; directly generate the instructions).
|
|
2531
|
|
2532 (define_expand "cmphi"
|
|
2533 [(match_operand:HI 0 "general_operand" "g")
|
|
2534 (match_operand:HI 1 "general_operand" "g")]
|
|
2535 ""
|
|
2536 "DONE;")
|
|
2537
|
|
2538 ;;============================================================================
|
|
2539 ;; Branch patterns - needed for conditional moves. This is because
|
|
2540 ;; they result in the bcc_gen_fctn array being initialised with the
|
|
2541 ;; code to define_expand the following, and this in turn means that
|
|
2542 ;; when noce_emit_cmove is called, the correct pattern can be
|
|
2543 ;; generated, based upon the assumed presence of the following. The
|
|
2544 ;; following are never actually used, because the earlier cbranch
|
|
2545 ;; patterns take precendence.
|
|
2546 ;;============================================================================
|
|
2547
|
|
2548 (define_expand "bne"
|
|
2549 [(set (pc)
|
|
2550 (if_then_else
|
|
2551 (ne (reg:CC CC_REGNUM) (const_int 0))
|
|
2552 (label_ref (match_operand 0 "" ""))
|
|
2553 (pc)))]
|
|
2554 ""
|
|
2555 "gcc_unreachable();")
|
|
2556
|
|
2557 (define_expand "beq"
|
|
2558 [(set (pc)
|
|
2559 (if_then_else
|
|
2560 (eq (reg:CC CC_REGNUM) (const_int 0))
|
|
2561 (label_ref (match_operand 0 "" ""))
|
|
2562 (pc)))]
|
|
2563 ""
|
|
2564 "gcc_unreachable();")
|
|
2565
|
|
2566 (define_expand "blt"
|
|
2567 [(set (pc)
|
|
2568 (if_then_else
|
|
2569 (lt (reg:CC CC_REGNUM) (const_int 0))
|
|
2570 (label_ref (match_operand 0 "" ""))
|
|
2571 (pc)))]
|
|
2572 ""
|
|
2573 "gcc_unreachable();")
|
|
2574
|
|
2575 (define_expand "bge"
|
|
2576 [(set (pc)
|
|
2577 (if_then_else
|
|
2578 (ge (reg:CC CC_REGNUM) (const_int 0))
|
|
2579 (label_ref (match_operand 0 "" ""))
|
|
2580 (pc)))]
|
|
2581 ""
|
|
2582 "gcc_unreachable();")
|
|
2583
|
|
2584 (define_expand "bgeu"
|
|
2585 [(set (pc)
|
|
2586 (if_then_else
|
|
2587 (geu (reg:CC CC_REGNUM) (const_int 0))
|
|
2588 (label_ref (match_operand 0 "" ""))
|
|
2589 (pc)))]
|
|
2590 ""
|
|
2591 "gcc_unreachable();")
|
|
2592
|
|
2593 (define_expand "bltu"
|
|
2594 [(set (pc)
|
|
2595 (if_then_else
|
|
2596 (ltu (reg:CC CC_REGNUM) (const_int 0))
|
|
2597 (label_ref (match_operand 0 "" ""))
|
|
2598 (pc)))]
|
|
2599 ""
|
|
2600 "gcc_unreachable();")
|
|
2601
|
|
2602 (define_expand "ble"
|
|
2603 [(set (pc)
|
|
2604 (if_then_else
|
|
2605 (le (reg:CC CC_REGNUM) (const_int 0))
|
|
2606 (label_ref (match_operand 0 "" ""))
|
|
2607 (pc)))]
|
|
2608 ""
|
|
2609 "gcc_unreachable();")
|
|
2610
|
|
2611 (define_expand "bgt"
|
|
2612 [(set (pc)
|
|
2613 (if_then_else
|
|
2614 (gt (reg:CC CC_REGNUM) (const_int 0))
|
|
2615 (label_ref (match_operand 0 "" ""))
|
|
2616 (pc)))]
|
|
2617 ""
|
|
2618 "gcc_unreachable();")
|
|
2619
|
|
2620 (define_expand "bleu"
|
|
2621 [(set (pc)
|
|
2622 (if_then_else
|
|
2623 (leu (reg:CC CC_REGNUM) (const_int 0))
|
|
2624 (label_ref (match_operand 0 "" ""))
|
|
2625 (pc)))]
|
|
2626 ""
|
|
2627 "gcc_unreachable();")
|
|
2628
|
|
2629 (define_expand "bgtu"
|
|
2630 [(set (pc)
|
|
2631 (if_then_else
|
|
2632 (gtu (reg:CC CC_REGNUM) (const_int 0))
|
|
2633 (label_ref (match_operand 0 "" ""))
|
|
2634 (pc)))]
|
|
2635 ""
|
|
2636 "gcc_unreachable();")
|
|
2637
|
|
2638 ;;============================================================================
|
|
2639 ;; Scheduling, including delay slot scheduling.
|
|
2640 ;;============================================================================
|
|
2641
|
|
2642 (automata_option "v")
|
|
2643 (automata_option "ndfa")
|
|
2644
|
|
2645 ;; Define each VLIW slot as a CPU resource. Note the three flavours of
|
|
2646 ;; branch. `realBranch' is an actual branch instruction. `macroBranch'
|
|
2647 ;; is a directive to the assembler, which may expand into multiple
|
|
2648 ;; instructions. `call' is an actual branch instruction, but one which
|
|
2649 ;; sets the link register, and hence can't be scheduled alongside
|
|
2650 ;; other instructions which set the link register. When the DFA
|
|
2651 ;; scheduler is fixed to prevent it scheduling a JL with an R12
|
|
2652 ;; setting register, the call type branches can be replaced by
|
|
2653 ;; realBranch types instead.
|
|
2654
|
|
2655 (define_attr "type"
|
|
2656 "picoAlu,basicAlu,nonCcAlu,mem,call,realBranch,macroBranch,mul,mac,app,comms,unknown"
|
|
2657 (const_string "unknown"))
|
|
2658
|
|
2659 (define_attr "schedType" "none,space,speed"
|
|
2660 (const (symbol_ref "picochip_schedule_type")))
|
|
2661
|
|
2662 ;; Define whether an instruction uses a long constant.
|
|
2663
|
|
2664 (define_attr "longConstant"
|
|
2665 "true,false" (const_string "false"))
|
|
2666
|
|
2667 ;; Define three EU slots.
|
|
2668 (define_query_cpu_unit "slot0,slot1,slot2")
|
|
2669
|
|
2670 ;; Pull in the pipeline descriptions for speed or space scheduling.
|
|
2671 (include "dfa_speed.md")
|
|
2672 (include "dfa_space.md")
|
|
2673
|
|
2674 ; Unknown instructions are assumed to take a single cycle, and use all
|
|
2675 ; slots. This enables them to actually output a sequence of
|
|
2676 ; instructions without any limitation. For the purposes of
|
|
2677 ; scheduling, unknown instructions are a pain, and should be removed
|
|
2678 ; completely. This means that RTL patterns should always be used to
|
|
2679 ; reduce complex sequences of instructions to individual instructions.
|
|
2680 (define_insn_reservation "unknownInsn" 1
|
|
2681 (eq_attr "type" "unknown")
|
|
2682 "(slot0+slot1+slot2)")
|
|
2683
|
|
2684 ; Allow any non-branch instructions to be placed in the branch
|
|
2685 ; slot. Branch slots are always executed.
|
|
2686 (define_delay (eq_attr "type" "realBranch,call")
|
|
2687 [(eq_attr "type" "!realBranch,macroBranch,call,unknown") (nil) (nil)])
|