]>
Commit | Line | Data |
---|---|---|
8d2af3a2 DD |
1 | ;; ALU operations with zero extensions |
2 | ;; | |
a945c346 | 3 | ;; Copyright (C) 2015-2024 Free Software Foundation, Inc. |
8d2af3a2 DD |
4 | ;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu> |
5 | ;; | |
6 | ;; This file is part of GCC. | |
7 | ;; | |
8 | ;; GCC is free software; you can redistribute it and/or modify | |
9 | ;; it under the terms of the GNU General Public License as published by | |
10 | ;; the Free Software Foundation; either version 3, or (at your option) | |
11 | ;; any later version. | |
12 | ;; | |
13 | ;; GCC is distributed in the hope that it will be useful, | |
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ;; GNU General Public License for more details. | |
17 | ;; | |
18 | ;; You should have received a copy of the GNU General Public License | |
19 | ;; along with GCC; see the file COPYING3. If not see | |
20 | ;; <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ; All PRU ALU instructions automatically zero-extend their source operands, | |
23 | ; and zero-extract the result into the destination register. This is | |
24 | ; described in the machine description by defining a separate pattern | |
25 | ; for each possible combination of zero_extend and mode for input operands. | |
26 | ; | |
27 | ; An unfortunate side effect is that quite a few invalid RTL patterns are | |
28 | ; generated. For example: | |
29 | ; ... (zero_extend:SI (match_operand:SI ...)) ... | |
30 | ; These patterns are harmless since no pass should generate such RTL. This | |
31 | ; shortcut allows us to keep small and concise machine description patterns. | |
32 | ||
33 | ||
34 | (define_subst_attr "alu2_zext" "alu2_zext_subst" "_z" "_noz") | |
35 | ||
36 | (define_subst_attr "alu3_zext_op1" "alu3_zext_op1_subst" "_z1" "_noz1") | |
37 | (define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2") | |
38 | (define_subst_attr "alu3_zext" "alu3_zext_subst" "_z" "_noz") | |
39 | ||
5ace1776 DD |
40 | (define_subst_attr "lmbd_zext_op1" "lmbd_zext_op1_subst" "_z1" "_noz1") |
41 | (define_subst_attr "lmbd_zext_op2" "lmbd_zext_op2_subst" "_z2" "_noz2") | |
42 | (define_subst_attr "lmbd_zext" "lmbd_zext_subst" "_z" "_noz") | |
43 | ||
8d2af3a2 DD |
44 | (define_subst_attr "bitalu_zext" "bitalu_zext_subst" "_z" "_noz") |
45 | ||
46 | (define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift lshiftrt]) | |
47 | (define_code_iterator ALUOP2 [neg not]) | |
48 | ||
49 | ;; Arithmetic Operations | |
50 | ||
51 | (define_insn "add_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>" | |
52 | [(set (match_operand:EQD 0 "register_operand" "=r,r,r") | |
53 | (plus:EQD | |
54 | (zero_extend:EQD | |
55 | (match_operand:EQS0 1 "register_operand" "%r,r,r")) | |
56 | (zero_extend:EQD | |
57 | (match_operand:EQS1 2 "nonmemory_operand" "r,<EQS1:ubyte_constr>,M"))))] | |
58 | "" | |
59 | "@ | |
60 | add\\t%0, %1, %2 | |
61 | add\\t%0, %1, %u2 | |
62 | sub\\t%0, %1, %n2" | |
63 | [(set_attr "type" "alu")]) | |
64 | ||
65 | (define_insn "sub_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>" | |
66 | [(set (match_operand:EQD 0 "register_operand" "=r,r") | |
67 | (minus:EQD | |
68 | (zero_extend:EQD | |
69 | (match_operand:EQS0 1 "reg_or_ubyte_operand" "r,<EQS0:ubyte_constr>")) | |
70 | (zero_extend:EQD | |
71 | (match_operand:EQS1 2 "register_operand" "r,r"))))] | |
72 | "" | |
73 | "@ | |
74 | sub\\t%0, %1, %2 | |
75 | rsb\\t%0, %2, %u1" | |
76 | [(set_attr "type" "alu")]) | |
77 | ||
78 | ||
5ace1776 DD |
79 | ;; Left Most Bit Detect instruction. |
80 | (define_insn "pru_lmbd_impl<EQD:mode><EQS0:mode><EQS1:mode>_<lmbd_zext><lmbd_zext_op1><lmbd_zext_op2>" | |
81 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
82 | (unspec:EQD | |
83 | [(zero_extend:EQD | |
84 | (match_operand:EQS0 1 "register_operand" "r")) | |
85 | (zero_extend:EQD | |
86 | (match_operand:EQS1 2 "reg_or_ubyte_operand" "r<EQS1:ubyte_constr>"))] | |
87 | UNSPEC_LMBD))] | |
88 | "" | |
89 | "lmbd\t%0, %1, %2" | |
90 | [(set_attr "type" "alu")]) | |
91 | ||
8d2af3a2 DD |
92 | (define_insn "neg_impl<EQD:mode><EQS0:mode>_<alu2_zext>" |
93 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
94 | (neg:EQD | |
95 | (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))))] | |
96 | "" | |
97 | "rsb\\t%0, %1, 0" | |
98 | [(set_attr "type" "alu")]) | |
99 | ||
100 | ||
101 | (define_insn "one_cmpl_impl<EQD:mode><EQS0:mode>_<alu2_zext>" | |
102 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
103 | (not:EQD | |
104 | (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))))] | |
105 | "" | |
106 | "not\\t%0, %1" | |
107 | [(set_attr "type" "alu")]) | |
108 | ||
109 | ; Specialized IOR/AND patterns for matching setbit/clearbit instructions. | |
110 | ; | |
111 | ; TODO - allow clrbit and setbit to support (1 << REG) constructs | |
112 | ||
113 | (define_insn "clearbit_<EQD:mode><EQS0:mode>_<bitalu_zext>" | |
114 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
115 | (and:EQD | |
116 | (zero_extend:EQD | |
117 | (match_operand:EQS0 1 "register_operand" "r")) | |
118 | (match_operand:EQD 2 "single_zero_operand" "n")))] | |
119 | "" | |
120 | "clr\\t%0, %1, %V2" | |
121 | [(set_attr "type" "alu")]) | |
122 | ||
123 | (define_insn "setbit_<EQD:mode><EQS0:mode>_<bitalu_zext>" | |
124 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
125 | (ior:EQD | |
126 | (zero_extend:EQD | |
127 | (match_operand:EQS0 1 "register_operand" "r")) | |
128 | (match_operand:EQD 2 "single_one_operand" "n")))] | |
129 | "" | |
130 | "set\\t%0, %1, %T2" | |
131 | [(set_attr "type" "alu")]) | |
132 | ||
133 | ; Regular ALU ops | |
134 | (define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>" | |
135 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
136 | (LOGICAL:EQD | |
137 | (zero_extend:EQD | |
138 | (match_operand:EQS0 1 "register_operand" "%r")) | |
139 | (zero_extend:EQD | |
140 | (match_operand:EQS1 2 "reg_or_ubyte_operand" "r<EQS1:ubyte_constr>"))))] | |
141 | "" | |
142 | "<logical_asm>\\t%0, %1, %u2" | |
143 | [(set_attr "type" "alu")]) | |
144 | ||
145 | ; Shift ALU ops | |
146 | (define_insn "<shift_op>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>" | |
147 | [(set (match_operand:EQD 0 "register_operand" "=r") | |
148 | (SHIFT:EQD | |
149 | (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r")) | |
150 | (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))] | |
151 | "" | |
152 | "<shift_asm>\\t%0, %1, %2" | |
153 | [(set_attr "type" "alu")]) | |
154 | ||
155 | ;; Substitutions | |
156 | ||
157 | (define_subst "alu2_zext_subst" | |
158 | [(set (match_operand:EQD 0) | |
159 | (ALUOP2:EQD (zero_extend:EQD (match_operand:EQD 1))))] | |
160 | "" | |
161 | [(set (match_dup 0) | |
162 | (ALUOP2:EQD (match_dup 1)))]) | |
163 | ||
164 | (define_subst "bitalu_zext_subst" | |
165 | [(set (match_operand:EQD 0) | |
166 | (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1)) | |
167 | (match_operand:EQD 2)))] | |
168 | "" | |
169 | [(set (match_dup 0) | |
170 | (ALUOP3:EQD (match_dup 1) | |
171 | (match_dup 2)))]) | |
172 | ||
173 | (define_subst "alu3_zext_subst" | |
174 | [(set (match_operand:EQD 0) | |
175 | (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1)) | |
176 | (zero_extend:EQD (match_operand:EQD 2))))] | |
177 | "" | |
178 | [(set (match_dup 0) | |
179 | (ALUOP3:EQD (match_dup 1) | |
180 | (match_dup 2)))]) | |
181 | ||
182 | (define_subst "alu3_zext_op1_subst" | |
183 | [(set (match_operand:EQD 0) | |
184 | (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1)) | |
185 | (zero_extend:EQD (match_operand:EQS1 2))))] | |
186 | "" | |
187 | [(set (match_dup 0) | |
188 | (ALUOP3:EQD (match_dup 1) | |
189 | (zero_extend:EQD (match_dup 2))))]) | |
190 | ||
191 | (define_subst "alu3_zext_op2_subst" | |
192 | [(set (match_operand:EQD 0) | |
193 | (ALUOP3:EQD (zero_extend:EQD (match_operand:EQS0 1)) | |
194 | (zero_extend:EQD (match_operand:EQD 2))))] | |
195 | "" | |
196 | [(set (match_dup 0) | |
197 | (ALUOP3:EQD (zero_extend:EQD (match_dup 1)) | |
198 | (match_dup 2)))]) | |
5ace1776 DD |
199 | |
200 | ||
201 | (define_subst "lmbd_zext_subst" | |
202 | [(set (match_operand:EQD 0) | |
203 | (unspec:EQD [(zero_extend:EQD (match_operand:EQD 1)) | |
204 | (zero_extend:EQD (match_operand:EQD 2))] | |
205 | UNSPEC_LMBD))] | |
206 | "" | |
207 | [(set (match_dup 0) | |
208 | (unspec:EQD [(match_dup 1) | |
209 | (match_dup 2)] | |
210 | UNSPEC_LMBD))]) | |
211 | ||
212 | (define_subst "lmbd_zext_op1_subst" | |
213 | [(set (match_operand:EQD 0) | |
214 | (unspec:EQD [(zero_extend:EQD (match_operand:EQD 1)) | |
215 | (zero_extend:EQD (match_operand:EQS1 2))] | |
216 | UNSPEC_LMBD))] | |
217 | "" | |
218 | [(set (match_dup 0) | |
219 | (unspec:EQD [(match_dup 1) | |
220 | (zero_extend:EQD (match_dup 2))] | |
221 | UNSPEC_LMBD))]) | |
222 | ||
223 | (define_subst "lmbd_zext_op2_subst" | |
224 | [(set (match_operand:EQD 0) | |
225 | (unspec:EQD [(zero_extend:EQD (match_operand:EQD 1)) | |
226 | (zero_extend:EQD (match_operand:EQD 2))] | |
227 | UNSPEC_LMBD))] | |
228 | "" | |
229 | [(set (match_dup 0) | |
230 | (unspec:EQD [(zero_extend:EQD (match_dup 1)) | |
231 | (match_dup 2)] | |
232 | UNSPEC_LMBD))]) |