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