Mercurial > hg > CbC > CbC_gcc
annotate gcc/config/stormy16/stormy16.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
rev | line source |
---|---|
0 | 1 /* Xstormy16 target functions. |
131 | 2 Copyright (C) 1997-2018 Free Software Foundation, Inc. |
0 | 3 Contributed by Red Hat, Inc. |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify | |
8 it under the terms of the GNU General Public License as published by | |
9 the Free Software Foundation; either version 3, or (at your option) | |
10 any later version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
131 | 21 #define IN_TARGET_CODE 1 |
22 | |
0 | 23 #include "config.h" |
24 #include "system.h" | |
25 #include "coretypes.h" | |
111 | 26 #include "backend.h" |
27 #include "target.h" | |
0 | 28 #include "rtl.h" |
111 | 29 #include "tree.h" |
30 #include "stringpool.h" | |
31 #include "attribs.h" | |
32 #include "gimple.h" | |
33 #include "df.h" | |
34 #include "memmodel.h" | |
35 #include "tm_p.h" | |
36 #include "stringpool.h" | |
37 #include "optabs.h" | |
38 #include "emit-rtl.h" | |
0 | 39 #include "recog.h" |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
40 #include "diagnostic-core.h" |
111 | 41 #include "output.h" |
42 #include "fold-const.h" | |
43 #include "stor-layout.h" | |
44 #include "varasm.h" | |
45 #include "calls.h" | |
46 #include "explow.h" | |
0 | 47 #include "expr.h" |
111 | 48 #include "langhooks.h" |
49 #include "cfgrtl.h" | |
50 #include "gimplify.h" | |
51 #include "reload.h" | |
52 #include "builtins.h" | |
53 | |
54 /* This file should be included last. */ | |
0 | 55 #include "target-def.h" |
56 | |
57 static rtx emit_addhi3_postreload (rtx, rtx, rtx); | |
58 static void xstormy16_asm_out_constructor (rtx, int); | |
59 static void xstormy16_asm_out_destructor (rtx, int); | |
60 static void xstormy16_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, | |
61 HOST_WIDE_INT, tree); | |
62 | |
63 static void xstormy16_init_builtins (void); | |
111 | 64 static rtx xstormy16_expand_builtin (tree, rtx, rtx, machine_mode, int); |
65 static int xstormy16_address_cost (rtx, machine_mode, addr_space_t, bool); | |
0 | 66 static bool xstormy16_return_in_memory (const_tree, const_tree); |
67 | |
68 static GTY(()) section *bss100_section; | |
69 | |
70 /* Compute a (partial) cost for rtx X. Return true if the complete | |
71 cost has been computed, and false if subexpressions should be | |
72 scanned. In either case, *TOTAL contains the cost result. */ | |
73 | |
74 static bool | |
111 | 75 xstormy16_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, |
76 int outer_code ATTRIBUTE_UNUSED, | |
77 int opno ATTRIBUTE_UNUSED, int *total, | |
78 bool speed ATTRIBUTE_UNUSED) | |
0 | 79 { |
111 | 80 int code = GET_CODE (x); |
81 | |
0 | 82 switch (code) |
83 { | |
84 case CONST_INT: | |
85 if (INTVAL (x) < 16 && INTVAL (x) >= 0) | |
86 *total = COSTS_N_INSNS (1) / 2; | |
87 else if (INTVAL (x) < 256 && INTVAL (x) >= 0) | |
88 *total = COSTS_N_INSNS (1); | |
89 else | |
90 *total = COSTS_N_INSNS (2); | |
91 return true; | |
92 | |
93 case CONST_DOUBLE: | |
94 case CONST: | |
95 case SYMBOL_REF: | |
96 case LABEL_REF: | |
97 *total = COSTS_N_INSNS (2); | |
98 return true; | |
99 | |
100 case MULT: | |
101 *total = COSTS_N_INSNS (35 + 6); | |
102 return true; | |
103 case DIV: | |
104 *total = COSTS_N_INSNS (51 - 6); | |
105 return true; | |
106 | |
107 default: | |
108 return false; | |
109 } | |
110 } | |
111 | |
112 static int | |
111 | 113 xstormy16_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED, |
114 addr_space_t as ATTRIBUTE_UNUSED, | |
115 bool speed ATTRIBUTE_UNUSED) | |
0 | 116 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
117 return (CONST_INT_P (x) ? 2 |
0 | 118 : GET_CODE (x) == PLUS ? 7 |
119 : 5); | |
120 } | |
121 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
122 /* Worker function for TARGET_MEMORY_MOVE_COST. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
123 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
124 static int |
111 | 125 xstormy16_memory_move_cost (machine_mode mode, reg_class_t rclass, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
126 bool in) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
127 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
128 return (5 + memory_move_secondary_cost (mode, rclass, in)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
129 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
130 |
0 | 131 /* Branches are handled as follows: |
132 | |
133 1. HImode compare-and-branches. The machine supports these | |
134 natively, so the appropriate pattern is emitted directly. | |
135 | |
136 2. SImode EQ and NE. These are emitted as pairs of HImode | |
137 compare-and-branches. | |
138 | |
139 3. SImode LT, GE, LTU and GEU. These are emitted as a sequence | |
140 of a SImode subtract followed by a branch (not a compare-and-branch), | |
141 like this: | |
142 sub | |
143 sbc | |
144 blt | |
145 | |
146 4. SImode GT, LE, GTU, LEU. These are emitted as a sequence like: | |
147 sub | |
148 sbc | |
149 blt | |
150 or | |
151 bne. */ | |
152 | |
153 /* Emit a branch of kind CODE to location LOC. */ | |
154 | |
155 void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
156 xstormy16_emit_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx loc) |
0 | 157 { |
158 rtx condition_rtx, loc_ref, branch, cy_clobber; | |
159 rtvec vec; | |
111 | 160 machine_mode mode; |
0 | 161 |
162 mode = GET_MODE (op0); | |
163 gcc_assert (mode == HImode || mode == SImode); | |
164 | |
165 if (mode == SImode | |
166 && (code == GT || code == LE || code == GTU || code == LEU)) | |
167 { | |
168 int unsigned_p = (code == GTU || code == LEU); | |
169 int gt_p = (code == GT || code == GTU); | |
170 rtx lab = NULL_RTX; | |
171 | |
172 if (gt_p) | |
173 lab = gen_label_rtx (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
174 xstormy16_emit_cbranch (unsigned_p ? LTU : LT, op0, op1, gt_p ? lab : loc); |
0 | 175 /* This should be generated as a comparison against the temporary |
176 created by the previous insn, but reload can't handle that. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
177 xstormy16_emit_cbranch (gt_p ? NE : EQ, op0, op1, loc); |
0 | 178 if (gt_p) |
179 emit_label (lab); | |
180 return; | |
181 } | |
182 else if (mode == SImode | |
183 && (code == NE || code == EQ) | |
184 && op1 != const0_rtx) | |
185 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
186 rtx op0_word, op1_word; |
0 | 187 rtx lab = NULL_RTX; |
188 int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; | |
189 int i; | |
190 | |
191 if (code == EQ) | |
192 lab = gen_label_rtx (); | |
193 | |
194 for (i = 0; i < num_words - 1; i++) | |
195 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
196 op0_word = simplify_gen_subreg (word_mode, op0, mode, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
197 i * UNITS_PER_WORD); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
198 op1_word = simplify_gen_subreg (word_mode, op1, mode, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
199 i * UNITS_PER_WORD); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
200 xstormy16_emit_cbranch (NE, op0_word, op1_word, code == EQ ? lab : loc); |
0 | 201 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
202 op0_word = simplify_gen_subreg (word_mode, op0, mode, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
203 i * UNITS_PER_WORD); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
204 op1_word = simplify_gen_subreg (word_mode, op1, mode, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
205 i * UNITS_PER_WORD); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
206 xstormy16_emit_cbranch (code, op0_word, op1_word, loc); |
0 | 207 |
208 if (code == EQ) | |
209 emit_label (lab); | |
210 return; | |
211 } | |
212 | |
213 /* We can't allow reload to try to generate any reload after a branch, | |
214 so when some register must match we must make the temporary ourselves. */ | |
215 if (mode != HImode) | |
216 { | |
217 rtx tmp; | |
218 tmp = gen_reg_rtx (mode); | |
219 emit_move_insn (tmp, op0); | |
220 op0 = tmp; | |
221 } | |
222 | |
223 condition_rtx = gen_rtx_fmt_ee (code, mode, op0, op1); | |
224 loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc); | |
111 | 225 branch = gen_rtx_SET (pc_rtx, |
0 | 226 gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx, |
227 loc_ref, pc_rtx)); | |
228 | |
229 cy_clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, CARRY_REGNUM)); | |
230 | |
231 if (mode == HImode) | |
232 vec = gen_rtvec (2, branch, cy_clobber); | |
233 else if (code == NE || code == EQ) | |
234 vec = gen_rtvec (2, branch, gen_rtx_CLOBBER (VOIDmode, op0)); | |
235 else | |
236 { | |
237 rtx sub; | |
238 #if 0 | |
111 | 239 sub = gen_rtx_SET (op0, gen_rtx_MINUS (SImode, op0, op1)); |
0 | 240 #else |
241 sub = gen_rtx_CLOBBER (SImode, op0); | |
242 #endif | |
243 vec = gen_rtvec (3, branch, sub, cy_clobber); | |
244 } | |
245 | |
246 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec)); | |
247 } | |
248 | |
249 /* Take a SImode conditional branch, one of GT/LE/GTU/LEU, and split | |
250 the arithmetic operation. Most of the work is done by | |
251 xstormy16_expand_arith. */ | |
252 | |
253 void | |
111 | 254 xstormy16_split_cbranch (machine_mode mode, rtx label, rtx comparison, |
0 | 255 rtx dest) |
256 { | |
257 rtx op0 = XEXP (comparison, 0); | |
258 rtx op1 = XEXP (comparison, 1); | |
111 | 259 rtx_insn *seq, *last_insn; |
0 | 260 rtx compare; |
261 | |
262 start_sequence (); | |
263 xstormy16_expand_arith (mode, COMPARE, dest, op0, op1); | |
264 seq = get_insns (); | |
265 end_sequence (); | |
266 | |
267 gcc_assert (INSN_P (seq)); | |
268 | |
269 last_insn = seq; | |
270 while (NEXT_INSN (last_insn) != NULL_RTX) | |
271 last_insn = NEXT_INSN (last_insn); | |
272 | |
273 compare = SET_SRC (XVECEXP (PATTERN (last_insn), 0, 0)); | |
274 PUT_CODE (XEXP (compare, 0), GET_CODE (comparison)); | |
275 XEXP (compare, 1) = gen_rtx_LABEL_REF (VOIDmode, label); | |
276 emit_insn (seq); | |
277 } | |
278 | |
279 | |
280 /* Return the string to output a conditional branch to LABEL, which is | |
281 the operand number of the label. | |
282 | |
283 OP is the conditional expression, or NULL for branch-always. | |
284 | |
285 REVERSED is nonzero if we should reverse the sense of the comparison. | |
286 | |
287 INSN is the insn. */ | |
288 | |
289 char * | |
111 | 290 xstormy16_output_cbranch_hi (rtx op, const char *label, int reversed, |
291 rtx_insn *insn) | |
0 | 292 { |
293 static char string[64]; | |
294 int need_longbranch = (op != NULL_RTX | |
295 ? get_attr_length (insn) == 8 | |
296 : get_attr_length (insn) == 4); | |
297 int really_reversed = reversed ^ need_longbranch; | |
298 const char *ccode; | |
299 const char *templ; | |
300 const char *operands; | |
301 enum rtx_code code; | |
302 | |
303 if (! op) | |
304 { | |
305 if (need_longbranch) | |
306 ccode = "jmpf"; | |
307 else | |
308 ccode = "br"; | |
309 sprintf (string, "%s %s", ccode, label); | |
310 return string; | |
311 } | |
312 | |
313 code = GET_CODE (op); | |
314 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
315 if (! REG_P (XEXP (op, 0))) |
0 | 316 { |
317 code = swap_condition (code); | |
318 operands = "%3,%2"; | |
319 } | |
320 else | |
321 operands = "%2,%3"; | |
322 | |
323 /* Work out which way this really branches. */ | |
324 if (really_reversed) | |
325 code = reverse_condition (code); | |
326 | |
327 switch (code) | |
328 { | |
329 case EQ: ccode = "z"; break; | |
330 case NE: ccode = "nz"; break; | |
331 case GE: ccode = "ge"; break; | |
332 case LT: ccode = "lt"; break; | |
333 case GT: ccode = "gt"; break; | |
334 case LE: ccode = "le"; break; | |
335 case GEU: ccode = "nc"; break; | |
336 case LTU: ccode = "c"; break; | |
337 case GTU: ccode = "hi"; break; | |
338 case LEU: ccode = "ls"; break; | |
339 | |
340 default: | |
341 gcc_unreachable (); | |
342 } | |
343 | |
344 if (need_longbranch) | |
345 templ = "b%s %s,.+8 | jmpf %s"; | |
346 else | |
347 templ = "b%s %s,%s"; | |
348 sprintf (string, templ, ccode, operands, label); | |
349 | |
350 return string; | |
351 } | |
352 | |
353 /* Return the string to output a conditional branch to LABEL, which is | |
354 the operand number of the label, but suitable for the tail of a | |
355 SImode branch. | |
356 | |
357 OP is the conditional expression (OP is never NULL_RTX). | |
358 | |
359 REVERSED is nonzero if we should reverse the sense of the comparison. | |
360 | |
361 INSN is the insn. */ | |
362 | |
363 char * | |
111 | 364 xstormy16_output_cbranch_si (rtx op, const char *label, int reversed, |
365 rtx_insn *insn) | |
0 | 366 { |
367 static char string[64]; | |
368 int need_longbranch = get_attr_length (insn) >= 8; | |
369 int really_reversed = reversed ^ need_longbranch; | |
370 const char *ccode; | |
371 const char *templ; | |
372 char prevop[16]; | |
373 enum rtx_code code; | |
374 | |
375 code = GET_CODE (op); | |
376 | |
377 /* Work out which way this really branches. */ | |
378 if (really_reversed) | |
379 code = reverse_condition (code); | |
380 | |
381 switch (code) | |
382 { | |
383 case EQ: ccode = "z"; break; | |
384 case NE: ccode = "nz"; break; | |
385 case GE: ccode = "ge"; break; | |
386 case LT: ccode = "lt"; break; | |
387 case GEU: ccode = "nc"; break; | |
388 case LTU: ccode = "c"; break; | |
389 | |
390 /* The missing codes above should never be generated. */ | |
391 default: | |
392 gcc_unreachable (); | |
393 } | |
394 | |
395 switch (code) | |
396 { | |
397 case EQ: case NE: | |
398 { | |
399 int regnum; | |
400 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
401 gcc_assert (REG_P (XEXP (op, 0))); |
0 | 402 |
403 regnum = REGNO (XEXP (op, 0)); | |
404 sprintf (prevop, "or %s,%s", reg_names[regnum], reg_names[regnum+1]); | |
405 } | |
406 break; | |
407 | |
408 case GE: case LT: case GEU: case LTU: | |
409 strcpy (prevop, "sbc %2,%3"); | |
410 break; | |
411 | |
412 default: | |
413 gcc_unreachable (); | |
414 } | |
415 | |
416 if (need_longbranch) | |
417 templ = "%s | b%s .+6 | jmpf %s"; | |
418 else | |
419 templ = "%s | b%s %s"; | |
420 sprintf (string, templ, prevop, ccode, label); | |
421 | |
422 return string; | |
423 } | |
424 | |
425 /* Many machines have some registers that cannot be copied directly to or from | |
426 memory or even from other types of registers. An example is the `MQ' | |
427 register, which on most machines, can only be copied to or from general | |
428 registers, but not memory. Some machines allow copying all registers to and | |
429 from memory, but require a scratch register for stores to some memory | |
430 locations (e.g., those with symbolic address on the RT, and those with | |
431 certain symbolic address on the SPARC when compiling PIC). In some cases, | |
432 both an intermediate and a scratch register are required. | |
433 | |
434 You should define these macros to indicate to the reload phase that it may | |
435 need to allocate at least one register for a reload in addition to the | |
436 register to contain the data. Specifically, if copying X to a register | |
437 RCLASS in MODE requires an intermediate register, you should define | |
438 `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of | |
439 whose registers can be used as intermediate registers or scratch registers. | |
440 | |
441 If copying a register RCLASS in MODE to X requires an intermediate or scratch | |
442 register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the | |
443 largest register class required. If the requirements for input and output | |
444 reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used | |
445 instead of defining both macros identically. | |
446 | |
447 The values returned by these macros are often `GENERAL_REGS'. Return | |
448 `NO_REGS' if no spare register is needed; i.e., if X can be directly copied | |
449 to or from a register of RCLASS in MODE without requiring a scratch register. | |
450 Do not define this macro if it would always return `NO_REGS'. | |
451 | |
452 If a scratch register is required (either with or without an intermediate | |
453 register), you should define patterns for `reload_inM' or `reload_outM', as | |
454 required.. These patterns, which will normally be implemented with a | |
455 `define_expand', should be similar to the `movM' patterns, except that | |
456 operand 2 is the scratch register. | |
457 | |
458 Define constraints for the reload register and scratch register that contain | |
459 a single register class. If the original reload register (whose class is | |
460 RCLASS) can meet the constraint given in the pattern, the value returned by | |
461 these macros is used for the class of the scratch register. Otherwise, two | |
462 additional reload registers are required. Their classes are obtained from | |
463 the constraints in the insn pattern. | |
464 | |
465 X might be a pseudo-register or a `subreg' of a pseudo-register, which could | |
466 either be in a hard register or in memory. Use `true_regnum' to find out; | |
467 it will return -1 if the pseudo is in memory and the hard register number if | |
468 it is in a register. | |
469 | |
470 These macros should not be used in the case where a particular class of | |
471 registers can only be copied to memory and not to another class of | |
472 registers. In that case, secondary reload registers are not needed and | |
473 would not be helpful. Instead, a stack location must be used to perform the | |
474 copy and the `movM' pattern should use memory as an intermediate storage. | |
475 This case often occurs between floating-point and general registers. */ | |
476 | |
477 enum reg_class | |
478 xstormy16_secondary_reload_class (enum reg_class rclass, | |
111 | 479 machine_mode mode ATTRIBUTE_UNUSED, |
0 | 480 rtx x) |
481 { | |
482 /* This chip has the interesting property that only the first eight | |
483 registers can be moved to/from memory. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
484 if ((MEM_P (x) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
485 || ((GET_CODE (x) == SUBREG || REG_P (x)) |
0 | 486 && (true_regnum (x) == -1 |
487 || true_regnum (x) >= FIRST_PSEUDO_REGISTER))) | |
488 && ! reg_class_subset_p (rclass, EIGHT_REGS)) | |
489 return EIGHT_REGS; | |
490 | |
491 return NO_REGS; | |
492 } | |
493 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
494 /* Worker function for TARGET_PREFERRED_RELOAD_CLASS |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
495 and TARGET_PREFERRED_OUTPUT_RELOAD_CLASS. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
496 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
497 static reg_class_t |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
498 xstormy16_preferred_reload_class (rtx x, reg_class_t rclass) |
0 | 499 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
500 if (rclass == GENERAL_REGS && MEM_P (x)) |
0 | 501 return EIGHT_REGS; |
502 | |
503 return rclass; | |
504 } | |
505 | |
506 /* Predicate for symbols and addresses that reflect special 8-bit | |
507 addressing. */ | |
508 | |
509 int | |
510 xstormy16_below100_symbol (rtx x, | |
111 | 511 machine_mode mode ATTRIBUTE_UNUSED) |
0 | 512 { |
513 if (GET_CODE (x) == CONST) | |
514 x = XEXP (x, 0); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
515 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))) |
0 | 516 x = XEXP (x, 0); |
517 | |
518 if (GET_CODE (x) == SYMBOL_REF) | |
519 return (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_XSTORMY16_BELOW100) != 0; | |
520 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
521 if (CONST_INT_P (x)) |
0 | 522 { |
523 HOST_WIDE_INT i = INTVAL (x); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
524 |
0 | 525 if ((i >= 0x0000 && i <= 0x00ff) |
526 || (i >= 0x7f00 && i <= 0x7fff)) | |
527 return 1; | |
528 } | |
529 return 0; | |
530 } | |
531 | |
532 /* Likewise, but only for non-volatile MEMs, for patterns where the | |
533 MEM will get split into smaller sized accesses. */ | |
534 | |
535 int | |
111 | 536 xstormy16_splittable_below100_operand (rtx x, machine_mode mode) |
0 | 537 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
538 if (MEM_P (x) && MEM_VOLATILE_P (x)) |
0 | 539 return 0; |
540 return xstormy16_below100_operand (x, mode); | |
541 } | |
542 | |
543 /* Expand an 8-bit IOR. This either detects the one case we can | |
544 actually do, or uses a 16-bit IOR. */ | |
545 | |
546 void | |
547 xstormy16_expand_iorqi3 (rtx *operands) | |
548 { | |
549 rtx in, out, outsub, val; | |
550 | |
551 out = operands[0]; | |
552 in = operands[1]; | |
553 val = operands[2]; | |
554 | |
555 if (xstormy16_onebit_set_operand (val, QImode)) | |
556 { | |
557 if (!xstormy16_below100_or_register (in, QImode)) | |
558 in = copy_to_mode_reg (QImode, in); | |
559 if (!xstormy16_below100_or_register (out, QImode)) | |
560 out = gen_reg_rtx (QImode); | |
561 emit_insn (gen_iorqi3_internal (out, in, val)); | |
562 if (out != operands[0]) | |
563 emit_move_insn (operands[0], out); | |
564 return; | |
565 } | |
566 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
567 if (! REG_P (in)) |
0 | 568 in = copy_to_mode_reg (QImode, in); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
569 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
570 if (! REG_P (val) && ! CONST_INT_P (val)) |
0 | 571 val = copy_to_mode_reg (QImode, val); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
572 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
573 if (! REG_P (out)) |
0 | 574 out = gen_reg_rtx (QImode); |
575 | |
576 in = simplify_gen_subreg (HImode, in, QImode, 0); | |
577 outsub = simplify_gen_subreg (HImode, out, QImode, 0); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
578 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
579 if (! CONST_INT_P (val)) |
0 | 580 val = simplify_gen_subreg (HImode, val, QImode, 0); |
581 | |
582 emit_insn (gen_iorhi3 (outsub, in, val)); | |
583 | |
584 if (out != operands[0]) | |
585 emit_move_insn (operands[0], out); | |
586 } | |
587 | |
588 /* Expand an 8-bit AND. This either detects the one case we can | |
589 actually do, or uses a 16-bit AND. */ | |
590 | |
591 void | |
592 xstormy16_expand_andqi3 (rtx *operands) | |
593 { | |
594 rtx in, out, outsub, val; | |
595 | |
596 out = operands[0]; | |
597 in = operands[1]; | |
598 val = operands[2]; | |
599 | |
600 if (xstormy16_onebit_clr_operand (val, QImode)) | |
601 { | |
602 if (!xstormy16_below100_or_register (in, QImode)) | |
603 in = copy_to_mode_reg (QImode, in); | |
604 if (!xstormy16_below100_or_register (out, QImode)) | |
605 out = gen_reg_rtx (QImode); | |
606 emit_insn (gen_andqi3_internal (out, in, val)); | |
607 if (out != operands[0]) | |
608 emit_move_insn (operands[0], out); | |
609 return; | |
610 } | |
611 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
612 if (! REG_P (in)) |
0 | 613 in = copy_to_mode_reg (QImode, in); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
614 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
615 if (! REG_P (val) && ! CONST_INT_P (val)) |
0 | 616 val = copy_to_mode_reg (QImode, val); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
617 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
618 if (! REG_P (out)) |
0 | 619 out = gen_reg_rtx (QImode); |
620 | |
621 in = simplify_gen_subreg (HImode, in, QImode, 0); | |
622 outsub = simplify_gen_subreg (HImode, out, QImode, 0); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
623 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
624 if (! CONST_INT_P (val)) |
0 | 625 val = simplify_gen_subreg (HImode, val, QImode, 0); |
626 | |
627 emit_insn (gen_andhi3 (outsub, in, val)); | |
628 | |
629 if (out != operands[0]) | |
630 emit_move_insn (operands[0], out); | |
631 } | |
632 | |
633 #define LEGITIMATE_ADDRESS_INTEGER_P(X, OFFSET) \ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
634 (CONST_INT_P (X) \ |
0 | 635 && (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 2048) < 4096) |
636 | |
637 #define LEGITIMATE_ADDRESS_CONST_INT_P(X, OFFSET) \ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
638 (CONST_INT_P (X) \ |
0 | 639 && INTVAL (X) + (OFFSET) >= 0 \ |
640 && INTVAL (X) + (OFFSET) < 0x8000 \ | |
641 && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00)) | |
642 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
643 bool |
111 | 644 xstormy16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
645 rtx x, bool strict) |
0 | 646 { |
647 if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
648 return true; |
0 | 649 |
650 if (GET_CODE (x) == PLUS | |
651 && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 0)) | |
652 { | |
653 x = XEXP (x, 0); | |
654 /* PR 31232: Do not allow INT+INT as an address. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
655 if (CONST_INT_P (x)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
656 return false; |
0 | 657 } |
658 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
659 if ((GET_CODE (x) == PRE_MODIFY && CONST_INT_P (XEXP (XEXP (x, 1), 1))) |
0 | 660 || GET_CODE (x) == POST_INC |
661 || GET_CODE (x) == PRE_DEC) | |
662 x = XEXP (x, 0); | |
663 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
664 if (REG_P (x) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
665 && REGNO_OK_FOR_BASE_P (REGNO (x)) |
0 | 666 && (! strict || REGNO (x) < FIRST_PSEUDO_REGISTER)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
667 return true; |
0 | 668 |
669 if (xstormy16_below100_symbol (x, mode)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
670 return true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
671 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
672 return false; |
0 | 673 } |
674 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
675 /* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P. |
0 | 676 |
677 On this chip, this is true if the address is valid with an offset | |
678 of 0 but not of 6, because in that case it cannot be used as an | |
679 address for DImode or DFmode, or if the address is a post-increment | |
680 or pre-decrement address. */ | |
681 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
682 static bool |
111 | 683 xstormy16_mode_dependent_address_p (const_rtx x, |
684 addr_space_t as ATTRIBUTE_UNUSED) | |
0 | 685 { |
686 if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0) | |
687 && ! LEGITIMATE_ADDRESS_CONST_INT_P (x, 6)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
688 return true; |
0 | 689 |
690 if (GET_CODE (x) == PLUS | |
691 && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 0) | |
692 && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 6)) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
693 return true; |
0 | 694 |
695 /* Auto-increment addresses are now treated generically in recog.c. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
696 return false; |
0 | 697 } |
698 | |
699 int | |
111 | 700 short_memory_operand (rtx x, machine_mode mode) |
0 | 701 { |
702 if (! memory_operand (x, mode)) | |
703 return 0; | |
704 return (GET_CODE (XEXP (x, 0)) != PLUS); | |
705 } | |
706 | |
707 /* Splitter for the 'move' patterns, for modes not directly implemented | |
708 by hardware. Emit insns to copy a value of mode MODE from SRC to | |
709 DEST. | |
710 | |
711 This function is only called when reload_completed. */ | |
712 | |
713 void | |
111 | 714 xstormy16_split_move (machine_mode mode, rtx dest, rtx src) |
0 | 715 { |
716 int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; | |
717 int direction, end, i; | |
718 int src_modifies = 0; | |
719 int dest_modifies = 0; | |
720 int src_volatile = 0; | |
721 int dest_volatile = 0; | |
722 rtx mem_operand; | |
723 rtx auto_inc_reg_rtx = NULL_RTX; | |
724 | |
725 /* Check initial conditions. */ | |
726 gcc_assert (reload_completed | |
727 && mode != QImode && mode != HImode | |
728 && nonimmediate_operand (dest, mode) | |
729 && general_operand (src, mode)); | |
730 | |
731 /* This case is not supported below, and shouldn't be generated. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
732 gcc_assert (! MEM_P (dest) || ! MEM_P (src)); |
0 | 733 |
734 /* This case is very very bad after reload, so trap it now. */ | |
735 gcc_assert (GET_CODE (dest) != SUBREG && GET_CODE (src) != SUBREG); | |
736 | |
737 /* The general idea is to copy by words, offsetting the source and | |
738 destination. Normally the least-significant word will be copied | |
739 first, but for pre-dec operations it's better to copy the | |
740 most-significant word first. Only one operand can be a pre-dec | |
741 or post-inc operand. | |
742 | |
743 It's also possible that the copy overlaps so that the direction | |
744 must be reversed. */ | |
745 direction = 1; | |
746 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
747 if (MEM_P (dest)) |
0 | 748 { |
749 mem_operand = XEXP (dest, 0); | |
750 dest_modifies = side_effects_p (mem_operand); | |
751 if (auto_inc_p (mem_operand)) | |
752 auto_inc_reg_rtx = XEXP (mem_operand, 0); | |
753 dest_volatile = MEM_VOLATILE_P (dest); | |
754 if (dest_volatile) | |
755 { | |
756 dest = copy_rtx (dest); | |
757 MEM_VOLATILE_P (dest) = 0; | |
758 } | |
759 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
760 else if (MEM_P (src)) |
0 | 761 { |
762 mem_operand = XEXP (src, 0); | |
763 src_modifies = side_effects_p (mem_operand); | |
764 if (auto_inc_p (mem_operand)) | |
765 auto_inc_reg_rtx = XEXP (mem_operand, 0); | |
766 src_volatile = MEM_VOLATILE_P (src); | |
767 if (src_volatile) | |
768 { | |
769 src = copy_rtx (src); | |
770 MEM_VOLATILE_P (src) = 0; | |
771 } | |
772 } | |
773 else | |
774 mem_operand = NULL_RTX; | |
775 | |
776 if (mem_operand == NULL_RTX) | |
777 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
778 if (REG_P (src) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
779 && REG_P (dest) |
0 | 780 && reg_overlap_mentioned_p (dest, src) |
781 && REGNO (dest) > REGNO (src)) | |
782 direction = -1; | |
783 } | |
784 else if (GET_CODE (mem_operand) == PRE_DEC | |
785 || (GET_CODE (mem_operand) == PLUS | |
786 && GET_CODE (XEXP (mem_operand, 0)) == PRE_DEC)) | |
787 direction = -1; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
788 else if (MEM_P (src) && reg_overlap_mentioned_p (dest, src)) |
0 | 789 { |
790 int regno; | |
791 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
792 gcc_assert (REG_P (dest)); |
0 | 793 regno = REGNO (dest); |
794 | |
795 gcc_assert (refers_to_regno_p (regno, regno + num_words, | |
796 mem_operand, 0)); | |
797 | |
111 | 798 if (refers_to_regno_p (regno, mem_operand)) |
0 | 799 direction = -1; |
800 else if (refers_to_regno_p (regno + num_words - 1, regno + num_words, | |
801 mem_operand, 0)) | |
802 direction = 1; | |
803 else | |
804 /* This means something like | |
805 (set (reg:DI r0) (mem:DI (reg:HI r1))) | |
806 which we'd need to support by doing the set of the second word | |
807 last. */ | |
808 gcc_unreachable (); | |
809 } | |
810 | |
811 end = direction < 0 ? -1 : num_words; | |
812 for (i = direction < 0 ? num_words - 1 : 0; i != end; i += direction) | |
813 { | |
814 rtx w_src, w_dest, insn; | |
815 | |
816 if (src_modifies) | |
817 w_src = gen_rtx_MEM (word_mode, mem_operand); | |
818 else | |
819 w_src = simplify_gen_subreg (word_mode, src, mode, i * UNITS_PER_WORD); | |
820 if (src_volatile) | |
821 MEM_VOLATILE_P (w_src) = 1; | |
822 if (dest_modifies) | |
823 w_dest = gen_rtx_MEM (word_mode, mem_operand); | |
824 else | |
825 w_dest = simplify_gen_subreg (word_mode, dest, mode, | |
826 i * UNITS_PER_WORD); | |
827 if (dest_volatile) | |
828 MEM_VOLATILE_P (w_dest) = 1; | |
829 | |
830 /* The simplify_subreg calls must always be able to simplify. */ | |
831 gcc_assert (GET_CODE (w_src) != SUBREG | |
832 && GET_CODE (w_dest) != SUBREG); | |
833 | |
111 | 834 insn = emit_insn (gen_rtx_SET (w_dest, w_src)); |
0 | 835 if (auto_inc_reg_rtx) |
836 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, | |
837 auto_inc_reg_rtx, | |
838 REG_NOTES (insn)); | |
839 } | |
840 } | |
841 | |
842 /* Expander for the 'move' patterns. Emit insns to copy a value of | |
843 mode MODE from SRC to DEST. */ | |
844 | |
845 void | |
111 | 846 xstormy16_expand_move (machine_mode mode, rtx dest, rtx src) |
0 | 847 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
848 if (MEM_P (dest) && (GET_CODE (XEXP (dest, 0)) == PRE_MODIFY)) |
0 | 849 { |
850 rtx pmv = XEXP (dest, 0); | |
851 rtx dest_reg = XEXP (pmv, 0); | |
852 rtx dest_mod = XEXP (pmv, 1); | |
111 | 853 rtx set = gen_rtx_SET (dest_reg, dest_mod); |
0 | 854 rtx clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, CARRY_REGNUM)); |
855 | |
856 dest = gen_rtx_MEM (mode, dest_reg); | |
857 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber))); | |
858 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
859 else if (MEM_P (src) && (GET_CODE (XEXP (src, 0)) == PRE_MODIFY)) |
0 | 860 { |
861 rtx pmv = XEXP (src, 0); | |
862 rtx src_reg = XEXP (pmv, 0); | |
863 rtx src_mod = XEXP (pmv, 1); | |
111 | 864 rtx set = gen_rtx_SET (src_reg, src_mod); |
0 | 865 rtx clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, CARRY_REGNUM)); |
866 | |
867 src = gen_rtx_MEM (mode, src_reg); | |
868 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber))); | |
869 } | |
870 | |
871 /* There are only limited immediate-to-memory move instructions. */ | |
872 if (! reload_in_progress | |
873 && ! reload_completed | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
874 && MEM_P (dest) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
875 && (! CONST_INT_P (XEXP (dest, 0)) |
0 | 876 || ! xstormy16_legitimate_address_p (mode, XEXP (dest, 0), 0)) |
877 && ! xstormy16_below100_operand (dest, mode) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
878 && ! REG_P (src) |
0 | 879 && GET_CODE (src) != SUBREG) |
880 src = copy_to_mode_reg (mode, src); | |
881 | |
882 /* Don't emit something we would immediately split. */ | |
883 if (reload_completed | |
884 && mode != HImode && mode != QImode) | |
885 { | |
886 xstormy16_split_move (mode, dest, src); | |
887 return; | |
888 } | |
889 | |
111 | 890 emit_insn (gen_rtx_SET (dest, src)); |
0 | 891 } |
892 | |
893 /* Stack Layout: | |
894 | |
895 The stack is laid out as follows: | |
896 | |
897 SP-> | |
898 FP-> Local variables | |
899 Register save area (up to 4 words) | |
900 Argument register save area for stdarg (NUM_ARGUMENT_REGISTERS words) | |
901 | |
902 AP-> Return address (two words) | |
903 9th procedure parameter word | |
904 10th procedure parameter word | |
905 ... | |
906 last procedure parameter word | |
907 | |
908 The frame pointer location is tuned to make it most likely that all | |
909 parameters and local variables can be accessed using a load-indexed | |
910 instruction. */ | |
911 | |
912 /* A structure to describe the layout. */ | |
913 struct xstormy16_stack_layout | |
914 { | |
915 /* Size of the topmost three items on the stack. */ | |
916 int locals_size; | |
917 int register_save_size; | |
918 int stdarg_save_size; | |
919 /* Sum of the above items. */ | |
920 int frame_size; | |
921 /* Various offsets. */ | |
922 int first_local_minus_ap; | |
923 int sp_minus_fp; | |
924 int fp_minus_ap; | |
925 }; | |
926 | |
927 /* Does REGNO need to be saved? */ | |
928 #define REG_NEEDS_SAVE(REGNUM, IFUN) \ | |
929 ((df_regs_ever_live_p (REGNUM) && ! call_used_regs[REGNUM]) \ | |
930 || (IFUN && ! fixed_regs[REGNUM] && call_used_regs[REGNUM] \ | |
931 && (REGNUM != CARRY_REGNUM) \ | |
111 | 932 && (df_regs_ever_live_p (REGNUM) || ! crtl->is_leaf))) |
0 | 933 |
934 /* Compute the stack layout. */ | |
935 | |
936 struct xstormy16_stack_layout | |
937 xstormy16_compute_stack_layout (void) | |
938 { | |
939 struct xstormy16_stack_layout layout; | |
940 int regno; | |
941 const int ifun = xstormy16_interrupt_function_p (); | |
942 | |
943 layout.locals_size = get_frame_size (); | |
944 | |
945 layout.register_save_size = 0; | |
946 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
947 if (REG_NEEDS_SAVE (regno, ifun)) | |
948 layout.register_save_size += UNITS_PER_WORD; | |
949 | |
950 if (cfun->stdarg) | |
951 layout.stdarg_save_size = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD; | |
952 else | |
953 layout.stdarg_save_size = 0; | |
954 | |
955 layout.frame_size = (layout.locals_size | |
956 + layout.register_save_size | |
957 + layout.stdarg_save_size); | |
958 | |
959 if (crtl->args.size <= 2048 && crtl->args.size != -1) | |
960 { | |
961 if (layout.frame_size - INCOMING_FRAME_SP_OFFSET | |
962 + crtl->args.size <= 2048) | |
963 layout.fp_minus_ap = layout.frame_size - INCOMING_FRAME_SP_OFFSET; | |
964 else | |
965 layout.fp_minus_ap = 2048 - crtl->args.size; | |
966 } | |
967 else | |
968 layout.fp_minus_ap = (layout.stdarg_save_size | |
969 + layout.register_save_size | |
970 - INCOMING_FRAME_SP_OFFSET); | |
971 layout.sp_minus_fp = (layout.frame_size - INCOMING_FRAME_SP_OFFSET | |
972 - layout.fp_minus_ap); | |
973 layout.first_local_minus_ap = layout.sp_minus_fp - layout.locals_size; | |
974 return layout; | |
975 } | |
976 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
977 /* Worker function for TARGET_CAN_ELIMINATE. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
978 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
979 static bool |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
980 xstormy16_can_eliminate (const int from, const int to) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
981 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
982 return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
983 ? ! frame_pointer_needed |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
984 : true); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
985 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
986 |
0 | 987 /* Determine how all the special registers get eliminated. */ |
988 | |
989 int | |
990 xstormy16_initial_elimination_offset (int from, int to) | |
991 { | |
992 struct xstormy16_stack_layout layout; | |
993 int result; | |
994 | |
995 layout = xstormy16_compute_stack_layout (); | |
996 | |
997 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) | |
998 result = layout.sp_minus_fp - layout.locals_size; | |
999 else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) | |
1000 result = - layout.locals_size; | |
1001 else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) | |
1002 result = - layout.fp_minus_ap; | |
1003 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) | |
1004 result = - (layout.sp_minus_fp + layout.fp_minus_ap); | |
1005 else | |
1006 gcc_unreachable (); | |
1007 | |
1008 return result; | |
1009 } | |
1010 | |
1011 static rtx | |
1012 emit_addhi3_postreload (rtx dest, rtx src0, rtx src1) | |
1013 { | |
1014 rtx set, clobber, insn; | |
1015 | |
111 | 1016 set = gen_rtx_SET (dest, gen_rtx_PLUS (HImode, src0, src1)); |
0 | 1017 clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, CARRY_REGNUM)); |
1018 insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber))); | |
1019 return insn; | |
1020 } | |
1021 | |
1022 /* Called after register allocation to add any instructions needed for | |
1023 the prologue. Using a prologue insn is favored compared to putting | |
1024 all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro, | |
1025 since it allows the scheduler to intermix instructions with the | |
1026 saves of the caller saved registers. In some cases, it might be | |
1027 necessary to emit a barrier instruction as the last insn to prevent | |
1028 such scheduling. | |
1029 | |
1030 Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1 | |
1031 so that the debug info generation code can handle them properly. */ | |
1032 | |
1033 void | |
1034 xstormy16_expand_prologue (void) | |
1035 { | |
1036 struct xstormy16_stack_layout layout; | |
1037 int regno; | |
1038 rtx insn; | |
1039 rtx mem_push_rtx; | |
1040 const int ifun = xstormy16_interrupt_function_p (); | |
1041 | |
1042 mem_push_rtx = gen_rtx_POST_INC (Pmode, stack_pointer_rtx); | |
1043 mem_push_rtx = gen_rtx_MEM (HImode, mem_push_rtx); | |
1044 | |
1045 layout = xstormy16_compute_stack_layout (); | |
1046 | |
1047 if (layout.locals_size >= 32768) | |
1048 error ("local variable memory requirements exceed capacity"); | |
1049 | |
111 | 1050 if (flag_stack_usage_info) |
1051 current_function_static_stack_size = layout.frame_size; | |
1052 | |
0 | 1053 /* Save the argument registers if necessary. */ |
1054 if (layout.stdarg_save_size) | |
1055 for (regno = FIRST_ARGUMENT_REGISTER; | |
1056 regno < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS; | |
1057 regno++) | |
1058 { | |
1059 rtx dwarf; | |
1060 rtx reg = gen_rtx_REG (HImode, regno); | |
1061 | |
1062 insn = emit_move_insn (mem_push_rtx, reg); | |
1063 RTX_FRAME_RELATED_P (insn) = 1; | |
1064 | |
1065 dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2)); | |
1066 | |
111 | 1067 XVECEXP (dwarf, 0, 0) = gen_rtx_SET (gen_rtx_MEM (Pmode, stack_pointer_rtx), |
0 | 1068 reg); |
111 | 1069 XVECEXP (dwarf, 0, 1) = gen_rtx_SET (stack_pointer_rtx, |
1070 plus_constant (Pmode, | |
1071 stack_pointer_rtx, | |
0 | 1072 GET_MODE_SIZE (Pmode))); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1073 add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf); |
0 | 1074 RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 0)) = 1; |
1075 RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 1)) = 1; | |
1076 } | |
1077 | |
1078 /* Push each of the registers to save. */ | |
1079 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
1080 if (REG_NEEDS_SAVE (regno, ifun)) | |
1081 { | |
1082 rtx dwarf; | |
1083 rtx reg = gen_rtx_REG (HImode, regno); | |
1084 | |
1085 insn = emit_move_insn (mem_push_rtx, reg); | |
1086 RTX_FRAME_RELATED_P (insn) = 1; | |
1087 | |
1088 dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2)); | |
1089 | |
111 | 1090 XVECEXP (dwarf, 0, 0) = gen_rtx_SET (gen_rtx_MEM (Pmode, stack_pointer_rtx), |
0 | 1091 reg); |
111 | 1092 XVECEXP (dwarf, 0, 1) = gen_rtx_SET (stack_pointer_rtx, |
1093 plus_constant (Pmode, | |
1094 stack_pointer_rtx, | |
0 | 1095 GET_MODE_SIZE (Pmode))); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1096 add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf); |
0 | 1097 RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 0)) = 1; |
1098 RTX_FRAME_RELATED_P (XVECEXP (dwarf, 0, 1)) = 1; | |
1099 } | |
1100 | |
1101 /* It's just possible that the SP here might be what we need for | |
1102 the new FP... */ | |
1103 if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size) | |
1104 { | |
1105 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); | |
1106 RTX_FRAME_RELATED_P (insn) = 1; | |
1107 } | |
1108 | |
1109 /* Allocate space for local variables. */ | |
1110 if (layout.locals_size) | |
1111 { | |
1112 insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx, | |
1113 GEN_INT (layout.locals_size)); | |
1114 RTX_FRAME_RELATED_P (insn) = 1; | |
1115 } | |
1116 | |
1117 /* Set up the frame pointer, if required. */ | |
1118 if (frame_pointer_needed && layout.sp_minus_fp != layout.locals_size) | |
1119 { | |
1120 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); | |
1121 RTX_FRAME_RELATED_P (insn) = 1; | |
1122 | |
1123 if (layout.sp_minus_fp) | |
1124 { | |
1125 insn = emit_addhi3_postreload (hard_frame_pointer_rtx, | |
1126 hard_frame_pointer_rtx, | |
1127 GEN_INT (- layout.sp_minus_fp)); | |
1128 RTX_FRAME_RELATED_P (insn) = 1; | |
1129 } | |
1130 } | |
1131 } | |
1132 | |
1133 /* Do we need an epilogue at all? */ | |
1134 | |
1135 int | |
1136 direct_return (void) | |
1137 { | |
1138 return (reload_completed | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1139 && xstormy16_compute_stack_layout ().frame_size == 0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1140 && ! xstormy16_interrupt_function_p ()); |
0 | 1141 } |
1142 | |
1143 /* Called after register allocation to add any instructions needed for | |
1144 the epilogue. Using an epilogue insn is favored compared to putting | |
1145 all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro, | |
1146 since it allows the scheduler to intermix instructions with the | |
1147 saves of the caller saved registers. In some cases, it might be | |
1148 necessary to emit a barrier instruction as the last insn to prevent | |
1149 such scheduling. */ | |
1150 | |
1151 void | |
1152 xstormy16_expand_epilogue (void) | |
1153 { | |
1154 struct xstormy16_stack_layout layout; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1155 rtx mem_pop_rtx; |
0 | 1156 int regno; |
1157 const int ifun = xstormy16_interrupt_function_p (); | |
1158 | |
1159 mem_pop_rtx = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); | |
1160 mem_pop_rtx = gen_rtx_MEM (HImode, mem_pop_rtx); | |
1161 | |
1162 layout = xstormy16_compute_stack_layout (); | |
1163 | |
1164 /* Pop the stack for the locals. */ | |
1165 if (layout.locals_size) | |
1166 { | |
1167 if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size) | |
1168 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); | |
1169 else | |
1170 emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx, | |
1171 GEN_INT (- layout.locals_size)); | |
1172 } | |
1173 | |
1174 /* Restore any call-saved registers. */ | |
1175 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) | |
1176 if (REG_NEEDS_SAVE (regno, ifun)) | |
1177 emit_move_insn (gen_rtx_REG (HImode, regno), mem_pop_rtx); | |
1178 | |
1179 /* Pop the stack for the stdarg save area. */ | |
1180 if (layout.stdarg_save_size) | |
1181 emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx, | |
1182 GEN_INT (- layout.stdarg_save_size)); | |
1183 | |
1184 /* Return. */ | |
1185 if (ifun) | |
1186 emit_jump_insn (gen_return_internal_interrupt ()); | |
1187 else | |
1188 emit_jump_insn (gen_return_internal ()); | |
1189 } | |
1190 | |
1191 int | |
1192 xstormy16_epilogue_uses (int regno) | |
1193 { | |
1194 if (reload_completed && call_used_regs[regno]) | |
1195 { | |
1196 const int ifun = xstormy16_interrupt_function_p (); | |
1197 return REG_NEEDS_SAVE (regno, ifun); | |
1198 } | |
1199 return 0; | |
1200 } | |
1201 | |
1202 void | |
1203 xstormy16_function_profiler (void) | |
1204 { | |
1205 sorry ("function_profiler support"); | |
1206 } | |
1207 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1208 /* Update CUM to advance past an argument in the argument list. The |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1209 values MODE, TYPE and NAMED describe that argument. Once this is |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1210 done, the variable CUM is suitable for analyzing the *following* |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1211 argument with `TARGET_FUNCTION_ARG', etc. |
0 | 1212 |
1213 This function need not do anything if the argument in question was | |
1214 passed on the stack. The compiler knows how to track the amount of | |
1215 stack space used for arguments without any special help. However, | |
1216 it makes life easier for xstormy16_build_va_list if it does update | |
1217 the word count. */ | |
1218 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1219 static void |
111 | 1220 xstormy16_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1221 const_tree type, bool named ATTRIBUTE_UNUSED) |
0 | 1222 { |
111 | 1223 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
1224 | |
0 | 1225 /* If an argument would otherwise be passed partially in registers, |
1226 and partially on the stack, the whole of it is passed on the | |
1227 stack. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1228 if (*cum < NUM_ARGUMENT_REGISTERS |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1229 && *cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1230 *cum = NUM_ARGUMENT_REGISTERS; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1231 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1232 *cum += XSTORMY16_WORD_SIZE (type, mode); |
0 | 1233 } |
1234 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1235 static rtx |
111 | 1236 xstormy16_function_arg (cumulative_args_t cum_v, machine_mode mode, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1237 const_tree type, bool named ATTRIBUTE_UNUSED) |
0 | 1238 { |
111 | 1239 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
1240 | |
0 | 1241 if (mode == VOIDmode) |
1242 return const0_rtx; | |
1243 if (targetm.calls.must_pass_in_stack (mode, type) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1244 || *cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS) |
0 | 1245 return NULL_RTX; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1246 return gen_rtx_REG (mode, *cum + FIRST_ARGUMENT_REGISTER); |
0 | 1247 } |
1248 | |
1249 /* Build the va_list type. | |
1250 | |
1251 For this chip, va_list is a record containing a counter and a pointer. | |
1252 The counter is of type 'int' and indicates how many bytes | |
1253 have been used to date. The pointer indicates the stack position | |
1254 for arguments that have not been passed in registers. | |
1255 To keep the layout nice, the pointer is first in the structure. */ | |
1256 | |
1257 static tree | |
1258 xstormy16_build_builtin_va_list (void) | |
1259 { | |
1260 tree f_1, f_2, record, type_decl; | |
1261 | |
1262 record = (*lang_hooks.types.make_type) (RECORD_TYPE); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1263 type_decl = build_decl (BUILTINS_LOCATION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1264 TYPE_DECL, get_identifier ("__va_list_tag"), record); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1265 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1266 f_1 = build_decl (BUILTINS_LOCATION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1267 FIELD_DECL, get_identifier ("base"), |
0 | 1268 ptr_type_node); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1269 f_2 = build_decl (BUILTINS_LOCATION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1270 FIELD_DECL, get_identifier ("count"), |
0 | 1271 unsigned_type_node); |
1272 | |
1273 DECL_FIELD_CONTEXT (f_1) = record; | |
1274 DECL_FIELD_CONTEXT (f_2) = record; | |
1275 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1276 TYPE_STUB_DECL (record) = type_decl; |
0 | 1277 TYPE_NAME (record) = type_decl; |
1278 TYPE_FIELDS (record) = f_1; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1279 DECL_CHAIN (f_1) = f_2; |
0 | 1280 |
1281 layout_type (record); | |
1282 | |
1283 return record; | |
1284 } | |
1285 | |
1286 /* Implement the stdarg/varargs va_start macro. STDARG_P is nonzero if this | |
1287 is stdarg.h instead of varargs.h. VALIST is the tree of the va_list | |
1288 variable to initialize. NEXTARG is the machine independent notion of the | |
1289 'next' argument after the variable arguments. */ | |
1290 | |
1291 static void | |
1292 xstormy16_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) | |
1293 { | |
1294 tree f_base, f_count; | |
1295 tree base, count; | |
1296 tree t,u; | |
1297 | |
1298 if (xstormy16_interrupt_function_p ()) | |
1299 error ("cannot use va_start in interrupt function"); | |
1300 | |
1301 f_base = TYPE_FIELDS (va_list_type_node); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1302 f_count = DECL_CHAIN (f_base); |
0 | 1303 |
1304 base = build3 (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base, NULL_TREE); | |
1305 count = build3 (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count, | |
1306 NULL_TREE); | |
1307 | |
1308 t = make_tree (TREE_TYPE (base), virtual_incoming_args_rtx); | |
1309 u = build_int_cst (NULL_TREE, - INCOMING_FRAME_SP_OFFSET); | |
1310 u = fold_convert (TREE_TYPE (count), u); | |
111 | 1311 t = fold_build_pointer_plus (t, u); |
0 | 1312 t = build2 (MODIFY_EXPR, TREE_TYPE (base), base, t); |
1313 TREE_SIDE_EFFECTS (t) = 1; | |
1314 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); | |
1315 | |
1316 t = build2 (MODIFY_EXPR, TREE_TYPE (count), count, | |
1317 build_int_cst (NULL_TREE, | |
1318 crtl->args.info * UNITS_PER_WORD)); | |
1319 TREE_SIDE_EFFECTS (t) = 1; | |
1320 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); | |
1321 } | |
1322 | |
1323 /* Implement the stdarg/varargs va_arg macro. VALIST is the variable | |
1324 of type va_list as a tree, TYPE is the type passed to va_arg. | |
1325 Note: This algorithm is documented in stormy-abi. */ | |
1326 | |
1327 static tree | |
1328 xstormy16_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, | |
1329 gimple_seq *post_p ATTRIBUTE_UNUSED) | |
1330 { | |
1331 tree f_base, f_count; | |
1332 tree base, count; | |
1333 tree count_tmp, addr, t; | |
1334 tree lab_gotaddr, lab_fromstack; | |
1335 int size, size_of_reg_args, must_stack; | |
1336 tree size_tree; | |
1337 | |
1338 f_base = TYPE_FIELDS (va_list_type_node); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1339 f_count = DECL_CHAIN (f_base); |
0 | 1340 |
1341 base = build3 (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base, NULL_TREE); | |
1342 count = build3 (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count, | |
1343 NULL_TREE); | |
1344 | |
1345 must_stack = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type); | |
1346 size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD); | |
1347 gimplify_expr (&size_tree, pre_p, NULL, is_gimple_val, fb_rvalue); | |
1348 | |
1349 size_of_reg_args = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD; | |
1350 | |
1351 count_tmp = get_initialized_tmp_var (count, pre_p, NULL); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1352 lab_gotaddr = create_artificial_label (UNKNOWN_LOCATION); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1353 lab_fromstack = create_artificial_label (UNKNOWN_LOCATION); |
111 | 1354 addr = create_tmp_var (ptr_type_node); |
0 | 1355 |
1356 if (!must_stack) | |
1357 { | |
1358 tree r; | |
1359 | |
1360 t = fold_convert (TREE_TYPE (count), size_tree); | |
1361 t = build2 (PLUS_EXPR, TREE_TYPE (count), count_tmp, t); | |
1362 r = fold_convert (TREE_TYPE (count), size_int (size_of_reg_args)); | |
1363 t = build2 (GT_EXPR, boolean_type_node, t, r); | |
1364 t = build3 (COND_EXPR, void_type_node, t, | |
1365 build1 (GOTO_EXPR, void_type_node, lab_fromstack), | |
1366 NULL_TREE); | |
1367 gimplify_and_add (t, pre_p); | |
1368 | |
111 | 1369 t = fold_build_pointer_plus (base, count_tmp); |
0 | 1370 gimplify_assign (addr, t, pre_p); |
1371 | |
1372 t = build1 (GOTO_EXPR, void_type_node, lab_gotaddr); | |
1373 gimplify_and_add (t, pre_p); | |
1374 | |
1375 t = build1 (LABEL_EXPR, void_type_node, lab_fromstack); | |
1376 gimplify_and_add (t, pre_p); | |
1377 } | |
1378 | |
1379 /* Arguments larger than a word might need to skip over some | |
1380 registers, since arguments are either passed entirely in | |
1381 registers or entirely on the stack. */ | |
1382 size = PUSH_ROUNDING (int_size_in_bytes (type)); | |
1383 if (size > 2 || size < 0 || must_stack) | |
1384 { | |
1385 tree r, u; | |
1386 | |
1387 r = size_int (NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD); | |
1388 u = build2 (MODIFY_EXPR, TREE_TYPE (count_tmp), count_tmp, r); | |
1389 | |
1390 t = fold_convert (TREE_TYPE (count), r); | |
1391 t = build2 (GE_EXPR, boolean_type_node, count_tmp, t); | |
1392 t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, u); | |
1393 gimplify_and_add (t, pre_p); | |
1394 } | |
1395 | |
1396 t = size_int (NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD | |
1397 + INCOMING_FRAME_SP_OFFSET); | |
1398 t = fold_convert (TREE_TYPE (count), t); | |
1399 t = build2 (MINUS_EXPR, TREE_TYPE (count), count_tmp, t); | |
1400 t = build2 (PLUS_EXPR, TREE_TYPE (count), t, | |
1401 fold_convert (TREE_TYPE (count), size_tree)); | |
1402 t = fold_convert (TREE_TYPE (t), fold (t)); | |
1403 t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t); | |
111 | 1404 t = fold_build_pointer_plus (base, t); |
0 | 1405 gimplify_assign (addr, t, pre_p); |
1406 | |
1407 t = build1 (LABEL_EXPR, void_type_node, lab_gotaddr); | |
1408 gimplify_and_add (t, pre_p); | |
1409 | |
1410 t = fold_convert (TREE_TYPE (count), size_tree); | |
1411 t = build2 (PLUS_EXPR, TREE_TYPE (count), count_tmp, t); | |
1412 gimplify_assign (count, t, pre_p); | |
1413 | |
1414 addr = fold_convert (build_pointer_type (type), addr); | |
1415 return build_va_arg_indirect_ref (addr); | |
1416 } | |
1417 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1418 /* Worker function for TARGET_TRAMPOLINE_INIT. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1419 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1420 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1421 xstormy16_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain) |
0 | 1422 { |
1423 rtx temp = gen_reg_rtx (HImode); | |
1424 rtx reg_fnaddr = gen_reg_rtx (HImode); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1425 rtx reg_addr, reg_addr_mem; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1426 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1427 reg_addr = copy_to_reg (XEXP (m_tramp, 0)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1428 reg_addr_mem = adjust_automodify_address (m_tramp, HImode, reg_addr, 0); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1429 |
0 | 1430 emit_move_insn (temp, GEN_INT (0x3130 | STATIC_CHAIN_REGNUM)); |
1431 emit_move_insn (reg_addr_mem, temp); | |
1432 emit_insn (gen_addhi3 (reg_addr, reg_addr, const2_rtx)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1433 reg_addr_mem = adjust_automodify_address (reg_addr_mem, VOIDmode, NULL, 2); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1434 |
0 | 1435 emit_move_insn (temp, static_chain); |
1436 emit_move_insn (reg_addr_mem, temp); | |
1437 emit_insn (gen_addhi3 (reg_addr, reg_addr, const2_rtx)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1438 reg_addr_mem = adjust_automodify_address (reg_addr_mem, VOIDmode, NULL, 2); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1439 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1440 emit_move_insn (reg_fnaddr, XEXP (DECL_RTL (fndecl), 0)); |
0 | 1441 emit_move_insn (temp, reg_fnaddr); |
1442 emit_insn (gen_andhi3 (temp, temp, GEN_INT (0xFF))); | |
1443 emit_insn (gen_iorhi3 (temp, temp, GEN_INT (0x0200))); | |
1444 emit_move_insn (reg_addr_mem, temp); | |
1445 emit_insn (gen_addhi3 (reg_addr, reg_addr, const2_rtx)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1446 reg_addr_mem = adjust_automodify_address (reg_addr_mem, VOIDmode, NULL, 2); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1447 |
0 | 1448 emit_insn (gen_lshrhi3 (reg_fnaddr, reg_fnaddr, GEN_INT (8))); |
1449 emit_move_insn (reg_addr_mem, reg_fnaddr); | |
1450 } | |
1451 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1452 /* Worker function for TARGET_FUNCTION_VALUE. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1453 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1454 static rtx |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1455 xstormy16_function_value (const_tree valtype, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1456 const_tree func ATTRIBUTE_UNUSED, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1457 bool outgoing ATTRIBUTE_UNUSED) |
0 | 1458 { |
111 | 1459 machine_mode mode; |
0 | 1460 mode = TYPE_MODE (valtype); |
1461 PROMOTE_MODE (mode, 0, valtype); | |
1462 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM); | |
1463 } | |
1464 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1465 /* Worker function for TARGET_LIBCALL_VALUE. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1466 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1467 static rtx |
111 | 1468 xstormy16_libcall_value (machine_mode mode, |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1469 const_rtx fun ATTRIBUTE_UNUSED) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1470 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1471 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1472 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1473 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1474 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1475 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1476 static bool |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1477 xstormy16_function_value_regno_p (const unsigned int regno) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1478 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1479 return (regno == RETURN_VALUE_REGNUM); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1480 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1481 |
0 | 1482 /* A C compound statement that outputs the assembler code for a thunk function, |
1483 used to implement C++ virtual function calls with multiple inheritance. The | |
1484 thunk acts as a wrapper around a virtual function, adjusting the implicit | |
1485 object parameter before handing control off to the real function. | |
1486 | |
1487 First, emit code to add the integer DELTA to the location that contains the | |
1488 incoming first argument. Assume that this argument contains a pointer, and | |
1489 is the one used to pass the `this' pointer in C++. This is the incoming | |
1490 argument *before* the function prologue, e.g. `%o0' on a sparc. The | |
1491 addition must preserve the values of all other incoming arguments. | |
1492 | |
1493 After the addition, emit code to jump to FUNCTION, which is a | |
1494 `FUNCTION_DECL'. This is a direct pure jump, not a call, and does not touch | |
1495 the return address. Hence returning from FUNCTION will return to whoever | |
1496 called the current `thunk'. | |
1497 | |
1498 The effect must be as if @var{function} had been called directly | |
1499 with the adjusted first argument. This macro is responsible for | |
1500 emitting all of the code for a thunk function; | |
1501 TARGET_ASM_FUNCTION_PROLOGUE and TARGET_ASM_FUNCTION_EPILOGUE are | |
1502 not invoked. | |
1503 | |
1504 The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been | |
1505 extracted from it.) It might possibly be useful on some targets, but | |
1506 probably not. */ | |
1507 | |
1508 static void | |
1509 xstormy16_asm_output_mi_thunk (FILE *file, | |
1510 tree thunk_fndecl ATTRIBUTE_UNUSED, | |
1511 HOST_WIDE_INT delta, | |
1512 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, | |
1513 tree function) | |
1514 { | |
1515 int regnum = FIRST_ARGUMENT_REGISTER; | |
1516 | |
1517 /* There might be a hidden first argument for a returned structure. */ | |
1518 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) | |
1519 regnum += 1; | |
1520 | |
1521 fprintf (file, "\tadd %s,#0x%x\n", reg_names[regnum], (int) delta & 0xFFFF); | |
1522 fputs ("\tjmpf ", file); | |
1523 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); | |
1524 putc ('\n', file); | |
1525 } | |
1526 | |
1527 /* The purpose of this function is to override the default behavior of | |
1528 BSS objects. Normally, they go into .bss or .sbss via ".common" | |
1529 directives, but we need to override that and put them in | |
1530 .bss_below100. We can't just use a section override (like we do | |
1531 for .data_below100), because that makes them initialized rather | |
1532 than uninitialized. */ | |
1533 | |
1534 void | |
1535 xstormy16_asm_output_aligned_common (FILE *stream, | |
1536 tree decl, | |
1537 const char *name, | |
1538 int size, | |
1539 int align, | |
1540 int global) | |
1541 { | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1542 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl); |
0 | 1543 rtx symbol; |
1544 | |
1545 if (mem != NULL_RTX | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1546 && MEM_P (mem) |
0 | 1547 && GET_CODE (symbol = XEXP (mem, 0)) == SYMBOL_REF |
1548 && SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_XSTORMY16_BELOW100) | |
1549 { | |
1550 const char *name2; | |
1551 int p2align = 0; | |
1552 | |
1553 switch_to_section (bss100_section); | |
1554 | |
1555 while (align > 8) | |
1556 { | |
1557 align /= 2; | |
1558 p2align ++; | |
1559 } | |
1560 | |
1561 name2 = default_strip_name_encoding (name); | |
1562 if (global) | |
1563 fprintf (stream, "\t.globl\t%s\n", name2); | |
1564 if (p2align) | |
1565 fprintf (stream, "\t.p2align %d\n", p2align); | |
1566 fprintf (stream, "\t.type\t%s, @object\n", name2); | |
1567 fprintf (stream, "\t.size\t%s, %d\n", name2, size); | |
1568 fprintf (stream, "%s:\n\t.space\t%d\n", name2, size); | |
1569 return; | |
1570 } | |
1571 | |
1572 if (!global) | |
1573 { | |
1574 fprintf (stream, "\t.local\t"); | |
1575 assemble_name (stream, name); | |
1576 fprintf (stream, "\n"); | |
1577 } | |
1578 fprintf (stream, "\t.comm\t"); | |
1579 assemble_name (stream, name); | |
1580 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT); | |
1581 } | |
1582 | |
1583 /* Implement TARGET_ASM_INIT_SECTIONS. */ | |
1584 | |
1585 static void | |
1586 xstormy16_asm_init_sections (void) | |
1587 { | |
1588 bss100_section | |
1589 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, | |
1590 output_section_asm_op, | |
1591 "\t.section \".bss_below100\",\"aw\",@nobits"); | |
1592 } | |
1593 | |
1594 /* Mark symbols with the "below100" attribute so that we can use the | |
1595 special addressing modes for them. */ | |
1596 | |
1597 static void | |
1598 xstormy16_encode_section_info (tree decl, rtx r, int first) | |
1599 { | |
1600 default_encode_section_info (decl, r, first); | |
1601 | |
1602 if (TREE_CODE (decl) == VAR_DECL | |
1603 && (lookup_attribute ("below100", DECL_ATTRIBUTES (decl)) | |
1604 || lookup_attribute ("BELOW100", DECL_ATTRIBUTES (decl)))) | |
1605 { | |
1606 rtx symbol = XEXP (r, 0); | |
1607 | |
1608 gcc_assert (GET_CODE (symbol) == SYMBOL_REF); | |
1609 SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_XSTORMY16_BELOW100; | |
1610 } | |
1611 } | |
1612 | |
1613 #undef TARGET_ASM_CONSTRUCTOR | |
1614 #define TARGET_ASM_CONSTRUCTOR xstormy16_asm_out_constructor | |
1615 #undef TARGET_ASM_DESTRUCTOR | |
1616 #define TARGET_ASM_DESTRUCTOR xstormy16_asm_out_destructor | |
1617 | |
1618 /* Output constructors and destructors. Just like | |
1619 default_named_section_asm_out_* but don't set the sections writable. */ | |
1620 | |
1621 static void | |
1622 xstormy16_asm_out_destructor (rtx symbol, int priority) | |
1623 { | |
1624 const char *section = ".dtors"; | |
111 | 1625 char buf[18]; |
0 | 1626 |
1627 /* ??? This only works reliably with the GNU linker. */ | |
1628 if (priority != DEFAULT_INIT_PRIORITY) | |
1629 { | |
1630 sprintf (buf, ".dtors.%.5u", | |
1631 /* Invert the numbering so the linker puts us in the proper | |
1632 order; constructors are run from right to left, and the | |
1633 linker sorts in increasing order. */ | |
1634 MAX_INIT_PRIORITY - priority); | |
1635 section = buf; | |
1636 } | |
1637 | |
1638 switch_to_section (get_section (section, 0, NULL)); | |
1639 assemble_align (POINTER_SIZE); | |
1640 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); | |
1641 } | |
1642 | |
1643 static void | |
1644 xstormy16_asm_out_constructor (rtx symbol, int priority) | |
1645 { | |
1646 const char *section = ".ctors"; | |
111 | 1647 char buf[18]; |
0 | 1648 |
1649 /* ??? This only works reliably with the GNU linker. */ | |
1650 if (priority != DEFAULT_INIT_PRIORITY) | |
1651 { | |
1652 sprintf (buf, ".ctors.%.5u", | |
1653 /* Invert the numbering so the linker puts us in the proper | |
1654 order; constructors are run from right to left, and the | |
1655 linker sorts in increasing order. */ | |
1656 MAX_INIT_PRIORITY - priority); | |
1657 section = buf; | |
1658 } | |
1659 | |
1660 switch_to_section (get_section (section, 0, NULL)); | |
1661 assemble_align (POINTER_SIZE); | |
1662 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); | |
1663 } | |
1664 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1665 /* Worker function for TARGET_PRINT_OPERAND_ADDRESS. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1666 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1667 Print a memory address as an operand to reference that memory location. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1668 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1669 static void |
111 | 1670 xstormy16_print_operand_address (FILE *file, machine_mode /*mode*/, |
1671 rtx address) | |
0 | 1672 { |
1673 HOST_WIDE_INT offset; | |
1674 int pre_dec, post_inc; | |
1675 | |
1676 /* There are a few easy cases. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1677 if (CONST_INT_P (address)) |
0 | 1678 { |
1679 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (address) & 0xFFFF); | |
1680 return; | |
1681 } | |
1682 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1683 if (CONSTANT_P (address) || LABEL_P (address)) |
0 | 1684 { |
1685 output_addr_const (file, address); | |
1686 return; | |
1687 } | |
1688 | |
1689 /* Otherwise, it's hopefully something of the form | |
1690 (plus:HI (pre_dec:HI (reg:HI ...)) (const_int ...)). */ | |
1691 if (GET_CODE (address) == PLUS) | |
1692 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1693 gcc_assert (CONST_INT_P (XEXP (address, 1))); |
0 | 1694 offset = INTVAL (XEXP (address, 1)); |
1695 address = XEXP (address, 0); | |
1696 } | |
1697 else | |
1698 offset = 0; | |
1699 | |
1700 pre_dec = (GET_CODE (address) == PRE_DEC); | |
1701 post_inc = (GET_CODE (address) == POST_INC); | |
1702 if (pre_dec || post_inc) | |
1703 address = XEXP (address, 0); | |
1704 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1705 gcc_assert (REG_P (address)); |
0 | 1706 |
1707 fputc ('(', file); | |
1708 if (pre_dec) | |
1709 fputs ("--", file); | |
1710 fputs (reg_names [REGNO (address)], file); | |
1711 if (post_inc) | |
1712 fputs ("++", file); | |
1713 if (offset != 0) | |
1714 fprintf (file, "," HOST_WIDE_INT_PRINT_DEC, offset); | |
1715 fputc (')', file); | |
1716 } | |
1717 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1718 /* Worker function for TARGET_PRINT_OPERAND. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1719 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1720 Print an operand to an assembler instruction. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1721 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1722 static void |
0 | 1723 xstormy16_print_operand (FILE *file, rtx x, int code) |
1724 { | |
1725 switch (code) | |
1726 { | |
1727 case 'B': | |
1728 /* There is either one bit set, or one bit clear, in X. | |
1729 Print it preceded by '#'. */ | |
1730 { | |
1731 static int bits_set[8] = { 0, 1, 1, 2, 1, 2, 2, 3 }; | |
1732 HOST_WIDE_INT xx = 1; | |
1733 HOST_WIDE_INT l; | |
1734 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1735 if (CONST_INT_P (x)) |
0 | 1736 xx = INTVAL (x); |
1737 else | |
1738 output_operand_lossage ("'B' operand is not constant"); | |
1739 | |
1740 /* GCC sign-extends masks with the MSB set, so we have to | |
1741 detect all the cases that differ only in sign extension | |
1742 beyond the bits we care about. Normally, the predicates | |
1743 and constraints ensure that we have the right values. This | |
1744 works correctly for valid masks. */ | |
1745 if (bits_set[xx & 7] <= 1) | |
1746 { | |
1747 /* Remove sign extension bits. */ | |
1748 if ((~xx & ~(HOST_WIDE_INT)0xff) == 0) | |
1749 xx &= 0xff; | |
1750 else if ((~xx & ~(HOST_WIDE_INT)0xffff) == 0) | |
1751 xx &= 0xffff; | |
1752 l = exact_log2 (xx); | |
1753 } | |
1754 else | |
1755 { | |
1756 /* Add sign extension bits. */ | |
1757 if ((xx & ~(HOST_WIDE_INT)0xff) == 0) | |
1758 xx |= ~(HOST_WIDE_INT)0xff; | |
1759 else if ((xx & ~(HOST_WIDE_INT)0xffff) == 0) | |
1760 xx |= ~(HOST_WIDE_INT)0xffff; | |
1761 l = exact_log2 (~xx); | |
1762 } | |
1763 | |
1764 if (l == -1) | |
1765 output_operand_lossage ("'B' operand has multiple bits set"); | |
1766 | |
1767 fprintf (file, IMMEDIATE_PREFIX HOST_WIDE_INT_PRINT_DEC, l); | |
1768 return; | |
1769 } | |
1770 | |
1771 case 'C': | |
1772 /* Print the symbol without a surrounding @fptr(). */ | |
1773 if (GET_CODE (x) == SYMBOL_REF) | |
1774 assemble_name (file, XSTR (x, 0)); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1775 else if (LABEL_P (x)) |
0 | 1776 output_asm_label (x); |
1777 else | |
111 | 1778 xstormy16_print_operand_address (file, VOIDmode, x); |
0 | 1779 return; |
1780 | |
1781 case 'o': | |
1782 case 'O': | |
1783 /* Print the immediate operand less one, preceded by '#'. | |
1784 For 'O', negate it first. */ | |
1785 { | |
1786 HOST_WIDE_INT xx = 0; | |
1787 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1788 if (CONST_INT_P (x)) |
0 | 1789 xx = INTVAL (x); |
1790 else | |
1791 output_operand_lossage ("'o' operand is not constant"); | |
1792 | |
1793 if (code == 'O') | |
1794 xx = -xx; | |
1795 | |
1796 fprintf (file, IMMEDIATE_PREFIX HOST_WIDE_INT_PRINT_DEC, xx - 1); | |
1797 return; | |
1798 } | |
1799 | |
1800 case 'b': | |
1801 /* Print the shift mask for bp/bn. */ | |
1802 { | |
1803 HOST_WIDE_INT xx = 1; | |
1804 HOST_WIDE_INT l; | |
1805 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1806 if (CONST_INT_P (x)) |
0 | 1807 xx = INTVAL (x); |
1808 else | |
1809 output_operand_lossage ("'B' operand is not constant"); | |
1810 | |
1811 l = 7 - xx; | |
1812 | |
1813 fputs (IMMEDIATE_PREFIX, file); | |
1814 fprintf (file, HOST_WIDE_INT_PRINT_DEC, l); | |
1815 return; | |
1816 } | |
1817 | |
1818 case 0: | |
1819 /* Handled below. */ | |
1820 break; | |
1821 | |
1822 default: | |
1823 output_operand_lossage ("xstormy16_print_operand: unknown code"); | |
1824 return; | |
1825 } | |
1826 | |
1827 switch (GET_CODE (x)) | |
1828 { | |
1829 case REG: | |
1830 fputs (reg_names [REGNO (x)], file); | |
1831 break; | |
1832 | |
1833 case MEM: | |
111 | 1834 xstormy16_print_operand_address (file, GET_MODE (x), XEXP (x, 0)); |
0 | 1835 break; |
1836 | |
1837 default: | |
1838 /* Some kind of constant or label; an immediate operand, | |
1839 so prefix it with '#' for the assembler. */ | |
1840 fputs (IMMEDIATE_PREFIX, file); | |
1841 output_addr_const (file, x); | |
1842 break; | |
1843 } | |
1844 | |
1845 return; | |
1846 } | |
1847 | |
1848 /* Expander for the `casesi' pattern. | |
1849 INDEX is the index of the switch statement. | |
1850 LOWER_BOUND is a CONST_INT that is the value of INDEX corresponding | |
1851 to the first table entry. | |
1852 RANGE is the number of table entries. | |
1853 TABLE is an ADDR_VEC that is the jump table. | |
1854 DEFAULT_LABEL is the address to branch to if INDEX is outside the | |
1855 range LOWER_BOUND to LOWER_BOUND + RANGE - 1. */ | |
1856 | |
1857 void | |
1858 xstormy16_expand_casesi (rtx index, rtx lower_bound, rtx range, | |
1859 rtx table, rtx default_label) | |
1860 { | |
1861 HOST_WIDE_INT range_i = INTVAL (range); | |
1862 rtx int_index; | |
1863 | |
1864 /* This code uses 'br', so it can deal only with tables of size up to | |
1865 8192 entries. */ | |
1866 if (range_i >= 8192) | |
1867 sorry ("switch statement of size %lu entries too large", | |
1868 (unsigned long) range_i); | |
1869 | |
1870 index = expand_binop (SImode, sub_optab, index, lower_bound, NULL_RTX, 0, | |
1871 OPTAB_LIB_WIDEN); | |
1872 emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, SImode, 1, | |
1873 default_label); | |
1874 int_index = gen_lowpart_common (HImode, index); | |
1875 emit_insn (gen_ashlhi3 (int_index, int_index, const2_rtx)); | |
1876 emit_jump_insn (gen_tablejump_pcrel (int_index, table)); | |
1877 } | |
1878 | |
1879 /* Output an ADDR_VEC. It is output as a sequence of 'jmpf' | |
1880 instructions, without label or alignment or any other special | |
1881 constructs. We know that the previous instruction will be the | |
1882 `tablejump_pcrel' output above. | |
1883 | |
1884 TODO: it might be nice to output 'br' instructions if they could | |
1885 all reach. */ | |
1886 | |
1887 void | |
1888 xstormy16_output_addr_vec (FILE *file, rtx label ATTRIBUTE_UNUSED, rtx table) | |
1889 { | |
1890 int vlen, idx; | |
1891 | |
1892 switch_to_section (current_function_section ()); | |
1893 | |
1894 vlen = XVECLEN (table, 0); | |
1895 for (idx = 0; idx < vlen; idx++) | |
1896 { | |
1897 fputs ("\tjmpf ", file); | |
1898 output_asm_label (XEXP (XVECEXP (table, 0, idx), 0)); | |
1899 fputc ('\n', file); | |
1900 } | |
1901 } | |
1902 | |
1903 /* Expander for the `call' patterns. | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1904 RETVAL is the RTL for the return register or NULL for void functions. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1905 DEST is the function to call, expressed as a MEM. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1906 COUNTER is ignored. */ |
0 | 1907 |
1908 void | |
1909 xstormy16_expand_call (rtx retval, rtx dest, rtx counter) | |
1910 { | |
1911 rtx call, temp; | |
111 | 1912 machine_mode mode; |
0 | 1913 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1914 gcc_assert (MEM_P (dest)); |
0 | 1915 dest = XEXP (dest, 0); |
1916 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1917 if (! CONSTANT_P (dest) && ! REG_P (dest)) |
0 | 1918 dest = force_reg (Pmode, dest); |
1919 | |
1920 if (retval == NULL) | |
1921 mode = VOIDmode; | |
1922 else | |
1923 mode = GET_MODE (retval); | |
1924 | |
1925 call = gen_rtx_CALL (mode, gen_rtx_MEM (FUNCTION_MODE, dest), | |
1926 counter); | |
1927 if (retval) | |
111 | 1928 call = gen_rtx_SET (retval, call); |
0 | 1929 |
1930 if (! CONSTANT_P (dest)) | |
1931 { | |
1932 temp = gen_reg_rtx (HImode); | |
1933 emit_move_insn (temp, const0_rtx); | |
1934 } | |
1935 else | |
1936 temp = const0_rtx; | |
1937 | |
1938 call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, | |
1939 gen_rtx_USE (VOIDmode, temp))); | |
1940 emit_call_insn (call); | |
1941 } | |
1942 | |
1943 /* Expanders for multiword computational operations. */ | |
1944 | |
1945 /* Expander for arithmetic operations; emit insns to compute | |
1946 | |
1947 (set DEST (CODE:MODE SRC0 SRC1)) | |
1948 | |
1949 When CODE is COMPARE, a branch template is generated | |
1950 (this saves duplicating code in xstormy16_split_cbranch). */ | |
1951 | |
1952 void | |
111 | 1953 xstormy16_expand_arith (machine_mode mode, enum rtx_code code, |
0 | 1954 rtx dest, rtx src0, rtx src1) |
1955 { | |
1956 int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; | |
1957 int i; | |
1958 int firstloop = 1; | |
1959 | |
1960 if (code == NEG) | |
1961 emit_move_insn (src0, const0_rtx); | |
1962 | |
1963 for (i = 0; i < num_words; i++) | |
1964 { | |
1965 rtx w_src0, w_src1, w_dest; | |
1966 rtx insn; | |
1967 | |
1968 w_src0 = simplify_gen_subreg (word_mode, src0, mode, | |
1969 i * UNITS_PER_WORD); | |
1970 w_src1 = simplify_gen_subreg (word_mode, src1, mode, i * UNITS_PER_WORD); | |
1971 w_dest = simplify_gen_subreg (word_mode, dest, mode, i * UNITS_PER_WORD); | |
1972 | |
1973 switch (code) | |
1974 { | |
1975 case PLUS: | |
1976 if (firstloop | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1977 && CONST_INT_P (w_src1) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1978 && INTVAL (w_src1) == 0) |
0 | 1979 continue; |
1980 | |
1981 if (firstloop) | |
1982 insn = gen_addchi4 (w_dest, w_src0, w_src1); | |
1983 else | |
1984 insn = gen_addchi5 (w_dest, w_src0, w_src1); | |
1985 break; | |
1986 | |
1987 case NEG: | |
1988 case MINUS: | |
1989 case COMPARE: | |
1990 if (code == COMPARE && i == num_words - 1) | |
1991 { | |
1992 rtx branch, sub, clobber, sub_1; | |
1993 | |
1994 sub_1 = gen_rtx_MINUS (HImode, w_src0, | |
1995 gen_rtx_ZERO_EXTEND (HImode, gen_rtx_REG (BImode, CARRY_REGNUM))); | |
111 | 1996 sub = gen_rtx_SET (w_dest, |
0 | 1997 gen_rtx_MINUS (HImode, sub_1, w_src1)); |
1998 clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, CARRY_REGNUM)); | |
111 | 1999 branch = gen_rtx_SET (pc_rtx, |
0 | 2000 gen_rtx_IF_THEN_ELSE (VOIDmode, |
2001 gen_rtx_EQ (HImode, | |
2002 sub_1, | |
2003 w_src1), | |
2004 pc_rtx, | |
2005 pc_rtx)); | |
2006 insn = gen_rtx_PARALLEL (VOIDmode, | |
2007 gen_rtvec (3, branch, sub, clobber)); | |
2008 } | |
2009 else if (firstloop | |
2010 && code != COMPARE | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2011 && CONST_INT_P (w_src1) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2012 && INTVAL (w_src1) == 0) |
0 | 2013 continue; |
2014 else if (firstloop) | |
2015 insn = gen_subchi4 (w_dest, w_src0, w_src1); | |
2016 else | |
2017 insn = gen_subchi5 (w_dest, w_src0, w_src1); | |
2018 break; | |
2019 | |
2020 case IOR: | |
2021 case XOR: | |
2022 case AND: | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2023 if (CONST_INT_P (w_src1) |
0 | 2024 && INTVAL (w_src1) == -(code == AND)) |
2025 continue; | |
2026 | |
111 | 2027 insn = gen_rtx_SET (w_dest, gen_rtx_fmt_ee (code, mode, |
2028 w_src0, w_src1)); | |
0 | 2029 break; |
2030 | |
2031 case NOT: | |
111 | 2032 insn = gen_rtx_SET (w_dest, gen_rtx_NOT (mode, w_src0)); |
0 | 2033 break; |
2034 | |
2035 default: | |
2036 gcc_unreachable (); | |
2037 } | |
2038 | |
2039 firstloop = 0; | |
2040 emit (insn); | |
2041 } | |
2042 | |
2043 /* If we emit nothing, try_split() will think we failed. So emit | |
2044 something that does nothing and can be optimized away. */ | |
2045 if (firstloop) | |
2046 emit (gen_nop ()); | |
2047 } | |
2048 | |
2049 /* The shift operations are split at output time for constant values; | |
2050 variable-width shifts get handed off to a library routine. | |
2051 | |
2052 Generate an output string to do (set X (CODE:MODE X SIZE_R)) | |
2053 SIZE_R will be a CONST_INT, X will be a hard register. */ | |
2054 | |
2055 const char * | |
111 | 2056 xstormy16_output_shift (machine_mode mode, enum rtx_code code, |
0 | 2057 rtx x, rtx size_r, rtx temp) |
2058 { | |
2059 HOST_WIDE_INT size; | |
2060 const char *r0, *r1, *rt; | |
2061 static char r[64]; | |
2062 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2063 gcc_assert (CONST_INT_P (size_r) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2064 && REG_P (x) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2065 && mode == SImode); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2066 |
0 | 2067 size = INTVAL (size_r) & (GET_MODE_BITSIZE (mode) - 1); |
2068 | |
2069 if (size == 0) | |
2070 return ""; | |
2071 | |
2072 r0 = reg_names [REGNO (x)]; | |
2073 r1 = reg_names [REGNO (x) + 1]; | |
2074 | |
2075 /* For shifts of size 1, we can use the rotate instructions. */ | |
2076 if (size == 1) | |
2077 { | |
2078 switch (code) | |
2079 { | |
2080 case ASHIFT: | |
2081 sprintf (r, "shl %s,#1 | rlc %s,#1", r0, r1); | |
2082 break; | |
2083 case ASHIFTRT: | |
2084 sprintf (r, "asr %s,#1 | rrc %s,#1", r1, r0); | |
2085 break; | |
2086 case LSHIFTRT: | |
2087 sprintf (r, "shr %s,#1 | rrc %s,#1", r1, r0); | |
2088 break; | |
2089 default: | |
2090 gcc_unreachable (); | |
2091 } | |
2092 return r; | |
2093 } | |
2094 | |
2095 /* For large shifts, there are easy special cases. */ | |
2096 if (size == 16) | |
2097 { | |
2098 switch (code) | |
2099 { | |
2100 case ASHIFT: | |
2101 sprintf (r, "mov %s,%s | mov %s,#0", r1, r0, r0); | |
2102 break; | |
2103 case ASHIFTRT: | |
2104 sprintf (r, "mov %s,%s | asr %s,#15", r0, r1, r1); | |
2105 break; | |
2106 case LSHIFTRT: | |
2107 sprintf (r, "mov %s,%s | mov %s,#0", r0, r1, r1); | |
2108 break; | |
2109 default: | |
2110 gcc_unreachable (); | |
2111 } | |
2112 return r; | |
2113 } | |
2114 if (size > 16) | |
2115 { | |
2116 switch (code) | |
2117 { | |
2118 case ASHIFT: | |
2119 sprintf (r, "mov %s,%s | mov %s,#0 | shl %s,#%d", | |
2120 r1, r0, r0, r1, (int) size - 16); | |
2121 break; | |
2122 case ASHIFTRT: | |
2123 sprintf (r, "mov %s,%s | asr %s,#15 | asr %s,#%d", | |
2124 r0, r1, r1, r0, (int) size - 16); | |
2125 break; | |
2126 case LSHIFTRT: | |
2127 sprintf (r, "mov %s,%s | mov %s,#0 | shr %s,#%d", | |
2128 r0, r1, r1, r0, (int) size - 16); | |
2129 break; | |
2130 default: | |
2131 gcc_unreachable (); | |
2132 } | |
2133 return r; | |
2134 } | |
2135 | |
2136 /* For the rest, we have to do more work. In particular, we | |
2137 need a temporary. */ | |
2138 rt = reg_names [REGNO (temp)]; | |
2139 switch (code) | |
2140 { | |
2141 case ASHIFT: | |
2142 sprintf (r, | |
2143 "mov %s,%s | shl %s,#%d | shl %s,#%d | shr %s,#%d | or %s,%s", | |
2144 rt, r0, r0, (int) size, r1, (int) size, rt, (int) (16 - size), | |
2145 r1, rt); | |
2146 break; | |
2147 case ASHIFTRT: | |
2148 sprintf (r, | |
2149 "mov %s,%s | asr %s,#%d | shr %s,#%d | shl %s,#%d | or %s,%s", | |
2150 rt, r1, r1, (int) size, r0, (int) size, rt, (int) (16 - size), | |
2151 r0, rt); | |
2152 break; | |
2153 case LSHIFTRT: | |
2154 sprintf (r, | |
2155 "mov %s,%s | shr %s,#%d | shr %s,#%d | shl %s,#%d | or %s,%s", | |
2156 rt, r1, r1, (int) size, r0, (int) size, rt, (int) (16 - size), | |
2157 r0, rt); | |
2158 break; | |
2159 default: | |
2160 gcc_unreachable (); | |
2161 } | |
2162 return r; | |
2163 } | |
2164 | |
2165 /* Attribute handling. */ | |
2166 | |
2167 /* Return nonzero if the function is an interrupt function. */ | |
2168 | |
2169 int | |
2170 xstormy16_interrupt_function_p (void) | |
2171 { | |
2172 tree attributes; | |
2173 | |
2174 /* The dwarf2 mechanism asks for INCOMING_FRAME_SP_OFFSET before | |
2175 any functions are declared, which is demonstrably wrong, but | |
2176 it is worked around here. FIXME. */ | |
2177 if (!cfun) | |
2178 return 0; | |
2179 | |
2180 attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); | |
2181 return lookup_attribute ("interrupt", attributes) != NULL_TREE; | |
2182 } | |
2183 | |
2184 #undef TARGET_ATTRIBUTE_TABLE | |
2185 #define TARGET_ATTRIBUTE_TABLE xstormy16_attribute_table | |
2186 | |
2187 static tree xstormy16_handle_interrupt_attribute | |
2188 (tree *, tree, tree, int, bool *); | |
2189 static tree xstormy16_handle_below100_attribute | |
2190 (tree *, tree, tree, int, bool *); | |
2191 | |
2192 static const struct attribute_spec xstormy16_attribute_table[] = | |
2193 { | |
131 | 2194 /* name, min_len, max_len, decl_req, type_req, fn_type_req, |
2195 affects_type_identity, handler, exclude. */ | |
2196 { "interrupt", 0, 0, false, true, true, false, | |
2197 xstormy16_handle_interrupt_attribute, NULL }, | |
2198 { "BELOW100", 0, 0, false, false, false, false, | |
2199 xstormy16_handle_below100_attribute, NULL }, | |
2200 { "below100", 0, 0, false, false, false, false, | |
2201 xstormy16_handle_below100_attribute, NULL }, | |
2202 { NULL, 0, 0, false, false, false, false, NULL, NULL } | |
0 | 2203 }; |
2204 | |
2205 /* Handle an "interrupt" attribute; | |
2206 arguments as in struct attribute_spec.handler. */ | |
2207 | |
2208 static tree | |
2209 xstormy16_handle_interrupt_attribute (tree *node, tree name, | |
2210 tree args ATTRIBUTE_UNUSED, | |
2211 int flags ATTRIBUTE_UNUSED, | |
2212 bool *no_add_attrs) | |
2213 { | |
2214 if (TREE_CODE (*node) != FUNCTION_TYPE) | |
2215 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2216 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2217 name); |
0 | 2218 *no_add_attrs = true; |
2219 } | |
2220 | |
2221 return NULL_TREE; | |
2222 } | |
2223 | |
2224 /* Handle an "below" attribute; | |
2225 arguments as in struct attribute_spec.handler. */ | |
2226 | |
2227 static tree | |
2228 xstormy16_handle_below100_attribute (tree *node, | |
2229 tree name ATTRIBUTE_UNUSED, | |
2230 tree args ATTRIBUTE_UNUSED, | |
2231 int flags ATTRIBUTE_UNUSED, | |
2232 bool *no_add_attrs) | |
2233 { | |
2234 if (TREE_CODE (*node) != VAR_DECL | |
2235 && TREE_CODE (*node) != POINTER_TYPE | |
2236 && TREE_CODE (*node) != TYPE_DECL) | |
2237 { | |
2238 warning (OPT_Wattributes, | |
2239 "%<__BELOW100__%> attribute only applies to variables"); | |
2240 *no_add_attrs = true; | |
2241 } | |
2242 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL) | |
2243 { | |
2244 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node))) | |
2245 { | |
2246 warning (OPT_Wattributes, "__BELOW100__ attribute not allowed " | |
2247 "with auto storage class"); | |
2248 *no_add_attrs = true; | |
2249 } | |
2250 } | |
2251 | |
2252 return NULL_TREE; | |
2253 } | |
2254 | |
2255 #undef TARGET_INIT_BUILTINS | |
2256 #define TARGET_INIT_BUILTINS xstormy16_init_builtins | |
2257 #undef TARGET_EXPAND_BUILTIN | |
2258 #define TARGET_EXPAND_BUILTIN xstormy16_expand_builtin | |
2259 | |
2260 static struct | |
2261 { | |
2262 const char * name; | |
2263 int md_code; | |
2264 const char * arg_ops; /* 0..9, t for temp register, r for return value. */ | |
2265 const char * arg_types; /* s=short,l=long, upper case for unsigned. */ | |
2266 } | |
2267 s16builtins[] = | |
2268 { | |
2269 { "__sdivlh", CODE_FOR_sdivlh, "rt01", "sls" }, | |
2270 { "__smodlh", CODE_FOR_sdivlh, "tr01", "sls" }, | |
2271 { "__udivlh", CODE_FOR_udivlh, "rt01", "SLS" }, | |
2272 { "__umodlh", CODE_FOR_udivlh, "tr01", "SLS" }, | |
2273 { NULL, 0, NULL, NULL } | |
2274 }; | |
2275 | |
2276 static void | |
2277 xstormy16_init_builtins (void) | |
2278 { | |
111 | 2279 tree args[2], ret_type, arg = NULL_TREE, ftype; |
2280 int i, a, n_args; | |
0 | 2281 |
2282 ret_type = void_type_node; | |
2283 | |
2284 for (i = 0; s16builtins[i].name; i++) | |
2285 { | |
111 | 2286 n_args = strlen (s16builtins[i].arg_types) - 1; |
2287 | |
2288 gcc_assert (n_args <= (int) ARRAY_SIZE (args)); | |
2289 | |
2290 for (a = n_args - 1; a >= 0; a--) | |
2291 args[a] = NULL_TREE; | |
2292 | |
2293 for (a = n_args; a >= 0; a--) | |
0 | 2294 { |
2295 switch (s16builtins[i].arg_types[a]) | |
2296 { | |
2297 case 's': arg = short_integer_type_node; break; | |
2298 case 'S': arg = short_unsigned_type_node; break; | |
2299 case 'l': arg = long_integer_type_node; break; | |
2300 case 'L': arg = long_unsigned_type_node; break; | |
2301 default: gcc_unreachable (); | |
2302 } | |
2303 if (a == 0) | |
2304 ret_type = arg; | |
2305 else | |
111 | 2306 args[a-1] = arg; |
0 | 2307 } |
111 | 2308 ftype = build_function_type_list (ret_type, args[0], args[1], NULL_TREE); |
2309 add_builtin_function (s16builtins[i].name, ftype, | |
2310 i, BUILT_IN_MD, NULL, NULL_TREE); | |
0 | 2311 } |
2312 } | |
2313 | |
2314 static rtx | |
2315 xstormy16_expand_builtin (tree exp, rtx target, | |
2316 rtx subtarget ATTRIBUTE_UNUSED, | |
111 | 2317 machine_mode mode ATTRIBUTE_UNUSED, |
0 | 2318 int ignore ATTRIBUTE_UNUSED) |
2319 { | |
2320 rtx op[10], args[10], pat, copyto[10], retval = 0; | |
2321 tree fndecl, argtree; | |
2322 int i, a, o, code; | |
2323 | |
2324 fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); | |
2325 argtree = TREE_OPERAND (exp, 1); | |
2326 i = DECL_FUNCTION_CODE (fndecl); | |
2327 code = s16builtins[i].md_code; | |
2328 | |
2329 for (a = 0; a < 10 && argtree; a++) | |
2330 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2331 args[a] = expand_normal (TREE_VALUE (argtree)); |
0 | 2332 argtree = TREE_CHAIN (argtree); |
2333 } | |
2334 | |
2335 for (o = 0; s16builtins[i].arg_ops[o]; o++) | |
2336 { | |
2337 char ao = s16builtins[i].arg_ops[o]; | |
2338 char c = insn_data[code].operand[o].constraint[0]; | |
111 | 2339 machine_mode omode; |
0 | 2340 |
2341 copyto[o] = 0; | |
2342 | |
111 | 2343 omode = (machine_mode) insn_data[code].operand[o].mode; |
0 | 2344 if (ao == 'r') |
2345 op[o] = target ? target : gen_reg_rtx (omode); | |
2346 else if (ao == 't') | |
2347 op[o] = gen_reg_rtx (omode); | |
2348 else | |
2349 op[o] = args[(int) hex_value (ao)]; | |
2350 | |
2351 if (! (*insn_data[code].operand[o].predicate) (op[o], GET_MODE (op[o]))) | |
2352 { | |
2353 if (c == '+' || c == '=') | |
2354 { | |
2355 copyto[o] = op[o]; | |
2356 op[o] = gen_reg_rtx (omode); | |
2357 } | |
2358 else | |
2359 op[o] = copy_to_mode_reg (omode, op[o]); | |
2360 } | |
2361 | |
2362 if (ao == 'r') | |
2363 retval = op[o]; | |
2364 } | |
2365 | |
2366 pat = GEN_FCN (code) (op[0], op[1], op[2], op[3], op[4], | |
2367 op[5], op[6], op[7], op[8], op[9]); | |
2368 emit_insn (pat); | |
2369 | |
2370 for (o = 0; s16builtins[i].arg_ops[o]; o++) | |
2371 if (copyto[o]) | |
2372 { | |
2373 emit_move_insn (copyto[o], op[o]); | |
2374 if (op[o] == retval) | |
2375 retval = copyto[o]; | |
2376 } | |
2377 | |
2378 return retval; | |
2379 } | |
2380 | |
2381 /* Look for combinations of insns that can be converted to BN or BP | |
2382 opcodes. This is, unfortunately, too complex to do with MD | |
2383 patterns. */ | |
2384 | |
2385 static void | |
111 | 2386 combine_bnp (rtx_insn *insn) |
0 | 2387 { |
2388 int insn_code, regno, need_extend; | |
2389 unsigned int mask; | |
111 | 2390 rtx cond, reg, qireg, mem; |
2391 rtx_insn *and_insn, *load; | |
2392 machine_mode load_mode = QImode; | |
2393 machine_mode and_mode = QImode; | |
2394 rtx_insn *shift = NULL; | |
0 | 2395 |
2396 insn_code = recog_memoized (insn); | |
2397 if (insn_code != CODE_FOR_cbranchhi | |
2398 && insn_code != CODE_FOR_cbranchhi_neg) | |
2399 return; | |
2400 | |
2401 cond = XVECEXP (PATTERN (insn), 0, 0); /* set */ | |
2402 cond = XEXP (cond, 1); /* if */ | |
2403 cond = XEXP (cond, 0); /* cond */ | |
2404 switch (GET_CODE (cond)) | |
2405 { | |
2406 case NE: | |
2407 case EQ: | |
2408 need_extend = 0; | |
2409 break; | |
2410 case LT: | |
2411 case GE: | |
2412 need_extend = 1; | |
2413 break; | |
2414 default: | |
2415 return; | |
2416 } | |
2417 | |
2418 reg = XEXP (cond, 0); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2419 if (! REG_P (reg)) |
0 | 2420 return; |
2421 regno = REGNO (reg); | |
2422 if (XEXP (cond, 1) != const0_rtx) | |
2423 return; | |
2424 if (! find_regno_note (insn, REG_DEAD, regno)) | |
2425 return; | |
2426 qireg = gen_rtx_REG (QImode, regno); | |
2427 | |
2428 if (need_extend) | |
2429 { | |
2430 /* LT and GE conditionals should have a sign extend before | |
2431 them. */ | |
111 | 2432 for (and_insn = prev_real_insn (insn); |
2433 and_insn != NULL_RTX; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2434 and_insn = prev_real_insn (and_insn)) |
0 | 2435 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2436 int and_code = recog_memoized (and_insn); |
0 | 2437 |
2438 if (and_code == CODE_FOR_extendqihi2 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2439 && rtx_equal_p (SET_DEST (PATTERN (and_insn)), reg) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2440 && rtx_equal_p (XEXP (SET_SRC (PATTERN (and_insn)), 0), qireg)) |
0 | 2441 break; |
2442 | |
2443 if (and_code == CODE_FOR_movhi_internal | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2444 && rtx_equal_p (SET_DEST (PATTERN (and_insn)), reg)) |
0 | 2445 { |
2446 /* This is for testing bit 15. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2447 and_insn = insn; |
0 | 2448 break; |
2449 } | |
2450 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2451 if (reg_mentioned_p (reg, and_insn)) |
0 | 2452 return; |
2453 | |
111 | 2454 if (! NOTE_P (and_insn) && ! NONJUMP_INSN_P (and_insn)) |
0 | 2455 return; |
2456 } | |
2457 } | |
2458 else | |
2459 { | |
2460 /* EQ and NE conditionals have an AND before them. */ | |
111 | 2461 for (and_insn = prev_real_insn (insn); |
2462 and_insn != NULL_RTX; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2463 and_insn = prev_real_insn (and_insn)) |
0 | 2464 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2465 if (recog_memoized (and_insn) == CODE_FOR_andhi3 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2466 && rtx_equal_p (SET_DEST (PATTERN (and_insn)), reg) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2467 && rtx_equal_p (XEXP (SET_SRC (PATTERN (and_insn)), 0), reg)) |
0 | 2468 break; |
2469 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2470 if (reg_mentioned_p (reg, and_insn)) |
0 | 2471 return; |
2472 | |
111 | 2473 if (! NOTE_P (and_insn) && ! NONJUMP_INSN_P (and_insn)) |
0 | 2474 return; |
2475 } | |
2476 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2477 if (and_insn) |
0 | 2478 { |
2479 /* Some mis-optimizations by GCC can generate a RIGHT-SHIFT | |
2480 followed by an AND like this: | |
2481 | |
2482 (parallel [(set (reg:HI r7) (lshiftrt:HI (reg:HI r7) (const_int 3))) | |
2483 (clobber (reg:BI carry))] | |
2484 | |
2485 (set (reg:HI r7) (and:HI (reg:HI r7) (const_int 1))) | |
2486 | |
2487 Attempt to detect this here. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2488 for (shift = prev_real_insn (and_insn); shift; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2489 shift = prev_real_insn (shift)) |
0 | 2490 { |
2491 if (recog_memoized (shift) == CODE_FOR_lshrhi3 | |
2492 && rtx_equal_p (SET_DEST (XVECEXP (PATTERN (shift), 0, 0)), reg) | |
2493 && rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (shift), 0, 0)), 0), reg)) | |
2494 break; | |
2495 | |
2496 if (reg_mentioned_p (reg, shift) | |
111 | 2497 || (! NOTE_P (shift) && ! NONJUMP_INSN_P (shift))) |
0 | 2498 { |
111 | 2499 shift = NULL; |
0 | 2500 break; |
2501 } | |
2502 } | |
2503 } | |
2504 } | |
111 | 2505 |
2506 if (and_insn == NULL_RTX) | |
0 | 2507 return; |
2508 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2509 for (load = shift ? prev_real_insn (shift) : prev_real_insn (and_insn); |
0 | 2510 load; |
2511 load = prev_real_insn (load)) | |
2512 { | |
2513 int load_code = recog_memoized (load); | |
2514 | |
2515 if (load_code == CODE_FOR_movhi_internal | |
2516 && rtx_equal_p (SET_DEST (PATTERN (load)), reg) | |
2517 && xstormy16_below100_operand (SET_SRC (PATTERN (load)), HImode) | |
2518 && ! MEM_VOLATILE_P (SET_SRC (PATTERN (load)))) | |
2519 { | |
2520 load_mode = HImode; | |
2521 break; | |
2522 } | |
2523 | |
2524 if (load_code == CODE_FOR_movqi_internal | |
2525 && rtx_equal_p (SET_DEST (PATTERN (load)), qireg) | |
2526 && xstormy16_below100_operand (SET_SRC (PATTERN (load)), QImode)) | |
2527 { | |
2528 load_mode = QImode; | |
2529 break; | |
2530 } | |
2531 | |
2532 if (load_code == CODE_FOR_zero_extendqihi2 | |
2533 && rtx_equal_p (SET_DEST (PATTERN (load)), reg) | |
2534 && xstormy16_below100_operand (XEXP (SET_SRC (PATTERN (load)), 0), QImode)) | |
2535 { | |
2536 load_mode = QImode; | |
2537 and_mode = HImode; | |
2538 break; | |
2539 } | |
2540 | |
2541 if (reg_mentioned_p (reg, load)) | |
2542 return; | |
2543 | |
111 | 2544 if (! NOTE_P (load) && ! NONJUMP_INSN_P (load)) |
0 | 2545 return; |
2546 } | |
2547 if (!load) | |
2548 return; | |
2549 | |
2550 mem = SET_SRC (PATTERN (load)); | |
2551 | |
2552 if (need_extend) | |
2553 { | |
2554 mask = (load_mode == HImode) ? 0x8000 : 0x80; | |
2555 | |
2556 /* If the mem includes a zero-extend operation and we are | |
2557 going to generate a sign-extend operation then move the | |
2558 mem inside the zero-extend. */ | |
2559 if (GET_CODE (mem) == ZERO_EXTEND) | |
2560 mem = XEXP (mem, 0); | |
2561 } | |
2562 else | |
2563 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2564 if (!xstormy16_onebit_set_operand (XEXP (SET_SRC (PATTERN (and_insn)), 1), |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2565 load_mode)) |
0 | 2566 return; |
2567 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2568 mask = (int) INTVAL (XEXP (SET_SRC (PATTERN (and_insn)), 1)); |
0 | 2569 |
2570 if (shift) | |
2571 mask <<= INTVAL (XEXP (SET_SRC (XVECEXP (PATTERN (shift), 0, 0)), 1)); | |
2572 } | |
2573 | |
2574 if (load_mode == HImode) | |
2575 { | |
2576 rtx addr = XEXP (mem, 0); | |
2577 | |
2578 if (! (mask & 0xff)) | |
2579 { | |
111 | 2580 addr = plus_constant (Pmode, addr, 1); |
0 | 2581 mask >>= 8; |
2582 } | |
2583 mem = gen_rtx_MEM (QImode, addr); | |
2584 } | |
2585 | |
2586 if (need_extend) | |
2587 XEXP (cond, 0) = gen_rtx_SIGN_EXTEND (HImode, mem); | |
2588 else | |
2589 XEXP (cond, 0) = gen_rtx_AND (and_mode, mem, GEN_INT (mask)); | |
2590 | |
2591 INSN_CODE (insn) = -1; | |
2592 delete_insn (load); | |
2593 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2594 if (and_insn != insn) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2595 delete_insn (and_insn); |
0 | 2596 |
2597 if (shift != NULL_RTX) | |
2598 delete_insn (shift); | |
2599 } | |
2600 | |
2601 static void | |
2602 xstormy16_reorg (void) | |
2603 { | |
111 | 2604 rtx_insn *insn; |
0 | 2605 |
2606 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | |
2607 { | |
2608 if (! JUMP_P (insn)) | |
2609 continue; | |
2610 combine_bnp (insn); | |
2611 } | |
2612 } | |
2613 | |
2614 /* Worker function for TARGET_RETURN_IN_MEMORY. */ | |
2615 | |
2616 static bool | |
2617 xstormy16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) | |
2618 { | |
2619 const HOST_WIDE_INT size = int_size_in_bytes (type); | |
2620 return (size == -1 || size > UNITS_PER_WORD * NUM_ARGUMENT_REGISTERS); | |
2621 } | |
111 | 2622 |
2623 /* Implement TARGET_HARD_REGNO_MODE_OK. */ | |
2624 | |
2625 static bool | |
2626 xstormy16_hard_regno_mode_ok (unsigned int regno, machine_mode mode) | |
2627 { | |
2628 return regno != 16 || mode == BImode; | |
2629 } | |
2630 | |
2631 /* Implement TARGET_MODES_TIEABLE_P. */ | |
2632 | |
2633 static bool | |
2634 xstormy16_modes_tieable_p (machine_mode mode1, machine_mode mode2) | |
2635 { | |
2636 return mode1 != BImode && mode2 != BImode; | |
2637 } | |
131 | 2638 |
2639 /* Implement PUSH_ROUNDING. */ | |
2640 | |
2641 poly_int64 | |
2642 xstormy16_push_rounding (poly_int64 bytes) | |
2643 { | |
2644 return (bytes + 1) & ~1; | |
2645 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2646 |
0 | 2647 #undef TARGET_ASM_ALIGNED_HI_OP |
2648 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" | |
2649 #undef TARGET_ASM_ALIGNED_SI_OP | |
2650 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" | |
2651 #undef TARGET_ENCODE_SECTION_INFO | |
2652 #define TARGET_ENCODE_SECTION_INFO xstormy16_encode_section_info | |
2653 | |
2654 /* Select_section doesn't handle .bss_below100. */ | |
2655 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS | |
2656 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false | |
2657 | |
2658 #undef TARGET_ASM_OUTPUT_MI_THUNK | |
2659 #define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk | |
2660 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK | |
2661 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall | |
2662 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2663 #undef TARGET_PRINT_OPERAND |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2664 #define TARGET_PRINT_OPERAND xstormy16_print_operand |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2665 #undef TARGET_PRINT_OPERAND_ADDRESS |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2666 #define TARGET_PRINT_OPERAND_ADDRESS xstormy16_print_operand_address |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2667 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2668 #undef TARGET_MEMORY_MOVE_COST |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2669 #define TARGET_MEMORY_MOVE_COST xstormy16_memory_move_cost |
0 | 2670 #undef TARGET_RTX_COSTS |
2671 #define TARGET_RTX_COSTS xstormy16_rtx_costs | |
2672 #undef TARGET_ADDRESS_COST | |
2673 #define TARGET_ADDRESS_COST xstormy16_address_cost | |
2674 | |
2675 #undef TARGET_BUILD_BUILTIN_VA_LIST | |
2676 #define TARGET_BUILD_BUILTIN_VA_LIST xstormy16_build_builtin_va_list | |
2677 #undef TARGET_EXPAND_BUILTIN_VA_START | |
2678 #define TARGET_EXPAND_BUILTIN_VA_START xstormy16_expand_builtin_va_start | |
2679 #undef TARGET_GIMPLIFY_VA_ARG_EXPR | |
2680 #define TARGET_GIMPLIFY_VA_ARG_EXPR xstormy16_gimplify_va_arg_expr | |
2681 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2682 #undef TARGET_PROMOTE_FUNCTION_MODE |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2683 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote |
0 | 2684 #undef TARGET_PROMOTE_PROTOTYPES |
2685 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | |
2686 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2687 #undef TARGET_FUNCTION_ARG |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2688 #define TARGET_FUNCTION_ARG xstormy16_function_arg |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2689 #undef TARGET_FUNCTION_ARG_ADVANCE |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2690 #define TARGET_FUNCTION_ARG_ADVANCE xstormy16_function_arg_advance |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2691 |
0 | 2692 #undef TARGET_RETURN_IN_MEMORY |
2693 #define TARGET_RETURN_IN_MEMORY xstormy16_return_in_memory | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2694 #undef TARGET_FUNCTION_VALUE |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2695 #define TARGET_FUNCTION_VALUE xstormy16_function_value |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2696 #undef TARGET_LIBCALL_VALUE |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2697 #define TARGET_LIBCALL_VALUE xstormy16_libcall_value |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2698 #undef TARGET_FUNCTION_VALUE_REGNO_P |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2699 #define TARGET_FUNCTION_VALUE_REGNO_P xstormy16_function_value_regno_p |
0 | 2700 |
2701 #undef TARGET_MACHINE_DEPENDENT_REORG | |
2702 #define TARGET_MACHINE_DEPENDENT_REORG xstormy16_reorg | |
2703 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2704 #undef TARGET_PREFERRED_RELOAD_CLASS |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2705 #define TARGET_PREFERRED_RELOAD_CLASS xstormy16_preferred_reload_class |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2706 #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2707 #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS xstormy16_preferred_reload_class |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2708 |
111 | 2709 #undef TARGET_LRA_P |
2710 #define TARGET_LRA_P hook_bool_void_false | |
2711 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2712 #undef TARGET_LEGITIMATE_ADDRESS_P |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2713 #define TARGET_LEGITIMATE_ADDRESS_P xstormy16_legitimate_address_p |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2714 #undef TARGET_MODE_DEPENDENT_ADDRESS_P |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2715 #define TARGET_MODE_DEPENDENT_ADDRESS_P xstormy16_mode_dependent_address_p |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2716 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2717 #undef TARGET_CAN_ELIMINATE |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2718 #define TARGET_CAN_ELIMINATE xstormy16_can_eliminate |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2719 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2720 #undef TARGET_TRAMPOLINE_INIT |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2721 #define TARGET_TRAMPOLINE_INIT xstormy16_trampoline_init |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2722 |
111 | 2723 #undef TARGET_HARD_REGNO_MODE_OK |
2724 #define TARGET_HARD_REGNO_MODE_OK xstormy16_hard_regno_mode_ok | |
2725 #undef TARGET_MODES_TIEABLE_P | |
2726 #define TARGET_MODES_TIEABLE_P xstormy16_modes_tieable_p | |
2727 | |
2728 #undef TARGET_CONSTANT_ALIGNMENT | |
2729 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2730 |
131 | 2731 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE |
2732 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed | |
2733 | |
0 | 2734 struct gcc_target targetm = TARGET_INITIALIZER; |
2735 | |
2736 #include "gt-stormy16.h" |