Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/picochip/picochip.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
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)]) |