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