1 | /* Subroutines for insn-output.c for Hitachi H8/300. |
---|
2 | Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. |
---|
3 | Contributed by Steve Chamberlain (sac@cygnus.com), |
---|
4 | Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com). |
---|
5 | |
---|
6 | This file is part of GNU CC. |
---|
7 | |
---|
8 | GNU CC 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 2, or (at your option) |
---|
11 | any later version. |
---|
12 | |
---|
13 | GNU CC 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 GNU CC; see the file COPYING. If not, write to |
---|
20 | the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
21 | Boston, MA 02111-1307, USA. */ |
---|
22 | |
---|
23 | #include "config.h" |
---|
24 | #include <stdio.h> |
---|
25 | #include "rtl.h" |
---|
26 | #include "regs.h" |
---|
27 | #include "hard-reg-set.h" |
---|
28 | #include "real.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" |
---|
36 | #include "expr.h" |
---|
37 | #include "tree.h" |
---|
38 | #include "obstack.h" |
---|
39 | |
---|
40 | /* Forward declarations. */ |
---|
41 | void print_operand_address (); |
---|
42 | char *index (); |
---|
43 | |
---|
44 | static int h8300_interrupt_function_p PROTO ((tree)); |
---|
45 | static int h8300_monitor_function_p PROTO ((tree)); |
---|
46 | static int h8300_os_task_function_p PROTO ((tree)); |
---|
47 | |
---|
48 | /* CPU_TYPE, says what cpu we're compiling for. */ |
---|
49 | int cpu_type; |
---|
50 | |
---|
51 | /* True if the current function is an interrupt handler |
---|
52 | (either via #pragma or an attribute specification). */ |
---|
53 | int interrupt_handler; |
---|
54 | |
---|
55 | /* True if the current function is an OS Task |
---|
56 | (via an attribute specification). */ |
---|
57 | int os_task; |
---|
58 | |
---|
59 | /* True if the current function is a monitor |
---|
60 | (via an attribute specification). */ |
---|
61 | int monitor; |
---|
62 | |
---|
63 | /* True if a #pragma saveall has been seen for the current function. */ |
---|
64 | int pragma_saveall; |
---|
65 | |
---|
66 | static char *names_big[] = |
---|
67 | {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"}; |
---|
68 | |
---|
69 | static char *names_extended[] = |
---|
70 | {"er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"}; |
---|
71 | |
---|
72 | static char *names_upper_extended[] = |
---|
73 | {"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"}; |
---|
74 | |
---|
75 | /* Points to one of the above. */ |
---|
76 | /* ??? The above could be put in an array indexed by CPU_TYPE. */ |
---|
77 | char **h8_reg_names; |
---|
78 | |
---|
79 | /* Various operations needed by the following, indexed by CPU_TYPE. */ |
---|
80 | |
---|
81 | static char *h8_push_ops[2] = |
---|
82 | {"push", "push.l"}; |
---|
83 | static char *h8_pop_ops[2] = |
---|
84 | {"pop", "pop.l"}; |
---|
85 | static char *h8_mov_ops[2] = |
---|
86 | {"mov.w", "mov.l"}; |
---|
87 | |
---|
88 | char *h8_push_op, *h8_pop_op, *h8_mov_op; |
---|
89 | |
---|
90 | /* Initialize various cpu specific globals at start up. */ |
---|
91 | |
---|
92 | void |
---|
93 | h8300_init_once () |
---|
94 | { |
---|
95 | if (TARGET_H8300) |
---|
96 | { |
---|
97 | cpu_type = (int) CPU_H8300; |
---|
98 | h8_reg_names = names_big; |
---|
99 | } |
---|
100 | else |
---|
101 | { |
---|
102 | /* For this we treat the H8/300 and H8/S the same. */ |
---|
103 | cpu_type = (int) CPU_H8300H; |
---|
104 | h8_reg_names = names_extended; |
---|
105 | } |
---|
106 | h8_push_op = h8_push_ops[cpu_type]; |
---|
107 | h8_pop_op = h8_pop_ops[cpu_type]; |
---|
108 | h8_mov_op = h8_mov_ops[cpu_type]; |
---|
109 | } |
---|
110 | |
---|
111 | char * |
---|
112 | byte_reg (x, b) |
---|
113 | rtx x; |
---|
114 | int b; |
---|
115 | { |
---|
116 | static char *names_small[] = |
---|
117 | {"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h", |
---|
118 | "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"}; |
---|
119 | |
---|
120 | return names_small[REGNO (x) * 2 + b]; |
---|
121 | } |
---|
122 | |
---|
123 | /* REGNO must be saved/restored across calls if this macro is true. */ |
---|
124 | |
---|
125 | #define WORD_REG_USED(regno) \ |
---|
126 | (regno < 7 && \ |
---|
127 | (interrupt_handler \ |
---|
128 | || pragma_saveall \ |
---|
129 | || (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \ |
---|
130 | || (regs_ever_live[regno] & !call_used_regs[regno]))) |
---|
131 | |
---|
132 | /* Output assembly language to FILE for the operation OP with operand size |
---|
133 | SIZE to adjust the stack pointer. */ |
---|
134 | |
---|
135 | static void |
---|
136 | dosize (file, op, size) |
---|
137 | FILE *file; |
---|
138 | char *op; |
---|
139 | unsigned int size; |
---|
140 | { |
---|
141 | /* On the h8300h and h8300s, for sizes <= 8 bytes it is as good or |
---|
142 | better to use adds/subs insns rather than add.l/sub.l |
---|
143 | with an immediate value. */ |
---|
144 | if (size > 4 && size <= 8 && (TARGET_H8300H || TARGET_H8300S)) |
---|
145 | { |
---|
146 | /* Crank the size down to <= 4 */ |
---|
147 | fprintf (file, "\t%ss\t#%d,sp\n", op, 4); |
---|
148 | size -= 4; |
---|
149 | } |
---|
150 | |
---|
151 | switch (size) |
---|
152 | { |
---|
153 | case 4: |
---|
154 | if (TARGET_H8300H || TARGET_H8300S) |
---|
155 | { |
---|
156 | fprintf (file, "\t%ss\t#%d,sp\n", op, 4); |
---|
157 | size = 0; |
---|
158 | break; |
---|
159 | } |
---|
160 | case 3: |
---|
161 | fprintf (file, "\t%ss\t#%d,sp\n", op, 2); |
---|
162 | size -= 2; |
---|
163 | /* Fall through... */ |
---|
164 | case 2: |
---|
165 | case 1: |
---|
166 | fprintf (file, "\t%ss\t#%d,sp\n", op, size); |
---|
167 | size = 0; |
---|
168 | break; |
---|
169 | case 0: |
---|
170 | break; |
---|
171 | default: |
---|
172 | if (TARGET_H8300) |
---|
173 | { |
---|
174 | if (current_function_needs_context |
---|
175 | && strcmp (op, "sub") == 0) |
---|
176 | { |
---|
177 | /* Egad. We don't have a temporary to hold the |
---|
178 | size of the frame in the prologue! Just inline |
---|
179 | the bastard since this shouldn't happen often. */ |
---|
180 | while (size >= 2) |
---|
181 | { |
---|
182 | fprintf (file, "\tsubs\t#2,sp\n"); |
---|
183 | size -= 2; |
---|
184 | } |
---|
185 | |
---|
186 | if (size) |
---|
187 | fprintf (file, "\tsubs\t#1,sp\n"); |
---|
188 | |
---|
189 | size = 0; |
---|
190 | } |
---|
191 | else |
---|
192 | fprintf (file, "\tmov.w\t#%d,r3\n\t%s.w\tr3,sp\n", size, op); |
---|
193 | } |
---|
194 | else |
---|
195 | fprintf (file, "\t%s\t#%d,sp\n", op, size); |
---|
196 | size = 0; |
---|
197 | break; |
---|
198 | } |
---|
199 | } |
---|
200 | |
---|
201 | /* Output assembly language code for the function prologue. */ |
---|
202 | static int push_order[FIRST_PSEUDO_REGISTER] = |
---|
203 | {0, 1, 2, 3, 4, 5, 6, -1, -1, -1}; |
---|
204 | static int pop_order[FIRST_PSEUDO_REGISTER] = |
---|
205 | {6, 5, 4, 3, 2, 1, 0, -1, -1, -1}; |
---|
206 | |
---|
207 | /* This is what the stack looks like after the prolog of |
---|
208 | a function with a frame has been set up: |
---|
209 | |
---|
210 | <args> |
---|
211 | PC |
---|
212 | FP <- fp |
---|
213 | <locals> |
---|
214 | <saved registers> <- sp |
---|
215 | |
---|
216 | This is what the stack looks like after the prolog of |
---|
217 | a function which doesn't have a frame: |
---|
218 | |
---|
219 | <args> |
---|
220 | PC |
---|
221 | <locals> |
---|
222 | <saved registers> <- sp |
---|
223 | */ |
---|
224 | |
---|
225 | void |
---|
226 | function_prologue (file, size) |
---|
227 | FILE *file; |
---|
228 | int size; |
---|
229 | { |
---|
230 | register int mask = 0; |
---|
231 | int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8; |
---|
232 | int idx; |
---|
233 | |
---|
234 | /* Note a function with the interrupt attribute and set interrupt_handler |
---|
235 | accordingly. */ |
---|
236 | if (h8300_interrupt_function_p (current_function_decl)) |
---|
237 | interrupt_handler = 1; |
---|
238 | |
---|
239 | /* If the current function has the OS_Task attribute set, then |
---|
240 | we have a naked prologue. */ |
---|
241 | if (h8300_os_task_function_p (current_function_decl)) |
---|
242 | { |
---|
243 | fprintf (file, ";OS_Task prologue\n"); |
---|
244 | os_task = 1; |
---|
245 | return; |
---|
246 | } |
---|
247 | |
---|
248 | if (h8300_monitor_function_p (current_function_decl)) |
---|
249 | { |
---|
250 | /* My understanding of monitor functions is they act just |
---|
251 | like interrupt functions, except the prologue must |
---|
252 | mask interrupts. */ |
---|
253 | fprintf (file, ";monitor prologue\n"); |
---|
254 | interrupt_handler = 1; |
---|
255 | monitor = 1; |
---|
256 | if (TARGET_H8300) |
---|
257 | { |
---|
258 | fprintf (file, "\tsubs\t#2,sp\n"); |
---|
259 | fprintf (file, "\tpush\tr0\n"); |
---|
260 | fprintf (file, "\tstc\tccr,r0l\n"); |
---|
261 | fprintf (file, "\torc\t#128,ccr\n"); |
---|
262 | fprintf (file, "\tmov.b\tr0l,@(4,sp)\n"); |
---|
263 | } |
---|
264 | else |
---|
265 | { |
---|
266 | fprintf (file, "\tpush\ter0\n"); |
---|
267 | fprintf (file, "\tstc\tccr,r0l\n"); |
---|
268 | fprintf (file, "\torc\t#128,ccr\n"); |
---|
269 | fprintf (file, "\tmov.b\tr0l,@(4,sp)\n"); |
---|
270 | } |
---|
271 | } |
---|
272 | |
---|
273 | if (frame_pointer_needed) |
---|
274 | { |
---|
275 | /* Push fp */ |
---|
276 | fprintf (file, "\t%s\t%s\n", h8_push_op, |
---|
277 | h8_reg_names[FRAME_POINTER_REGNUM]); |
---|
278 | fprintf (file, "\t%s\t%s,%s\n", h8_mov_op, |
---|
279 | h8_reg_names[STACK_POINTER_REGNUM], |
---|
280 | h8_reg_names[FRAME_POINTER_REGNUM]); |
---|
281 | } |
---|
282 | |
---|
283 | /* leave room for locals */ |
---|
284 | dosize (file, "sub", fsize); |
---|
285 | |
---|
286 | /* Push the rest of the registers */ |
---|
287 | for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++) |
---|
288 | { |
---|
289 | int regno = push_order[idx]; |
---|
290 | |
---|
291 | if (regno >= 0 |
---|
292 | && WORD_REG_USED (regno) |
---|
293 | && (!frame_pointer_needed || regno != FRAME_POINTER_REGNUM)) |
---|
294 | { |
---|
295 | if (TARGET_H8300S) |
---|
296 | { |
---|
297 | /* Try to push multiple registers. */ |
---|
298 | if (regno == 0 || regno == 4) |
---|
299 | { |
---|
300 | int second_regno = push_order[idx + 1]; |
---|
301 | int third_regno = push_order[idx + 2]; |
---|
302 | int fourth_regno = push_order[idx + 3]; |
---|
303 | |
---|
304 | if (fourth_regno >= 0 |
---|
305 | && WORD_REG_USED (fourth_regno) |
---|
306 | && (!frame_pointer_needed |
---|
307 | || fourth_regno != FRAME_POINTER_REGNUM) |
---|
308 | && third_regno >= 0 |
---|
309 | && WORD_REG_USED (third_regno) |
---|
310 | && (!frame_pointer_needed |
---|
311 | || third_regno != FRAME_POINTER_REGNUM) |
---|
312 | && second_regno >= 0 |
---|
313 | && WORD_REG_USED (second_regno) |
---|
314 | && (!frame_pointer_needed |
---|
315 | || second_regno != FRAME_POINTER_REGNUM)) |
---|
316 | { |
---|
317 | fprintf (file, "\tstm.l %s-%s,@-sp\n", |
---|
318 | h8_reg_names[regno], |
---|
319 | h8_reg_names[fourth_regno]); |
---|
320 | idx += 3; |
---|
321 | continue; |
---|
322 | } |
---|
323 | } |
---|
324 | if (regno == 0 || regno == 4) |
---|
325 | { |
---|
326 | int second_regno = push_order[idx + 1]; |
---|
327 | int third_regno = push_order[idx + 2]; |
---|
328 | |
---|
329 | if (third_regno >= 0 |
---|
330 | && WORD_REG_USED (third_regno) |
---|
331 | && (!frame_pointer_needed |
---|
332 | || third_regno != FRAME_POINTER_REGNUM) |
---|
333 | && second_regno >= 0 |
---|
334 | && WORD_REG_USED (second_regno) |
---|
335 | && (!frame_pointer_needed |
---|
336 | || second_regno != FRAME_POINTER_REGNUM)) |
---|
337 | { |
---|
338 | fprintf (file, "\tstm.l %s-%s,@-sp\n", |
---|
339 | h8_reg_names[regno], |
---|
340 | h8_reg_names[third_regno]); |
---|
341 | idx += 2; |
---|
342 | continue; |
---|
343 | } |
---|
344 | } |
---|
345 | if (regno == 0 || regno == 2 || regno == 4 || regno == 6) |
---|
346 | { |
---|
347 | int second_regno = push_order[idx + 1]; |
---|
348 | |
---|
349 | if (second_regno >= 0 |
---|
350 | && WORD_REG_USED (second_regno) |
---|
351 | && (!frame_pointer_needed |
---|
352 | || second_regno != FRAME_POINTER_REGNUM)) |
---|
353 | { |
---|
354 | fprintf (file, "\tstm.l %s-%s,@-sp\n", |
---|
355 | h8_reg_names[regno], |
---|
356 | h8_reg_names[second_regno]); |
---|
357 | idx += 1; |
---|
358 | continue; |
---|
359 | } |
---|
360 | } |
---|
361 | } |
---|
362 | fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]); |
---|
363 | } |
---|
364 | } |
---|
365 | } |
---|
366 | |
---|
367 | /* Output assembly language code for the function epilogue. */ |
---|
368 | |
---|
369 | void |
---|
370 | function_epilogue (file, size) |
---|
371 | FILE *file; |
---|
372 | int size; |
---|
373 | { |
---|
374 | register int regno; |
---|
375 | register int mask = 0; |
---|
376 | int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8; |
---|
377 | int idx; |
---|
378 | rtx insn = get_last_insn (); |
---|
379 | |
---|
380 | if (os_task) |
---|
381 | { |
---|
382 | /* OS_Task epilogues are nearly naked -- they just have an |
---|
383 | rts instruction. */ |
---|
384 | fprintf (file, ";OS_task epilogue\n"); |
---|
385 | fprintf (file, "\trts\n"); |
---|
386 | goto out; |
---|
387 | } |
---|
388 | |
---|
389 | /* monitor epilogues are the same as interrupt function epilogues. |
---|
390 | Just make a note that we're in an monitor epilogue. */ |
---|
391 | if (monitor) |
---|
392 | fprintf(file, ";monitor epilogue\n"); |
---|
393 | |
---|
394 | /* If the last insn was a BARRIER, we don't have to write any code. */ |
---|
395 | if (GET_CODE (insn) == NOTE) |
---|
396 | insn = prev_nonnote_insn (insn); |
---|
397 | if (insn && GET_CODE (insn) == BARRIER) |
---|
398 | return; |
---|
399 | |
---|
400 | /* Pop the saved registers. */ |
---|
401 | for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++) |
---|
402 | { |
---|
403 | int regno = pop_order[idx]; |
---|
404 | |
---|
405 | if (regno >= 0 |
---|
406 | && WORD_REG_USED (regno) |
---|
407 | && (!frame_pointer_needed || regno != FRAME_POINTER_REGNUM)) |
---|
408 | { |
---|
409 | if (TARGET_H8300S) |
---|
410 | { |
---|
411 | /* Try to pop multiple registers. */ |
---|
412 | if (regno == 7 || regno == 3) |
---|
413 | { |
---|
414 | int second_regno = pop_order[idx + 1]; |
---|
415 | int third_regno = pop_order[idx + 2]; |
---|
416 | int fourth_regno = pop_order[idx + 3]; |
---|
417 | |
---|
418 | if (fourth_regno >= 0 |
---|
419 | && WORD_REG_USED (fourth_regno) |
---|
420 | && (!frame_pointer_needed |
---|
421 | || fourth_regno != FRAME_POINTER_REGNUM) |
---|
422 | && third_regno >= 0 |
---|
423 | && WORD_REG_USED (third_regno) |
---|
424 | && (!frame_pointer_needed |
---|
425 | || third_regno != FRAME_POINTER_REGNUM) |
---|
426 | && second_regno >= 0 |
---|
427 | && WORD_REG_USED (second_regno) |
---|
428 | && (!frame_pointer_needed |
---|
429 | || second_regno != FRAME_POINTER_REGNUM)) |
---|
430 | { |
---|
431 | fprintf (file, "\tldm.l @sp+,%s-%s\n", |
---|
432 | h8_reg_names[fourth_regno], |
---|
433 | h8_reg_names[regno]); |
---|
434 | idx += 3; |
---|
435 | continue; |
---|
436 | } |
---|
437 | } |
---|
438 | if (regno == 6 || regno == 2) |
---|
439 | { |
---|
440 | int second_regno = pop_order[idx + 1]; |
---|
441 | int third_regno = pop_order[idx + 2]; |
---|
442 | |
---|
443 | if (third_regno >= 0 |
---|
444 | && WORD_REG_USED (third_regno) |
---|
445 | && (!frame_pointer_needed |
---|
446 | || third_regno != FRAME_POINTER_REGNUM) |
---|
447 | && second_regno >= 0 |
---|
448 | && WORD_REG_USED (second_regno) |
---|
449 | && (!frame_pointer_needed |
---|
450 | || second_regno != FRAME_POINTER_REGNUM)) |
---|
451 | { |
---|
452 | fprintf (file, "\tldm.l @sp+,%s-%s\n", |
---|
453 | h8_reg_names[third_regno], |
---|
454 | h8_reg_names[regno]); |
---|
455 | idx += 2; |
---|
456 | continue; |
---|
457 | } |
---|
458 | } |
---|
459 | if (regno == 7 || regno == 5 || regno == 3 || regno == 1) |
---|
460 | { |
---|
461 | int second_regno = pop_order[idx + 1]; |
---|
462 | |
---|
463 | if (second_regno >= 0 |
---|
464 | && WORD_REG_USED (second_regno) |
---|
465 | && (!frame_pointer_needed |
---|
466 | || second_regno != FRAME_POINTER_REGNUM)) |
---|
467 | { |
---|
468 | fprintf (file, "\tldm.l @sp+,%s-%s\n", |
---|
469 | h8_reg_names[second_regno], |
---|
470 | h8_reg_names[regno]); |
---|
471 | idx += 1; |
---|
472 | continue; |
---|
473 | } |
---|
474 | } |
---|
475 | } |
---|
476 | fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]); |
---|
477 | } |
---|
478 | } |
---|
479 | |
---|
480 | /* deallocate locals */ |
---|
481 | dosize (file, "add", fsize); |
---|
482 | |
---|
483 | /* pop frame pointer if we had one. */ |
---|
484 | if (frame_pointer_needed) |
---|
485 | fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[FRAME_POINTER_REGNUM]); |
---|
486 | |
---|
487 | /* If this is a monitor function, there is one register still left on |
---|
488 | the stack. */ |
---|
489 | if (monitor) |
---|
490 | fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[0]); |
---|
491 | |
---|
492 | if (interrupt_handler) |
---|
493 | fprintf (file, "\trte\n"); |
---|
494 | else |
---|
495 | fprintf (file, "\trts\n"); |
---|
496 | |
---|
497 | out: |
---|
498 | interrupt_handler = 0; |
---|
499 | os_task = 0; |
---|
500 | monitor = 0; |
---|
501 | pragma_saveall = 0; |
---|
502 | } |
---|
503 | |
---|
504 | /* Output assembly code for the start of the file. */ |
---|
505 | |
---|
506 | asm_file_start (file) |
---|
507 | FILE *file; |
---|
508 | { |
---|
509 | fprintf (file, ";\tGCC For the Hitachi H8/300\n"); |
---|
510 | fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n"); |
---|
511 | fprintf (file, ";\trelease F-1\n"); |
---|
512 | if (optimize) |
---|
513 | fprintf (file, "; -O%d\n", optimize); |
---|
514 | if (TARGET_H8300H) |
---|
515 | fprintf (file, "\n\t.h8300h\n"); |
---|
516 | else if (TARGET_H8300S) |
---|
517 | fprintf (file, "\n\t.h8300s\n"); |
---|
518 | else |
---|
519 | fprintf (file, "\n\n"); |
---|
520 | output_file_directive (file, main_input_filename); |
---|
521 | } |
---|
522 | |
---|
523 | /* Output assembly language code for the end of file. */ |
---|
524 | |
---|
525 | void |
---|
526 | asm_file_end (file) |
---|
527 | FILE *file; |
---|
528 | { |
---|
529 | fprintf (file, "\t.end\n"); |
---|
530 | } |
---|
531 | |
---|
532 | /* Return true if VALUE is a valid constant for constraint 'P'. |
---|
533 | IE: VALUE is a power of two <= 2**15. */ |
---|
534 | |
---|
535 | int |
---|
536 | small_power_of_two (value) |
---|
537 | int value; |
---|
538 | { |
---|
539 | switch (value) |
---|
540 | { |
---|
541 | case 1: |
---|
542 | case 2: |
---|
543 | case 4: |
---|
544 | case 8: |
---|
545 | case 16: |
---|
546 | case 32: |
---|
547 | case 64: |
---|
548 | case 128: |
---|
549 | case 256: |
---|
550 | case 512: |
---|
551 | case 1024: |
---|
552 | case 2048: |
---|
553 | case 4096: |
---|
554 | case 8192: |
---|
555 | case 16384: |
---|
556 | case 32768: |
---|
557 | return 1; |
---|
558 | } |
---|
559 | return 0; |
---|
560 | } |
---|
561 | |
---|
562 | /* Return true if VALUE is a valid constant for constraint 'O', which |
---|
563 | means that the constant would be ok to use as a bit for a bclr |
---|
564 | instruction. */ |
---|
565 | |
---|
566 | int |
---|
567 | ok_for_bclr (value) |
---|
568 | int value; |
---|
569 | { |
---|
570 | return small_power_of_two ((~value) & 0xff); |
---|
571 | } |
---|
572 | |
---|
573 | /* Return true is OP is a valid source operand for an integer move |
---|
574 | instruction. */ |
---|
575 | |
---|
576 | int |
---|
577 | general_operand_src (op, mode) |
---|
578 | rtx op; |
---|
579 | enum machine_mode mode; |
---|
580 | { |
---|
581 | if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC) |
---|
582 | return 1; |
---|
583 | return general_operand (op, mode); |
---|
584 | } |
---|
585 | |
---|
586 | /* Return true if OP is a valid destination operand for an integer move |
---|
587 | instruction. */ |
---|
588 | |
---|
589 | int |
---|
590 | general_operand_dst (op, mode) |
---|
591 | rtx op; |
---|
592 | enum machine_mode mode; |
---|
593 | { |
---|
594 | if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == PRE_DEC) |
---|
595 | return 1; |
---|
596 | return general_operand (op, mode); |
---|
597 | } |
---|
598 | |
---|
599 | /* Return true if OP is a const valid for a bit clear instruction. */ |
---|
600 | |
---|
601 | int |
---|
602 | o_operand (operand, mode) |
---|
603 | rtx operand; |
---|
604 | enum machine_mode mode; |
---|
605 | { |
---|
606 | return (GET_CODE (operand) == CONST_INT |
---|
607 | && CONST_OK_FOR_O (INTVAL (operand))); |
---|
608 | } |
---|
609 | |
---|
610 | /* Return true if OP is a const valid for a bit set or bit xor instruction. */ |
---|
611 | |
---|
612 | int |
---|
613 | p_operand (operand, mode) |
---|
614 | rtx operand; |
---|
615 | enum machine_mode mode; |
---|
616 | { |
---|
617 | return (GET_CODE (operand) == CONST_INT |
---|
618 | && CONST_OK_FOR_P (INTVAL (operand))); |
---|
619 | } |
---|
620 | |
---|
621 | /* Return true if OP is a valid call operand. */ |
---|
622 | |
---|
623 | int |
---|
624 | call_insn_operand (op, mode) |
---|
625 | rtx op; |
---|
626 | enum machine_mode mode; |
---|
627 | { |
---|
628 | if (GET_CODE (op) == MEM) |
---|
629 | { |
---|
630 | rtx inside = XEXP (op, 0); |
---|
631 | if (register_operand (inside, Pmode)) |
---|
632 | return 1; |
---|
633 | if (CONSTANT_ADDRESS_P (inside)) |
---|
634 | return 1; |
---|
635 | } |
---|
636 | return 0; |
---|
637 | } |
---|
638 | |
---|
639 | int |
---|
640 | adds_subs_operand (op, mode) |
---|
641 | rtx op; |
---|
642 | enum machine_mode mode; |
---|
643 | { |
---|
644 | if (GET_CODE (op) == CONST_INT) |
---|
645 | { |
---|
646 | if (INTVAL (op) <= 4 && INTVAL (op) >= 0) |
---|
647 | return 1; |
---|
648 | if (INTVAL (op) >= -4 && INTVAL (op) <= 0) |
---|
649 | return 1; |
---|
650 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
651 | && INTVAL (op) != 7 |
---|
652 | && (INTVAL (op) <= 8 && INTVAL (op) >= 0)) |
---|
653 | return 1; |
---|
654 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
655 | && INTVAL (op) != -7 |
---|
656 | && (INTVAL (op) >= -8 && INTVAL (op) <= 0)) |
---|
657 | return 1; |
---|
658 | } |
---|
659 | return 0; |
---|
660 | } |
---|
661 | |
---|
662 | /* Return nonzero if op is an adds/subs operand which only requires |
---|
663 | one insn to implement. It is assumed that OP is already an adds/subs |
---|
664 | operand. */ |
---|
665 | int |
---|
666 | one_insn_adds_subs_operand (op, mode) |
---|
667 | rtx op; |
---|
668 | enum machine_mode mode; |
---|
669 | { |
---|
670 | int val = INTVAL (op); |
---|
671 | |
---|
672 | if (val == 1 || val == -1 |
---|
673 | || val == 2 || val == -2 |
---|
674 | || ((TARGET_H8300H || TARGET_H8300S) |
---|
675 | && (val == 4 || val == -4))) |
---|
676 | return 1; |
---|
677 | return 0; |
---|
678 | } |
---|
679 | |
---|
680 | char * |
---|
681 | output_adds_subs (operands) |
---|
682 | rtx *operands; |
---|
683 | { |
---|
684 | int val = INTVAL (operands[2]); |
---|
685 | |
---|
686 | /* First get the value into the range -4..4 inclusive. |
---|
687 | |
---|
688 | The only way it can be out of this range is when TARGET_H8300H |
---|
689 | or TARGET_H8300S is true, thus it is safe to use adds #4 and subs #4. */ |
---|
690 | if (val > 4) |
---|
691 | { |
---|
692 | output_asm_insn ("adds #4,%A0", operands); |
---|
693 | val -= 4; |
---|
694 | } |
---|
695 | |
---|
696 | if (val < -4) |
---|
697 | { |
---|
698 | output_asm_insn ("subs #4,%A0", operands); |
---|
699 | val += 4; |
---|
700 | } |
---|
701 | |
---|
702 | /* Handle case were val == 4 or val == -4 and we're compiling |
---|
703 | for TARGET_H8300H or TARGET_H8300S. */ |
---|
704 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
705 | && val == 4) |
---|
706 | return "adds #4,%A0"; |
---|
707 | |
---|
708 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
709 | && val == -4) |
---|
710 | return "subs #4,%A0"; |
---|
711 | |
---|
712 | if (val > 2) |
---|
713 | { |
---|
714 | output_asm_insn ("adds #2,%A0", operands); |
---|
715 | val -= 2; |
---|
716 | } |
---|
717 | |
---|
718 | if (val < -2) |
---|
719 | { |
---|
720 | output_asm_insn ("subs #2,%A0", operands); |
---|
721 | val += 2; |
---|
722 | } |
---|
723 | |
---|
724 | /* val should be one or two now. */ |
---|
725 | if (val == 2) |
---|
726 | return "adds #2,%A0"; |
---|
727 | |
---|
728 | if (val == -2) |
---|
729 | return "subs #2,%A0"; |
---|
730 | |
---|
731 | /* val should be one now. */ |
---|
732 | if (val == 1) |
---|
733 | return "adds #1,%A0"; |
---|
734 | |
---|
735 | if (val == -1) |
---|
736 | return "subs #1,%A0"; |
---|
737 | |
---|
738 | /* If not optimizing, we might be asked to add 0. */ |
---|
739 | if (val == 0) |
---|
740 | return ""; |
---|
741 | |
---|
742 | /* In theory, this can't happen. */ |
---|
743 | abort (); |
---|
744 | } |
---|
745 | |
---|
746 | /* Return true if OP is a valid call operand, and OP represents |
---|
747 | an operand for a small call (4 bytes instead of 6 bytes). */ |
---|
748 | |
---|
749 | int |
---|
750 | small_call_insn_operand (op, mode) |
---|
751 | rtx op; |
---|
752 | enum machine_mode mode; |
---|
753 | { |
---|
754 | if (GET_CODE (op) == MEM) |
---|
755 | { |
---|
756 | rtx inside = XEXP (op, 0); |
---|
757 | |
---|
758 | /* Register indirect is a small call. */ |
---|
759 | if (register_operand (inside, Pmode)) |
---|
760 | return 1; |
---|
761 | |
---|
762 | /* A call through the function vector is a small |
---|
763 | call too. */ |
---|
764 | if (GET_CODE (inside) == SYMBOL_REF |
---|
765 | && SYMBOL_REF_FLAG (inside)) |
---|
766 | return 1; |
---|
767 | } |
---|
768 | /* Otherwise it's a large call. */ |
---|
769 | return 0; |
---|
770 | } |
---|
771 | |
---|
772 | /* Return true if OP is a valid jump operand. */ |
---|
773 | |
---|
774 | int |
---|
775 | jump_address_operand (op, mode) |
---|
776 | rtx op; |
---|
777 | enum machine_mode mode; |
---|
778 | { |
---|
779 | if (GET_CODE (op) == REG) |
---|
780 | return mode == Pmode; |
---|
781 | |
---|
782 | if (GET_CODE (op) == MEM) |
---|
783 | { |
---|
784 | rtx inside = XEXP (op, 0); |
---|
785 | if (register_operand (inside, Pmode)) |
---|
786 | return 1; |
---|
787 | if (CONSTANT_ADDRESS_P (inside)) |
---|
788 | return 1; |
---|
789 | } |
---|
790 | return 0; |
---|
791 | } |
---|
792 | |
---|
793 | /* Recognize valid operands for bitfield instructions. */ |
---|
794 | |
---|
795 | extern int rtx_equal_function_value_matters; |
---|
796 | |
---|
797 | int |
---|
798 | bit_operand (op, mode) |
---|
799 | rtx op; |
---|
800 | enum machine_mode mode; |
---|
801 | { |
---|
802 | /* We can except any general operand, expept that MEM operands must |
---|
803 | be limited to those that use addresses valid for the 'U' constraint. */ |
---|
804 | if (!general_operand (op, mode)) |
---|
805 | return 0; |
---|
806 | |
---|
807 | /* Accept any mem during RTL generation. Otherwise, the code that does |
---|
808 | insv and extzv will think that we can not handle memory. However, |
---|
809 | to avoid reload problems, we only accept 'U' MEM operands after RTL |
---|
810 | generation. This means that any named pattern which uses this predicate |
---|
811 | must force its operands to match 'U' before emitting RTL. */ |
---|
812 | |
---|
813 | if (GET_CODE (op) == REG) |
---|
814 | return 1; |
---|
815 | if (GET_CODE (op) == SUBREG) |
---|
816 | return 1; |
---|
817 | if (!rtx_equal_function_value_matters) |
---|
818 | { |
---|
819 | /* We're building rtl */ |
---|
820 | return GET_CODE (op) == MEM; |
---|
821 | } |
---|
822 | else |
---|
823 | { |
---|
824 | return (GET_CODE (op) == MEM |
---|
825 | && EXTRA_CONSTRAINT (op, 'U')); |
---|
826 | } |
---|
827 | } |
---|
828 | |
---|
829 | int |
---|
830 | bit_memory_operand (op, mode) |
---|
831 | rtx op; |
---|
832 | enum machine_mode mode; |
---|
833 | { |
---|
834 | return (GET_CODE (op) == MEM |
---|
835 | && EXTRA_CONSTRAINT (op, 'U')); |
---|
836 | } |
---|
837 | |
---|
838 | /* Recognize valid operators for bit test. */ |
---|
839 | |
---|
840 | int |
---|
841 | eq_operator (x, mode) |
---|
842 | rtx x; |
---|
843 | enum machine_mode mode; |
---|
844 | { |
---|
845 | return (GET_CODE (x) == EQ || GET_CODE (x) == NE); |
---|
846 | } |
---|
847 | |
---|
848 | /* Handle machine specific pragmas for compatibility with existing |
---|
849 | compilers for the H8/300. |
---|
850 | |
---|
851 | pragma saveall generates prolog/epilog code which saves and |
---|
852 | restores all the registers on function entry. |
---|
853 | |
---|
854 | pragma interrupt saves and restores all registers, and exits with |
---|
855 | an rte instruction rather than an rts. A pointer to a function |
---|
856 | with this attribute may be safely used in an interrupt vector. */ |
---|
857 | |
---|
858 | int |
---|
859 | handle_pragma (file, t) |
---|
860 | FILE *file; |
---|
861 | tree t; |
---|
862 | { |
---|
863 | int retval = 0; |
---|
864 | register char *pname; |
---|
865 | |
---|
866 | if (TREE_CODE (t) != IDENTIFIER_NODE) |
---|
867 | return 0; |
---|
868 | |
---|
869 | pname = IDENTIFIER_POINTER (t); |
---|
870 | if (strcmp (pname, "interrupt") == 0) |
---|
871 | interrupt_handler = retval = 1; |
---|
872 | else if (strcmp (pname, "saveall") == 0) |
---|
873 | pragma_saveall = retval = 1; |
---|
874 | |
---|
875 | return retval; |
---|
876 | } |
---|
877 | |
---|
878 | /* If the next arg with MODE and TYPE is to be passed in a register, return |
---|
879 | the rtx to represent where it is passed. CUM represents the state after |
---|
880 | the last argument. NAMED is not used. */ |
---|
881 | |
---|
882 | static char *hand_list[] = |
---|
883 | { |
---|
884 | "__main", |
---|
885 | "__cmpsi2", |
---|
886 | "__divhi3", |
---|
887 | "__modhi3", |
---|
888 | "__udivhi3", |
---|
889 | "__umodhi3", |
---|
890 | "__divsi3", |
---|
891 | "__modsi3", |
---|
892 | "__udivsi3", |
---|
893 | "__umodsi3", |
---|
894 | "__mulhi3", |
---|
895 | "__mulsi3", |
---|
896 | "__reg_memcpy", |
---|
897 | "__reg_memset", |
---|
898 | "__ucmpsi2", |
---|
899 | 0, |
---|
900 | }; |
---|
901 | |
---|
902 | /* Return an RTX to represent where a value with mode MODE will be returned |
---|
903 | from a function. If the result is 0, the argument is pushed. */ |
---|
904 | |
---|
905 | rtx |
---|
906 | function_arg (cum, mode, type, named) |
---|
907 | CUMULATIVE_ARGS *cum; |
---|
908 | enum machine_mode mode; |
---|
909 | tree type; |
---|
910 | int named; |
---|
911 | { |
---|
912 | rtx result = 0; |
---|
913 | char *fname; |
---|
914 | int regpass = 0; |
---|
915 | |
---|
916 | /* Never pass unnamed arguments in registers. */ |
---|
917 | if (!named) |
---|
918 | return 0; |
---|
919 | |
---|
920 | /* Pass 3 regs worth of data in regs when user asked on the command line. */ |
---|
921 | if (TARGET_QUICKCALL) |
---|
922 | regpass = 3; |
---|
923 | |
---|
924 | /* If calling hand written assembler, use 4 regs of args. */ |
---|
925 | |
---|
926 | if (cum->libcall) |
---|
927 | { |
---|
928 | char **p; |
---|
929 | |
---|
930 | fname = XSTR (cum->libcall, 0); |
---|
931 | |
---|
932 | /* See if this libcall is one of the hand coded ones. */ |
---|
933 | |
---|
934 | for (p = hand_list; *p && strcmp (*p, fname) != 0; p++) |
---|
935 | ; |
---|
936 | |
---|
937 | if (*p) |
---|
938 | regpass = 4; |
---|
939 | } |
---|
940 | |
---|
941 | if (regpass) |
---|
942 | { |
---|
943 | int size; |
---|
944 | |
---|
945 | if (mode == BLKmode) |
---|
946 | size = int_size_in_bytes (type); |
---|
947 | else |
---|
948 | size = GET_MODE_SIZE (mode); |
---|
949 | |
---|
950 | if (size + cum->nbytes > regpass * UNITS_PER_WORD) |
---|
951 | { |
---|
952 | result = 0; |
---|
953 | } |
---|
954 | else |
---|
955 | { |
---|
956 | switch (cum->nbytes / UNITS_PER_WORD) |
---|
957 | { |
---|
958 | case 0: |
---|
959 | result = gen_rtx (REG, mode, 0); |
---|
960 | break; |
---|
961 | case 1: |
---|
962 | result = gen_rtx (REG, mode, 1); |
---|
963 | break; |
---|
964 | case 2: |
---|
965 | result = gen_rtx (REG, mode, 2); |
---|
966 | break; |
---|
967 | case 3: |
---|
968 | result = gen_rtx (REG, mode, 3); |
---|
969 | break; |
---|
970 | default: |
---|
971 | result = 0; |
---|
972 | } |
---|
973 | } |
---|
974 | } |
---|
975 | |
---|
976 | return result; |
---|
977 | } |
---|
978 | |
---|
979 | /* Return the cost of the rtx R with code CODE. */ |
---|
980 | |
---|
981 | int |
---|
982 | const_costs (r, c) |
---|
983 | rtx r; |
---|
984 | enum rtx_code c; |
---|
985 | { |
---|
986 | switch (c) |
---|
987 | { |
---|
988 | case CONST_INT: |
---|
989 | switch (INTVAL (r)) |
---|
990 | { |
---|
991 | case 0: |
---|
992 | case 1: |
---|
993 | case 2: |
---|
994 | case -1: |
---|
995 | case -2: |
---|
996 | return 0; |
---|
997 | case 4: |
---|
998 | case -4: |
---|
999 | if (TARGET_H8300H || TARGET_H8300S) |
---|
1000 | return 0; |
---|
1001 | else |
---|
1002 | return 1; |
---|
1003 | default: |
---|
1004 | return 1; |
---|
1005 | } |
---|
1006 | |
---|
1007 | case CONST: |
---|
1008 | case LABEL_REF: |
---|
1009 | case SYMBOL_REF: |
---|
1010 | return 3; |
---|
1011 | |
---|
1012 | case CONST_DOUBLE: |
---|
1013 | return 20; |
---|
1014 | |
---|
1015 | default: |
---|
1016 | return 4; |
---|
1017 | } |
---|
1018 | } |
---|
1019 | |
---|
1020 | /* Documentation for the machine specific operand escapes: |
---|
1021 | |
---|
1022 | 'A' print rn in h8/300 mode, erN in H8/300H mode |
---|
1023 | 'C' print (operand - 2). |
---|
1024 | 'E' like s but negative. |
---|
1025 | 'F' like t but negative. |
---|
1026 | 'G' constant just the negative |
---|
1027 | 'L' fake label, changed after used twice. |
---|
1028 | 'M' turn a 'M' constant into its negative mod 2. |
---|
1029 | 'P' if operand is incing/decing sp, print .w, otherwise .b. |
---|
1030 | 'R' print operand as a byte:8 address if appropriate, else fall back to |
---|
1031 | 'X' handling. |
---|
1032 | 'S' print operand as a long word |
---|
1033 | 'T' print operand as a word |
---|
1034 | 'U' if operand is incing/decing sp, print l, otherwise nothing. |
---|
1035 | 'V' find the set bit, and print its number. |
---|
1036 | 'W' find the clear bit, and print its number. |
---|
1037 | 'X' print operand as a byte |
---|
1038 | 'Y' print either l or h depending on whether last 'Z' operand < 8 or >= 8. |
---|
1039 | If this operand isn't a register, fall back to 'R' handling. |
---|
1040 | 'Z' print int & 7. |
---|
1041 | 'b' print the bit opcode |
---|
1042 | 'c' print the ibit opcode |
---|
1043 | 'd' bcc if EQ, bcs if NE |
---|
1044 | 'e' first word of 32 bit value - if reg, then least reg. if mem |
---|
1045 | then least. if const then most sig word |
---|
1046 | 'f' second word of 32 bit value - if reg, then biggest reg. if mem |
---|
1047 | then +2. if const then least sig word |
---|
1048 | 'g' bcs if EQ, bcc if NE |
---|
1049 | 'j' print operand as condition code. |
---|
1050 | 'k' print operand as reverse condition code. |
---|
1051 | 's' print as low byte of 16 bit value |
---|
1052 | 't' print as high byte of 16 bit value |
---|
1053 | 'w' print as low byte of 32 bit value |
---|
1054 | 'x' print as 2nd byte of 32 bit value |
---|
1055 | 'y' print as 3rd byte of 32 bit value |
---|
1056 | 'z' print as msb of 32 bit value |
---|
1057 | */ |
---|
1058 | |
---|
1059 | /* Return assembly language string which identifies a comparison type. */ |
---|
1060 | |
---|
1061 | static char * |
---|
1062 | cond_string (code) |
---|
1063 | enum rtx_code code; |
---|
1064 | { |
---|
1065 | switch (code) |
---|
1066 | { |
---|
1067 | case NE: |
---|
1068 | return "ne"; |
---|
1069 | case EQ: |
---|
1070 | return "eq"; |
---|
1071 | case GE: |
---|
1072 | return "ge"; |
---|
1073 | case GT: |
---|
1074 | return "gt"; |
---|
1075 | case LE: |
---|
1076 | return "le"; |
---|
1077 | case LT: |
---|
1078 | return "lt"; |
---|
1079 | case GEU: |
---|
1080 | return "hs"; |
---|
1081 | case GTU: |
---|
1082 | return "hi"; |
---|
1083 | case LEU: |
---|
1084 | return "ls"; |
---|
1085 | case LTU: |
---|
1086 | return "lo"; |
---|
1087 | default: |
---|
1088 | abort (); |
---|
1089 | } |
---|
1090 | } |
---|
1091 | |
---|
1092 | /* Print operand X using operand code CODE to assembly language output file |
---|
1093 | FILE. */ |
---|
1094 | |
---|
1095 | void |
---|
1096 | print_operand (file, x, code) |
---|
1097 | FILE *file; |
---|
1098 | rtx x; |
---|
1099 | int code; |
---|
1100 | { |
---|
1101 | /* This is used to general unique labels for the 'L' code. */ |
---|
1102 | static int lab = 1000; |
---|
1103 | |
---|
1104 | /* This is used for communication between the 'P' and 'U' codes. */ |
---|
1105 | static char *last_p; |
---|
1106 | |
---|
1107 | /* This is used for communication between codes V,W,Z and Y. */ |
---|
1108 | static int bitint; |
---|
1109 | |
---|
1110 | switch (code) |
---|
1111 | { |
---|
1112 | case 'A': |
---|
1113 | if (GET_CODE (x) == REG) |
---|
1114 | fprintf (file, "%s", h8_reg_names[REGNO (x)]); |
---|
1115 | else |
---|
1116 | goto def; |
---|
1117 | break; |
---|
1118 | case 'C': |
---|
1119 | fprintf (file, "#%d", INTVAL (x) - 2); |
---|
1120 | break; |
---|
1121 | case 'E': |
---|
1122 | switch (GET_CODE (x)) |
---|
1123 | { |
---|
1124 | case REG: |
---|
1125 | fprintf (file, "%sl", names_big[REGNO (x)]); |
---|
1126 | break; |
---|
1127 | case CONST_INT: |
---|
1128 | fprintf (file, "#%d", (-INTVAL (x)) & 0xff); |
---|
1129 | break; |
---|
1130 | default: |
---|
1131 | abort (); |
---|
1132 | } |
---|
1133 | break; |
---|
1134 | case 'F': |
---|
1135 | switch (GET_CODE (x)) |
---|
1136 | { |
---|
1137 | case REG: |
---|
1138 | fprintf (file, "%sh", names_big[REGNO (x)]); |
---|
1139 | break; |
---|
1140 | case CONST_INT: |
---|
1141 | fprintf (file, "#%d", ((-INTVAL (x)) & 0xff00) >> 8); |
---|
1142 | break; |
---|
1143 | default: |
---|
1144 | abort (); |
---|
1145 | } |
---|
1146 | break; |
---|
1147 | case 'G': |
---|
1148 | if (GET_CODE (x) != CONST_INT) |
---|
1149 | abort (); |
---|
1150 | fprintf (file, "#%d", 0xff & (-INTVAL (x))); |
---|
1151 | break; |
---|
1152 | case 'L': |
---|
1153 | /* 'L' must always be used twice in a single pattern. It generates |
---|
1154 | the same label twice, and then will generate a unique label the |
---|
1155 | next time it is used. */ |
---|
1156 | asm_fprintf (file, "tl%d", (lab++) / 2); |
---|
1157 | break; |
---|
1158 | case 'M': |
---|
1159 | /* For 3/-3 and 4/-4, the other 2 is handled separately. */ |
---|
1160 | switch (INTVAL (x)) |
---|
1161 | { |
---|
1162 | case 2: |
---|
1163 | case 4: |
---|
1164 | case -2: |
---|
1165 | case -4: |
---|
1166 | fprintf (file, "#2"); |
---|
1167 | break; |
---|
1168 | case 1: |
---|
1169 | case 3: |
---|
1170 | case -1: |
---|
1171 | case -3: |
---|
1172 | fprintf (file, "#1"); |
---|
1173 | break; |
---|
1174 | default: |
---|
1175 | abort (); |
---|
1176 | } |
---|
1177 | break; |
---|
1178 | case 'P': |
---|
1179 | if (REGNO (XEXP (XEXP (x, 0), 0)) == STACK_POINTER_REGNUM) |
---|
1180 | { |
---|
1181 | last_p = ""; |
---|
1182 | fprintf (file, ".w"); |
---|
1183 | } |
---|
1184 | else |
---|
1185 | { |
---|
1186 | last_p = "l"; |
---|
1187 | fprintf (file, ".b"); |
---|
1188 | } |
---|
1189 | break; |
---|
1190 | case 'S': |
---|
1191 | if (GET_CODE (x) == REG) |
---|
1192 | fprintf (file, "%s", names_extended[REGNO (x)]); |
---|
1193 | else |
---|
1194 | goto def; |
---|
1195 | break; |
---|
1196 | case 'T': |
---|
1197 | if (GET_CODE (x) == REG) |
---|
1198 | fprintf (file, "%s", names_big[REGNO (x)]); |
---|
1199 | else |
---|
1200 | goto def; |
---|
1201 | break; |
---|
1202 | case 'U': |
---|
1203 | fprintf (file, "%s%s", names_big[REGNO (x)], last_p); |
---|
1204 | break; |
---|
1205 | case 'V': |
---|
1206 | bitint = exact_log2 (INTVAL (x)); |
---|
1207 | if (bitint == -1) |
---|
1208 | abort (); |
---|
1209 | fprintf (file, "#%d", bitint & 7); |
---|
1210 | break; |
---|
1211 | case 'W': |
---|
1212 | bitint = exact_log2 ((~INTVAL (x)) & 0xff); |
---|
1213 | if (bitint == -1) |
---|
1214 | abort (); |
---|
1215 | fprintf (file, "#%d", bitint & 7); |
---|
1216 | break; |
---|
1217 | case 'R': |
---|
1218 | case 'X': |
---|
1219 | if (GET_CODE (x) == REG) |
---|
1220 | fprintf (file, "%s", byte_reg (x, 0)); |
---|
1221 | else |
---|
1222 | goto def; |
---|
1223 | break; |
---|
1224 | case 'Y': |
---|
1225 | if (bitint == -1) |
---|
1226 | abort (); |
---|
1227 | if (GET_CODE (x) == REG) |
---|
1228 | fprintf (file, "%s%c", names_big[REGNO (x)], bitint > 7 ? 'h' : 'l'); |
---|
1229 | else |
---|
1230 | print_operand (file, x, 'R'); |
---|
1231 | bitint = -1; |
---|
1232 | break; |
---|
1233 | case 'Z': |
---|
1234 | bitint = INTVAL (x); |
---|
1235 | fprintf (file, "#%d", bitint & 7); |
---|
1236 | break; |
---|
1237 | case 'b': |
---|
1238 | switch (GET_CODE (x)) |
---|
1239 | { |
---|
1240 | case IOR: |
---|
1241 | fprintf (file, "bor"); |
---|
1242 | break; |
---|
1243 | case XOR: |
---|
1244 | fprintf (file, "bxor"); |
---|
1245 | break; |
---|
1246 | case AND: |
---|
1247 | fprintf (file, "band"); |
---|
1248 | break; |
---|
1249 | } |
---|
1250 | break; |
---|
1251 | case 'c': |
---|
1252 | switch (GET_CODE (x)) |
---|
1253 | { |
---|
1254 | case IOR: |
---|
1255 | fprintf (file, "bior"); |
---|
1256 | break; |
---|
1257 | case XOR: |
---|
1258 | fprintf (file, "bixor"); |
---|
1259 | break; |
---|
1260 | case AND: |
---|
1261 | fprintf (file, "biand"); |
---|
1262 | break; |
---|
1263 | } |
---|
1264 | break; |
---|
1265 | case 'd': |
---|
1266 | switch (GET_CODE (x)) |
---|
1267 | { |
---|
1268 | case EQ: |
---|
1269 | fprintf (file, "bcc"); |
---|
1270 | break; |
---|
1271 | case NE: |
---|
1272 | fprintf (file, "bcs"); |
---|
1273 | break; |
---|
1274 | default: |
---|
1275 | abort (); |
---|
1276 | } |
---|
1277 | break; |
---|
1278 | case 'e': |
---|
1279 | switch (GET_CODE (x)) |
---|
1280 | { |
---|
1281 | case REG: |
---|
1282 | if (TARGET_H8300) |
---|
1283 | fprintf (file, "%s", names_big[REGNO (x)]); |
---|
1284 | else |
---|
1285 | fprintf (file, "%s", names_upper_extended[REGNO (x)]); |
---|
1286 | break; |
---|
1287 | case MEM: |
---|
1288 | x = adj_offsettable_operand (x, 0); |
---|
1289 | print_operand (file, x, 0); |
---|
1290 | break; |
---|
1291 | case CONST_INT: |
---|
1292 | fprintf (file, "#%d", ((INTVAL (x) >> 16) & 0xffff)); |
---|
1293 | break; |
---|
1294 | default: |
---|
1295 | abort (); |
---|
1296 | break; |
---|
1297 | } |
---|
1298 | break; |
---|
1299 | case 'f': |
---|
1300 | switch (GET_CODE (x)) |
---|
1301 | { |
---|
1302 | case REG: |
---|
1303 | if (TARGET_H8300) |
---|
1304 | fprintf (file, "%s", names_big[REGNO (x) + 1]); |
---|
1305 | else |
---|
1306 | fprintf (file, "%s", names_big[REGNO (x)]); |
---|
1307 | break; |
---|
1308 | case MEM: |
---|
1309 | x = adj_offsettable_operand (x, 2); |
---|
1310 | print_operand (file, x, 0); |
---|
1311 | break; |
---|
1312 | case CONST_INT: |
---|
1313 | fprintf (file, "#%d", INTVAL (x) & 0xffff); |
---|
1314 | break; |
---|
1315 | default: |
---|
1316 | abort (); |
---|
1317 | } |
---|
1318 | break; |
---|
1319 | case 'g': |
---|
1320 | switch (GET_CODE (x)) |
---|
1321 | { |
---|
1322 | case NE: |
---|
1323 | fprintf (file, "bcc"); |
---|
1324 | break; |
---|
1325 | case EQ: |
---|
1326 | fprintf (file, "bcs"); |
---|
1327 | break; |
---|
1328 | default: |
---|
1329 | abort (); |
---|
1330 | } |
---|
1331 | break; |
---|
1332 | case 'j': |
---|
1333 | asm_fprintf (file, cond_string (GET_CODE (x))); |
---|
1334 | break; |
---|
1335 | case 'k': |
---|
1336 | asm_fprintf (file, cond_string (reverse_condition (GET_CODE (x)))); |
---|
1337 | break; |
---|
1338 | case 's': |
---|
1339 | if (GET_CODE (x) == CONST_INT) |
---|
1340 | fprintf (file, "#%d", (INTVAL (x)) & 0xff); |
---|
1341 | else |
---|
1342 | fprintf (file, "%s", byte_reg (x, 0)); |
---|
1343 | break; |
---|
1344 | case 't': |
---|
1345 | if (GET_CODE (x) == CONST_INT) |
---|
1346 | fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff); |
---|
1347 | else |
---|
1348 | fprintf (file, "%s", byte_reg (x, 1)); |
---|
1349 | break; |
---|
1350 | case 'u': |
---|
1351 | if (GET_CODE (x) != CONST_INT) |
---|
1352 | abort (); |
---|
1353 | fprintf (file, "%d", INTVAL (x)); |
---|
1354 | break; |
---|
1355 | case 'w': |
---|
1356 | if (GET_CODE (x) == CONST_INT) |
---|
1357 | fprintf (file, "#%d", INTVAL (x) & 0xff); |
---|
1358 | else |
---|
1359 | fprintf (file, "%s", |
---|
1360 | byte_reg (x, TARGET_H8300 ? 2 : 0)); |
---|
1361 | break; |
---|
1362 | case 'x': |
---|
1363 | if (GET_CODE (x) == CONST_INT) |
---|
1364 | fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff); |
---|
1365 | else |
---|
1366 | fprintf (file, "%s", |
---|
1367 | byte_reg (x, TARGET_H8300 ? 3 : 1)); |
---|
1368 | break; |
---|
1369 | case 'y': |
---|
1370 | if (GET_CODE (x) == CONST_INT) |
---|
1371 | fprintf (file, "#%d", (INTVAL (x) >> 16) & 0xff); |
---|
1372 | else |
---|
1373 | fprintf (file, "%s", byte_reg (x, 0)); |
---|
1374 | break; |
---|
1375 | case 'z': |
---|
1376 | if (GET_CODE (x) == CONST_INT) |
---|
1377 | fprintf (file, "#%d", (INTVAL (x) >> 24) & 0xff); |
---|
1378 | else |
---|
1379 | fprintf (file, "%s", byte_reg (x, 1)); |
---|
1380 | break; |
---|
1381 | |
---|
1382 | default: |
---|
1383 | def: |
---|
1384 | switch (GET_CODE (x)) |
---|
1385 | { |
---|
1386 | case REG: |
---|
1387 | switch (GET_MODE (x)) |
---|
1388 | { |
---|
1389 | case QImode: |
---|
1390 | #if 0 /* Is it asm ("mov.b %0,r2l", ...) */ |
---|
1391 | fprintf (file, "%s", byte_reg (x, 0)); |
---|
1392 | #else /* ... or is it asm ("mov.b %0l,r2l", ...) */ |
---|
1393 | fprintf (file, "%s", names_big[REGNO (x)]); |
---|
1394 | #endif |
---|
1395 | break; |
---|
1396 | case HImode: |
---|
1397 | fprintf (file, "%s", names_big[REGNO (x)]); |
---|
1398 | break; |
---|
1399 | case SImode: |
---|
1400 | case SFmode: |
---|
1401 | fprintf (file, "%s", names_extended[REGNO (x)]); |
---|
1402 | break; |
---|
1403 | default: |
---|
1404 | abort (); |
---|
1405 | } |
---|
1406 | break; |
---|
1407 | |
---|
1408 | case MEM: |
---|
1409 | fprintf (file, "@"); |
---|
1410 | output_address (XEXP (x, 0)); |
---|
1411 | |
---|
1412 | /* If this is an 'R' operand (reference into the 8-bit area), |
---|
1413 | then specify a symbolic address as "foo:8". */ |
---|
1414 | if (code == 'R' |
---|
1415 | && GET_CODE (XEXP (x, 0)) == SYMBOL_REF |
---|
1416 | && SYMBOL_REF_FLAG (XEXP (x, 0))) |
---|
1417 | fprintf (file, ":8"); |
---|
1418 | if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF |
---|
1419 | && TINY_DATA_NAME_P (XSTR (XEXP (x, 0), 0))) |
---|
1420 | fprintf (file, ":16"); |
---|
1421 | break; |
---|
1422 | |
---|
1423 | case CONST_INT: |
---|
1424 | case SYMBOL_REF: |
---|
1425 | case CONST: |
---|
1426 | case LABEL_REF: |
---|
1427 | fprintf (file, "#"); |
---|
1428 | print_operand_address (file, x); |
---|
1429 | break; |
---|
1430 | } |
---|
1431 | } |
---|
1432 | } |
---|
1433 | |
---|
1434 | /* Output assembly language output for the address ADDR to FILE. */ |
---|
1435 | |
---|
1436 | void |
---|
1437 | print_operand_address (file, addr) |
---|
1438 | FILE *file; |
---|
1439 | rtx addr; |
---|
1440 | { |
---|
1441 | switch (GET_CODE (addr)) |
---|
1442 | { |
---|
1443 | case REG: |
---|
1444 | fprintf (file, "%s", h8_reg_names[REGNO (addr)]); |
---|
1445 | break; |
---|
1446 | |
---|
1447 | case PRE_DEC: |
---|
1448 | fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]); |
---|
1449 | break; |
---|
1450 | |
---|
1451 | case POST_INC: |
---|
1452 | fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]); |
---|
1453 | break; |
---|
1454 | |
---|
1455 | case PLUS: |
---|
1456 | fprintf (file, "("); |
---|
1457 | if (GET_CODE (XEXP (addr, 0)) == REG) |
---|
1458 | { |
---|
1459 | /* reg,foo */ |
---|
1460 | print_operand_address (file, XEXP (addr, 1)); |
---|
1461 | fprintf (file, ","); |
---|
1462 | print_operand_address (file, XEXP (addr, 0)); |
---|
1463 | } |
---|
1464 | else |
---|
1465 | { |
---|
1466 | /* foo+k */ |
---|
1467 | print_operand_address (file, XEXP (addr, 0)); |
---|
1468 | fprintf (file, "+"); |
---|
1469 | print_operand_address (file, XEXP (addr, 1)); |
---|
1470 | } |
---|
1471 | fprintf (file, ")"); |
---|
1472 | break; |
---|
1473 | |
---|
1474 | case CONST_INT: |
---|
1475 | { |
---|
1476 | /* Since the h8/300 only has 16 bit pointers, negative values are also |
---|
1477 | those >= 32768. This happens for example with pointer minus a |
---|
1478 | constant. We don't want to turn (char *p - 2) into |
---|
1479 | (char *p + 65534) because loop unrolling can build upon this |
---|
1480 | (IE: char *p + 131068). */ |
---|
1481 | int n = INTVAL (addr); |
---|
1482 | if (TARGET_H8300) |
---|
1483 | n = (int) (short) n; |
---|
1484 | if (n < 0) |
---|
1485 | /* ??? Why the special case for -ve values? */ |
---|
1486 | fprintf (file, "-%d", -n); |
---|
1487 | else |
---|
1488 | fprintf (file, "%d", n); |
---|
1489 | break; |
---|
1490 | } |
---|
1491 | |
---|
1492 | default: |
---|
1493 | output_addr_const (file, addr); |
---|
1494 | break; |
---|
1495 | } |
---|
1496 | } |
---|
1497 | |
---|
1498 | /* Output all insn addresses and their sizes into the assembly language |
---|
1499 | output file. This is helpful for debugging whether the length attributes |
---|
1500 | in the md file are correct. This is not meant to be a user selectable |
---|
1501 | option. */ |
---|
1502 | |
---|
1503 | void |
---|
1504 | final_prescan_insn (insn, operand, num_operands) |
---|
1505 | rtx insn, *operand; |
---|
1506 | int num_operands; |
---|
1507 | { |
---|
1508 | /* This holds the last insn address. */ |
---|
1509 | static int last_insn_address = 0; |
---|
1510 | |
---|
1511 | int uid = INSN_UID (insn); |
---|
1512 | |
---|
1513 | if (TARGET_RTL_DUMP) |
---|
1514 | { |
---|
1515 | fprintf (asm_out_file, "\n****************"); |
---|
1516 | print_rtl (asm_out_file, PATTERN (insn)); |
---|
1517 | fprintf (asm_out_file, "\n"); |
---|
1518 | } |
---|
1519 | |
---|
1520 | if (TARGET_ADDRESSES) |
---|
1521 | { |
---|
1522 | fprintf (asm_out_file, "; 0x%x %d\n", insn_addresses[uid], |
---|
1523 | insn_addresses[uid] - last_insn_address); |
---|
1524 | last_insn_address = insn_addresses[uid]; |
---|
1525 | } |
---|
1526 | } |
---|
1527 | |
---|
1528 | /* Prepare for an SI sized move. */ |
---|
1529 | |
---|
1530 | int |
---|
1531 | do_movsi (operands) |
---|
1532 | rtx operands[]; |
---|
1533 | { |
---|
1534 | rtx src = operands[1]; |
---|
1535 | rtx dst = operands[0]; |
---|
1536 | if (!reload_in_progress && !reload_completed) |
---|
1537 | { |
---|
1538 | if (!register_operand (dst, GET_MODE (dst))) |
---|
1539 | { |
---|
1540 | rtx tmp = gen_reg_rtx (GET_MODE (dst)); |
---|
1541 | emit_move_insn (tmp, src); |
---|
1542 | operands[1] = tmp; |
---|
1543 | } |
---|
1544 | } |
---|
1545 | return 0; |
---|
1546 | } |
---|
1547 | |
---|
1548 | /* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). |
---|
1549 | Define the offset between two registers, one to be eliminated, and the other |
---|
1550 | its replacement, at the start of a routine. */ |
---|
1551 | |
---|
1552 | int |
---|
1553 | initial_offset (from, to) |
---|
1554 | { |
---|
1555 | int offset = 0; |
---|
1556 | |
---|
1557 | if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) |
---|
1558 | offset = UNITS_PER_WORD + frame_pointer_needed * UNITS_PER_WORD; |
---|
1559 | else |
---|
1560 | { |
---|
1561 | int regno; |
---|
1562 | |
---|
1563 | for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) |
---|
1564 | if ((regs_ever_live[regno] |
---|
1565 | && (!call_used_regs[regno] || regno == FRAME_POINTER_REGNUM))) |
---|
1566 | offset += UNITS_PER_WORD; |
---|
1567 | |
---|
1568 | /* See the comments for get_frame_size. We need to round it up to |
---|
1569 | STACK_BOUNDARY. */ |
---|
1570 | |
---|
1571 | offset += ((get_frame_size () + STACK_BOUNDARY / BITS_PER_UNIT - 1) |
---|
1572 | & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1)); |
---|
1573 | |
---|
1574 | if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) |
---|
1575 | offset += UNITS_PER_WORD; /* Skip saved PC */ |
---|
1576 | } |
---|
1577 | return offset; |
---|
1578 | } |
---|
1579 | |
---|
1580 | /* Update the condition code from the insn. */ |
---|
1581 | |
---|
1582 | int |
---|
1583 | notice_update_cc (body, insn) |
---|
1584 | rtx body; |
---|
1585 | rtx insn; |
---|
1586 | { |
---|
1587 | switch (get_attr_cc (insn)) |
---|
1588 | { |
---|
1589 | case CC_NONE: |
---|
1590 | /* Insn does not affect CC at all. */ |
---|
1591 | break; |
---|
1592 | |
---|
1593 | case CC_NONE_0HIT: |
---|
1594 | /* Insn does not change CC, but the 0'th operand has been changed. */ |
---|
1595 | if (cc_status.value1 != 0 |
---|
1596 | && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1)) |
---|
1597 | cc_status.value1 = 0; |
---|
1598 | break; |
---|
1599 | |
---|
1600 | case CC_SET_ZN: |
---|
1601 | /* Insn sets the Z,N flags of CC to recog_operand[0]. |
---|
1602 | The V flag is unusable. The C flag may or may not be known but |
---|
1603 | that's ok because alter_cond will change tests to use EQ/NE. */ |
---|
1604 | CC_STATUS_INIT; |
---|
1605 | cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY; |
---|
1606 | cc_status.value1 = recog_operand[0]; |
---|
1607 | break; |
---|
1608 | |
---|
1609 | case CC_SET_ZNV: |
---|
1610 | /* Insn sets the Z,N,V flags of CC to recog_operand[0]. |
---|
1611 | The C flag may or may not be known but that's ok because |
---|
1612 | alter_cond will change tests to use EQ/NE. */ |
---|
1613 | CC_STATUS_INIT; |
---|
1614 | cc_status.flags |= CC_NO_CARRY; |
---|
1615 | cc_status.value1 = recog_operand[0]; |
---|
1616 | break; |
---|
1617 | |
---|
1618 | case CC_COMPARE: |
---|
1619 | /* The insn is a compare instruction. */ |
---|
1620 | CC_STATUS_INIT; |
---|
1621 | cc_status.value1 = SET_SRC (body); |
---|
1622 | break; |
---|
1623 | |
---|
1624 | case CC_CLOBBER: |
---|
1625 | /* Insn doesn't leave CC in a usable state. */ |
---|
1626 | CC_STATUS_INIT; |
---|
1627 | break; |
---|
1628 | } |
---|
1629 | } |
---|
1630 | |
---|
1631 | /* Recognize valid operators for bit instructions */ |
---|
1632 | |
---|
1633 | int |
---|
1634 | bit_operator (x, mode) |
---|
1635 | rtx x; |
---|
1636 | enum machine_mode mode; |
---|
1637 | { |
---|
1638 | enum rtx_code code = GET_CODE (x); |
---|
1639 | |
---|
1640 | return (code == XOR |
---|
1641 | || code == AND |
---|
1642 | || code == IOR); |
---|
1643 | } |
---|
1644 | |
---|
1645 | /* Shifts. |
---|
1646 | |
---|
1647 | We devote a fair bit of code to getting efficient shifts since we can only |
---|
1648 | shift one bit at a time on the H8/300 and H8/300H and only one or two |
---|
1649 | bits at a time on the H8/S. |
---|
1650 | |
---|
1651 | The basic shift methods: |
---|
1652 | |
---|
1653 | * loop shifts -- emit a loop using one (or two on H8/S) bit shifts; |
---|
1654 | this is the default. SHIFT_LOOP |
---|
1655 | |
---|
1656 | * inlined shifts -- emit straight line code for the shift; this is |
---|
1657 | used when a straight line shift is about the same size or smaller |
---|
1658 | than a loop. We allow the inline version to be slightly longer in |
---|
1659 | some cases as it saves a register. SHIFT_INLINE |
---|
1660 | |
---|
1661 | * rotate + and -- rotate the value the opposite direction, then |
---|
1662 | mask off the values we don't need. This is used when only a few |
---|
1663 | of the bits in the original value will survive in the shifted value. |
---|
1664 | Again, this is used when it's about the same size or smaller than |
---|
1665 | a loop. We allow this version to be slightly longer as it is usually |
---|
1666 | much faster than a loop. SHIFT_ROT_AND |
---|
1667 | |
---|
1668 | * swap (+ shifts) -- often it's possible to swap bytes/words to |
---|
1669 | simulate a shift by 8/16. Once swapped a few inline shifts can be |
---|
1670 | added if the shift count is slightly more than 8 or 16. This is used |
---|
1671 | when it's about the same size or smaller than a loop. We allow this |
---|
1672 | version to be slightly longer as it is usually much faster than a loop. |
---|
1673 | SHIFT_SPECIAL |
---|
1674 | |
---|
1675 | * There other oddballs. Not worth explaining. SHIFT_SPECIAL |
---|
1676 | |
---|
1677 | |
---|
1678 | Here are some thoughts on what the absolutely positively best code is. |
---|
1679 | "Best" here means some rational trade-off between code size and speed, |
---|
1680 | where speed is more preferred but not at the expense of generating 20 insns. |
---|
1681 | |
---|
1682 | A trailing '*' after the shift count indicates the "best" mode isn't |
---|
1683 | implemented. |
---|
1684 | |
---|
1685 | H8/300 QImode shifts |
---|
1686 | 1-4 - do them inline |
---|
1687 | 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits |
---|
1688 | ASHIFTRT: loop |
---|
1689 | 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits |
---|
1690 | ASHIFTRT: shll, subx (propagate carry bit to all bits) |
---|
1691 | |
---|
1692 | H8/300 HImode shifts |
---|
1693 | 1-4 - do them inline |
---|
1694 | 5-6 - loop |
---|
1695 | 7 - shift 2nd half other way into carry. |
---|
1696 | copy 1st half into 2nd half |
---|
1697 | rotate 2nd half other way with carry |
---|
1698 | rotate 1st half other way (no carry) |
---|
1699 | mask off bits in 1st half (ASHIFT | LSHIFTRT). |
---|
1700 | sign extend 1st half (ASHIFTRT) |
---|
1701 | 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT) |
---|
1702 | 9-12 - do shift by 8, inline remaining shifts |
---|
1703 | 13-14* - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0 |
---|
1704 | - ASHIFTRT: loop |
---|
1705 | 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0 |
---|
1706 | - ASHIFTRT: shll, subx, set other byte |
---|
1707 | |
---|
1708 | H8/300 SImode shifts |
---|
1709 | 1-2 - do them inline |
---|
1710 | 3-6 - loop |
---|
1711 | 7* - shift other way once, move bytes into place, |
---|
1712 | move carry into place (possibly with sign extension) |
---|
1713 | 8 - move bytes into place, zero or sign extend other |
---|
1714 | 9-14 - loop |
---|
1715 | 15* - shift other way once, move word into place, move carry into place |
---|
1716 | 16 - move word, zero or sign extend other |
---|
1717 | 17-23 - loop |
---|
1718 | 24* - move bytes into place, zero or sign extend other |
---|
1719 | 25-27 - loop |
---|
1720 | 28-30* - ASHIFT | LSHIFTRT: rotate top byte, mask, move byte into place, |
---|
1721 | zero others |
---|
1722 | ASHIFTRT: loop |
---|
1723 | 31 - ASHIFT | LSHIFTRT: rotate top byte, mask, byte byte into place, |
---|
1724 | zero others |
---|
1725 | ASHIFTRT: shll top byte, subx, copy to other bytes |
---|
1726 | |
---|
1727 | H8/300H QImode shifts (same as H8/300 QImode shifts) |
---|
1728 | 1-4 - do them inline |
---|
1729 | 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits |
---|
1730 | ASHIFTRT: loop |
---|
1731 | 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits |
---|
1732 | ASHIFTRT: shll, subx (propagate carry bit to all bits) |
---|
1733 | |
---|
1734 | |
---|
1735 | H8/300H HImode shifts |
---|
1736 | 1-4 - do them inline |
---|
1737 | 5-6 - loop |
---|
1738 | 7 - shift 2nd half other way into carry. |
---|
1739 | copy 1st half into 2nd half |
---|
1740 | rotate entire word other way using carry |
---|
1741 | mask off remaining bits (ASHIFT | LSHIFTRT) |
---|
1742 | sign extend remaining bits (ASHIFTRT) |
---|
1743 | 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT) |
---|
1744 | 9-12 - do shift by 8, inline remaining shifts |
---|
1745 | 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0 |
---|
1746 | - ASHIFTRT: loop |
---|
1747 | 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0 |
---|
1748 | - ASHIFTRT: shll, subx, set other byte |
---|
1749 | |
---|
1750 | H8/300H SImode shifts |
---|
1751 | (These are complicated by the fact that we don't have byte level access to |
---|
1752 | the top word.) |
---|
1753 | A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw) |
---|
1754 | 1-4 - do them inline |
---|
1755 | 5-14 - loop |
---|
1756 | 15* - shift other way once, move word into place, move carry into place |
---|
1757 | (with sign extension for ASHIFTRT) |
---|
1758 | 16 - move word into place, zero or sign extend other |
---|
1759 | 17-20 - do 16bit shift, then inline remaining shifts |
---|
1760 | 20-23 - loop |
---|
1761 | 24* - ASHIFT: move byte 0(msb) to byte 1, zero byte 0, |
---|
1762 | move word 0 to word 1, zero word 0 |
---|
1763 | LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0, |
---|
1764 | zero word 1, zero byte 1 |
---|
1765 | ASHIFTRT: move word 1 to word 0, move byte 1 to byte 0, |
---|
1766 | sign extend byte 0, sign extend word 0 |
---|
1767 | 25-27* - either loop, or |
---|
1768 | do 24 bit shift, inline rest |
---|
1769 | 28-30 - ASHIFT: rotate 4/3/2, mask |
---|
1770 | LSHIFTRT: rotate 4/3/2, mask |
---|
1771 | ASHIFTRT: loop |
---|
1772 | 31 - shll, subx byte 0, sign extend byte 0, sign extend word 0 |
---|
1773 | |
---|
1774 | H8/S QImode shifts |
---|
1775 | 1-6 - do them inline |
---|
1776 | 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits |
---|
1777 | ASHIFTRT: shll, subx (propagate carry bit to all bits) |
---|
1778 | |
---|
1779 | H8/S HImode shifts |
---|
1780 | 1-7 - do them inline |
---|
1781 | 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT) |
---|
1782 | 9-12 - do shift by 8, inline remaining shifts |
---|
1783 | 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0 |
---|
1784 | - ASHIFTRT: loop |
---|
1785 | 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0 |
---|
1786 | - ASHIFTRT: shll, subx, set other byte |
---|
1787 | |
---|
1788 | H8/S SImode shifts |
---|
1789 | (These are complicated by the fact that we don't have byte level access to |
---|
1790 | the top word.) |
---|
1791 | A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw) |
---|
1792 | 1-10 - do them inline |
---|
1793 | 11-14 - loop |
---|
1794 | 15* - shift other way once, move word into place, move carry into place |
---|
1795 | (with sign extension for ASHIFTRT) |
---|
1796 | 16 - move word into place, zero or sign extend other |
---|
1797 | 17-20 - do 16bit shift, then inline remaining shifts |
---|
1798 | 20-23 - loop |
---|
1799 | 24* - ASHIFT: move byte 0(msb) to byte 1, zero byte 0, |
---|
1800 | move word 0 to word 1, zero word 0 |
---|
1801 | LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0, |
---|
1802 | zero word 1, zero byte 1 |
---|
1803 | ASHIFTRT: move word 1 to word 0, move byte 1 to byte 0, |
---|
1804 | sign extend byte 0, sign extend word 0 |
---|
1805 | 25-27* - either loop, or |
---|
1806 | do 24 bit shift, inline rest |
---|
1807 | 28-30 - ASHIFT: rotate 4/3/2, mask |
---|
1808 | LSHIFTRT: rotate 4/3/2, mask |
---|
1809 | ASHIFTRT: loop |
---|
1810 | 31 - shll, subx byte 0, sign extend byte 0, sign extend word 0 |
---|
1811 | |
---|
1812 | Panic!!! */ |
---|
1813 | |
---|
1814 | int |
---|
1815 | nshift_operator (x, mode) |
---|
1816 | rtx x; |
---|
1817 | enum machine_mode mode; |
---|
1818 | { |
---|
1819 | switch (GET_CODE (x)) |
---|
1820 | { |
---|
1821 | case ASHIFTRT: |
---|
1822 | case LSHIFTRT: |
---|
1823 | case ASHIFT: |
---|
1824 | return 1; |
---|
1825 | |
---|
1826 | default: |
---|
1827 | return 0; |
---|
1828 | } |
---|
1829 | } |
---|
1830 | |
---|
1831 | /* Called from the .md file to emit code to do shifts. |
---|
1832 | Returns a boolean indicating success |
---|
1833 | (currently this is always TRUE). */ |
---|
1834 | |
---|
1835 | int |
---|
1836 | expand_a_shift (mode, code, operands) |
---|
1837 | enum machine_mode mode; |
---|
1838 | int code; |
---|
1839 | rtx operands[]; |
---|
1840 | { |
---|
1841 | emit_move_insn (operands[0], operands[1]); |
---|
1842 | |
---|
1843 | /* need a loop to get all the bits we want - we generate the |
---|
1844 | code at emit time, but need to allocate a scratch reg now */ |
---|
1845 | |
---|
1846 | emit_insn (gen_rtx |
---|
1847 | (PARALLEL, VOIDmode, |
---|
1848 | gen_rtvec (2, |
---|
1849 | gen_rtx (SET, VOIDmode, operands[0], |
---|
1850 | gen_rtx (code, mode, operands[0], operands[2])), |
---|
1851 | gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, QImode, 0))))); |
---|
1852 | |
---|
1853 | return 1; |
---|
1854 | } |
---|
1855 | |
---|
1856 | /* Shift algorithm determination. |
---|
1857 | |
---|
1858 | There are various ways of doing a shift: |
---|
1859 | SHIFT_INLINE: If the amount is small enough, just generate as many one-bit |
---|
1860 | shifts as we need. |
---|
1861 | SHIFT_ROT_AND: If the amount is large but close to either end, rotate the |
---|
1862 | necessary bits into position and then set the rest to zero. |
---|
1863 | SHIFT_SPECIAL: Hand crafted assembler. |
---|
1864 | SHIFT_LOOP: If the above methods fail, just loop. */ |
---|
1865 | |
---|
1866 | enum shift_alg |
---|
1867 | { |
---|
1868 | SHIFT_INLINE, |
---|
1869 | SHIFT_ROT_AND, |
---|
1870 | SHIFT_SPECIAL, |
---|
1871 | SHIFT_LOOP, |
---|
1872 | SHIFT_MAX |
---|
1873 | }; |
---|
1874 | |
---|
1875 | /* Symbols of the various shifts which can be used as indices. */ |
---|
1876 | |
---|
1877 | enum shift_type |
---|
1878 | { |
---|
1879 | SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT |
---|
1880 | }; |
---|
1881 | |
---|
1882 | /* Symbols of the various modes which can be used as indices. */ |
---|
1883 | |
---|
1884 | enum shift_mode |
---|
1885 | { |
---|
1886 | QIshift, HIshift, SIshift |
---|
1887 | }; |
---|
1888 | |
---|
1889 | /* For single bit shift insns, record assembler and what bits of the |
---|
1890 | condition code are valid afterwards (represented as various CC_FOO |
---|
1891 | bits, 0 means CC isn't left in a usable state). */ |
---|
1892 | |
---|
1893 | struct shift_insn |
---|
1894 | { |
---|
1895 | char *assembler; |
---|
1896 | int cc_valid; |
---|
1897 | }; |
---|
1898 | |
---|
1899 | /* Assembler instruction shift table. |
---|
1900 | |
---|
1901 | These tables are used to look up the basic shifts. |
---|
1902 | They are indexed by cpu, shift_type, and mode. |
---|
1903 | */ |
---|
1904 | |
---|
1905 | static const struct shift_insn shift_one[2][3][3] = |
---|
1906 | { |
---|
1907 | /* H8/300 */ |
---|
1908 | { |
---|
1909 | /* SHIFT_ASHIFT */ |
---|
1910 | { |
---|
1911 | { "shll\t%X0", CC_NO_CARRY }, |
---|
1912 | { "add.w\t%T0,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, |
---|
1913 | { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", 0 } |
---|
1914 | }, |
---|
1915 | /* SHIFT_LSHIFTRT */ |
---|
1916 | { |
---|
1917 | { "shlr\t%X0", CC_NO_CARRY }, |
---|
1918 | { "shlr\t%t0\n\trotxr\t%s0", 0 }, |
---|
1919 | { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 } |
---|
1920 | }, |
---|
1921 | /* SHIFT_ASHIFTRT */ |
---|
1922 | { |
---|
1923 | { "shar\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, |
---|
1924 | { "shar\t%t0\n\trotxr\t%s0", 0 }, |
---|
1925 | { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 } |
---|
1926 | } |
---|
1927 | }, |
---|
1928 | /* H8/300H */ |
---|
1929 | { |
---|
1930 | /* SHIFT_ASHIFT */ |
---|
1931 | { |
---|
1932 | { "shll.b\t%X0", CC_NO_CARRY }, |
---|
1933 | { "shll.w\t%T0", CC_NO_CARRY }, |
---|
1934 | { "shll.l\t%S0", CC_NO_CARRY } |
---|
1935 | }, |
---|
1936 | /* SHIFT_LSHIFTRT */ |
---|
1937 | { |
---|
1938 | { "shlr.b\t%X0", CC_NO_CARRY }, |
---|
1939 | { "shlr.w\t%T0", CC_NO_CARRY }, |
---|
1940 | { "shlr.l\t%S0", CC_NO_CARRY } |
---|
1941 | }, |
---|
1942 | /* SHIFT_ASHIFTRT */ |
---|
1943 | { |
---|
1944 | { "shar.b\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, |
---|
1945 | { "shar.w\t%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, |
---|
1946 | { "shar.l\t%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY } |
---|
1947 | } |
---|
1948 | } |
---|
1949 | }; |
---|
1950 | |
---|
1951 | static const struct shift_insn shift_two[3][3] = |
---|
1952 | { |
---|
1953 | /* SHIFT_ASHIFT */ |
---|
1954 | { |
---|
1955 | { "shll.b\t#2,%X0", CC_NO_CARRY }, |
---|
1956 | { "shll.w\t#2,%T0", CC_NO_CARRY }, |
---|
1957 | { "shll.l\t#2,%S0", CC_NO_CARRY } |
---|
1958 | }, |
---|
1959 | /* SHIFT_LSHIFTRT */ |
---|
1960 | { |
---|
1961 | { "shlr.b\t#2,%X0", CC_NO_CARRY }, |
---|
1962 | { "shlr.w\t#2,%T0", CC_NO_CARRY }, |
---|
1963 | { "shlr.l\t#2,%S0", CC_NO_CARRY } |
---|
1964 | }, |
---|
1965 | /* SHIFT_ASHIFTRT */ |
---|
1966 | { |
---|
1967 | { "shar.b\t#2,%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, |
---|
1968 | { "shar.w\t#2,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }, |
---|
1969 | { "shar.l\t#2,%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY } |
---|
1970 | } |
---|
1971 | }; |
---|
1972 | |
---|
1973 | /* Rotates are organized by which shift they'll be used in implementing. |
---|
1974 | There's no need to record whether the cc is valid afterwards because |
---|
1975 | it is the AND insn that will decide this. */ |
---|
1976 | |
---|
1977 | static const char *const rotate_one[2][3][3] = |
---|
1978 | { |
---|
1979 | /* H8/300 */ |
---|
1980 | { |
---|
1981 | /* SHIFT_ASHIFT */ |
---|
1982 | { |
---|
1983 | "rotr\t%X0", |
---|
1984 | "shlr\t%t0\n\trotxr\t%s0\n\tbst\t#7,%t0", |
---|
1985 | 0 |
---|
1986 | }, |
---|
1987 | /* SHIFT_LSHIFTRT */ |
---|
1988 | { |
---|
1989 | "rotl\t%X0", |
---|
1990 | "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0", |
---|
1991 | 0 |
---|
1992 | }, |
---|
1993 | /* SHIFT_ASHIFTRT */ |
---|
1994 | { |
---|
1995 | "rotl\t%X0", |
---|
1996 | "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0", |
---|
1997 | 0 |
---|
1998 | } |
---|
1999 | }, |
---|
2000 | /* H8/300H */ |
---|
2001 | { |
---|
2002 | /* SHIFT_ASHIFT */ |
---|
2003 | { |
---|
2004 | "rotr.b\t%X0", |
---|
2005 | "rotr.w\t%T0", |
---|
2006 | "rotr.l\t%S0" |
---|
2007 | }, |
---|
2008 | /* SHIFT_LSHIFTRT */ |
---|
2009 | { |
---|
2010 | "rotl.b\t%X0", |
---|
2011 | "rotl.w\t%T0", |
---|
2012 | "rotl.l\t%S0" |
---|
2013 | }, |
---|
2014 | /* SHIFT_ASHIFTRT */ |
---|
2015 | { |
---|
2016 | "rotl.b\t%X0", |
---|
2017 | "rotl.w\t%T0", |
---|
2018 | "rotl.l\t%S0" |
---|
2019 | } |
---|
2020 | } |
---|
2021 | }; |
---|
2022 | |
---|
2023 | static const char *const rotate_two[3][3] = |
---|
2024 | { |
---|
2025 | /* SHIFT_ASHIFT */ |
---|
2026 | { |
---|
2027 | "rotr.b\t#2,%X0", |
---|
2028 | "rotr.w\t#2,%T0", |
---|
2029 | "rotr.l\t#2,%S0" |
---|
2030 | }, |
---|
2031 | /* SHIFT_LSHIFTRT */ |
---|
2032 | { |
---|
2033 | "rotl.b\t#2,%X0", |
---|
2034 | "rotl.w\t#2,%T0", |
---|
2035 | "rotl.l\t#2,%S0" |
---|
2036 | }, |
---|
2037 | /* SHIFT_ASHIFTRT */ |
---|
2038 | { |
---|
2039 | "rotl.b\t#2,%X0", |
---|
2040 | "rotl.w\t#2,%T0", |
---|
2041 | "rotl.l\t#2,%S0" |
---|
2042 | } |
---|
2043 | }; |
---|
2044 | |
---|
2045 | /* Given CPU, MODE, SHIFT_TYPE, and shift count COUNT, determine the best |
---|
2046 | algorithm for doing the shift. The assembler code is stored in ASSEMBLER. |
---|
2047 | We don't achieve maximum efficiency in all cases, but the hooks are here |
---|
2048 | to do so. |
---|
2049 | |
---|
2050 | For now we just use lots of switch statements. Since we don't even come |
---|
2051 | close to supporting all the cases, this is simplest. If this function ever |
---|
2052 | gets too big, perhaps resort to a more table based lookup. Of course, |
---|
2053 | at this point you may just wish to do it all in rtl. |
---|
2054 | |
---|
2055 | WARNING: The constraints on insns shiftbyn_QI/HI/SI assume shifts of |
---|
2056 | 1,2,3,4 will be inlined (1,2 for SI). */ |
---|
2057 | |
---|
2058 | static enum shift_alg |
---|
2059 | get_shift_alg (cpu, shift_type, mode, count, assembler_p, |
---|
2060 | assembler2_p, cc_valid_p) |
---|
2061 | enum attr_cpu cpu; |
---|
2062 | enum shift_type shift_type; |
---|
2063 | enum machine_mode mode; |
---|
2064 | int count; |
---|
2065 | const char **assembler_p; |
---|
2066 | const char **assembler2_p; |
---|
2067 | int *cc_valid_p; |
---|
2068 | { |
---|
2069 | /* The default is to loop. */ |
---|
2070 | enum shift_alg alg = SHIFT_LOOP; |
---|
2071 | enum shift_mode shift_mode; |
---|
2072 | |
---|
2073 | /* We don't handle negative shifts or shifts greater than the word size, |
---|
2074 | they should have been handled already. */ |
---|
2075 | |
---|
2076 | if (count < 0 || count > GET_MODE_BITSIZE (mode)) |
---|
2077 | abort (); |
---|
2078 | |
---|
2079 | switch (mode) |
---|
2080 | { |
---|
2081 | case QImode: |
---|
2082 | shift_mode = QIshift; |
---|
2083 | break; |
---|
2084 | case HImode: |
---|
2085 | shift_mode = HIshift; |
---|
2086 | break; |
---|
2087 | case SImode: |
---|
2088 | shift_mode = SIshift; |
---|
2089 | break; |
---|
2090 | default: |
---|
2091 | abort (); |
---|
2092 | } |
---|
2093 | |
---|
2094 | /* Assume either SHIFT_LOOP or SHIFT_INLINE. |
---|
2095 | It is up to the caller to know that looping clobbers cc. */ |
---|
2096 | *assembler_p = shift_one[cpu][shift_type][shift_mode].assembler; |
---|
2097 | if (TARGET_H8300S) |
---|
2098 | *assembler2_p = shift_two[shift_type][shift_mode].assembler; |
---|
2099 | else |
---|
2100 | *assembler2_p = NULL; |
---|
2101 | *cc_valid_p = shift_one[cpu][shift_type][shift_mode].cc_valid; |
---|
2102 | |
---|
2103 | /* Now look for cases we want to optimize. */ |
---|
2104 | |
---|
2105 | switch (shift_mode) |
---|
2106 | { |
---|
2107 | case QIshift: |
---|
2108 | if (count <= 4) |
---|
2109 | return SHIFT_INLINE; |
---|
2110 | else |
---|
2111 | { |
---|
2112 | /* Shift by 5/6 are only 3 insns on the H8/S, so it's just as |
---|
2113 | fast as SHIFT_ROT_AND, plus CC is valid. */ |
---|
2114 | if (TARGET_H8300S && count <= 6) |
---|
2115 | return SHIFT_INLINE; |
---|
2116 | |
---|
2117 | /* For ASHIFTRT by 7 bits, the sign bit is simply replicated |
---|
2118 | through the entire value. */ |
---|
2119 | if (shift_type == SHIFT_ASHIFTRT && count == 7) |
---|
2120 | { |
---|
2121 | *assembler_p = "shll\t%X0\n\tsubx\t%X0,%X0"; |
---|
2122 | *cc_valid_p = 0; |
---|
2123 | return SHIFT_SPECIAL; |
---|
2124 | } |
---|
2125 | |
---|
2126 | /* Other ASHIFTRTs are too much of a pain. */ |
---|
2127 | if (shift_type == SHIFT_ASHIFTRT) |
---|
2128 | return SHIFT_LOOP; |
---|
2129 | |
---|
2130 | /* Other shifts by 5, 6, or 7 bits use SHIFT_ROT_AND. */ |
---|
2131 | *assembler_p = rotate_one[cpu][shift_type][shift_mode]; |
---|
2132 | if (TARGET_H8300S) |
---|
2133 | *assembler2_p = rotate_two[shift_type][shift_mode]; |
---|
2134 | *cc_valid_p = 0; |
---|
2135 | return SHIFT_ROT_AND; |
---|
2136 | } |
---|
2137 | |
---|
2138 | case HIshift: |
---|
2139 | if (count <= 4) |
---|
2140 | return SHIFT_INLINE; |
---|
2141 | else if (TARGET_H8300S && count <= 7) |
---|
2142 | return SHIFT_INLINE; |
---|
2143 | else if (count == 7) |
---|
2144 | { |
---|
2145 | if (shift_type == SHIFT_ASHIFT && TARGET_H8300) |
---|
2146 | { |
---|
2147 | *assembler_p = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.b\t%t0\n\trotr.b\t%s0\n\tand.b\t#0x80,%s0"; |
---|
2148 | *cc_valid_p = 0; |
---|
2149 | return SHIFT_SPECIAL; |
---|
2150 | } |
---|
2151 | |
---|
2152 | if (shift_type == SHIFT_ASHIFT && TARGET_H8300H) |
---|
2153 | { |
---|
2154 | *assembler_p = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.w\t%T0\n\tand.b\t#0x80,%s0"; |
---|
2155 | *cc_valid_p = 0; |
---|
2156 | return SHIFT_SPECIAL; |
---|
2157 | } |
---|
2158 | |
---|
2159 | if (shift_type == SHIFT_LSHIFTRT && TARGET_H8300) |
---|
2160 | { |
---|
2161 | *assembler_p = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\trotl.b\t%t0\n\tand.b\t#0x01,%t0"; |
---|
2162 | *cc_valid_p = 0; |
---|
2163 | return SHIFT_SPECIAL; |
---|
2164 | } |
---|
2165 | |
---|
2166 | if (shift_type == SHIFT_LSHIFTRT && TARGET_H8300H) |
---|
2167 | { |
---|
2168 | *assembler_p = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.w\t%T0\n\tand.b\t#0x01,%t0"; |
---|
2169 | *cc_valid_p = 0; |
---|
2170 | return SHIFT_SPECIAL; |
---|
2171 | } |
---|
2172 | |
---|
2173 | if (shift_type == SHIFT_ASHIFTRT) |
---|
2174 | { |
---|
2175 | *assembler_p = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\tsubx\t%t0,%t0"; |
---|
2176 | *cc_valid_p = 0; |
---|
2177 | return SHIFT_SPECIAL; |
---|
2178 | } |
---|
2179 | } |
---|
2180 | else if (count == 8) |
---|
2181 | { |
---|
2182 | switch (shift_type) |
---|
2183 | { |
---|
2184 | case SHIFT_ASHIFT: |
---|
2185 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0"; |
---|
2186 | *cc_valid_p = 0; |
---|
2187 | return SHIFT_SPECIAL; |
---|
2188 | case SHIFT_LSHIFTRT: |
---|
2189 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0"; |
---|
2190 | *cc_valid_p = 0; |
---|
2191 | return SHIFT_SPECIAL; |
---|
2192 | case SHIFT_ASHIFTRT: |
---|
2193 | if (TARGET_H8300) |
---|
2194 | *assembler_p = "mov.b\t%t0,%s0\n\tshll\t%t0\n\tsubx\t%t0,%t0\t"; |
---|
2195 | else |
---|
2196 | *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0"; |
---|
2197 | *cc_valid_p = 0; |
---|
2198 | return SHIFT_SPECIAL; |
---|
2199 | } |
---|
2200 | } |
---|
2201 | else if (count == 9) |
---|
2202 | { |
---|
2203 | switch (shift_type) |
---|
2204 | { |
---|
2205 | case SHIFT_ASHIFT: |
---|
2206 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0"; |
---|
2207 | *cc_valid_p = 0; |
---|
2208 | return SHIFT_SPECIAL; |
---|
2209 | case SHIFT_LSHIFTRT: |
---|
2210 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0"; |
---|
2211 | *cc_valid_p = 0; |
---|
2212 | return SHIFT_SPECIAL; |
---|
2213 | case SHIFT_ASHIFTRT: |
---|
2214 | if (TARGET_H8300) |
---|
2215 | *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0"; |
---|
2216 | else |
---|
2217 | *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t%s0"; |
---|
2218 | *cc_valid_p = 0; |
---|
2219 | return SHIFT_SPECIAL; |
---|
2220 | } |
---|
2221 | } |
---|
2222 | else if (count == 10) |
---|
2223 | { |
---|
2224 | switch (shift_type) |
---|
2225 | { |
---|
2226 | case SHIFT_ASHIFT: |
---|
2227 | if (TARGET_H8300S) |
---|
2228 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t#2,%t0\n\t"; |
---|
2229 | else |
---|
2230 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0\n\tshal.b\t%t0"; |
---|
2231 | *cc_valid_p = 0; |
---|
2232 | return SHIFT_SPECIAL; |
---|
2233 | case SHIFT_LSHIFTRT: |
---|
2234 | if (TARGET_H8300S) |
---|
2235 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t#2,%s0"; |
---|
2236 | else |
---|
2237 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0\n\tshlr.b\t%s0"; |
---|
2238 | *cc_valid_p = 0; |
---|
2239 | return SHIFT_SPECIAL; |
---|
2240 | case SHIFT_ASHIFTRT: |
---|
2241 | if (TARGET_H8300) |
---|
2242 | *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0\n\tshar.b\t%s0"; |
---|
2243 | else if (TARGET_H8300H) |
---|
2244 | *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t%s0\n\tshar.b\t%s0"; |
---|
2245 | else if (TARGET_H8300S) |
---|
2246 | *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t#2,%s0"; |
---|
2247 | *cc_valid_p = 0; |
---|
2248 | return SHIFT_SPECIAL; |
---|
2249 | } |
---|
2250 | } |
---|
2251 | else if (count == 11) |
---|
2252 | { |
---|
2253 | switch (shift_type) |
---|
2254 | { |
---|
2255 | case SHIFT_ASHIFT: |
---|
2256 | if (TARGET_H8300S) |
---|
2257 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t#2,%t0\n\tshal.b\t%t0"; |
---|
2258 | else |
---|
2259 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0\n\tshal.b\t%t0\n\tshal.b\t%t0"; |
---|
2260 | *cc_valid_p = 0; |
---|
2261 | return SHIFT_SPECIAL; |
---|
2262 | case SHIFT_LSHIFTRT: |
---|
2263 | if (TARGET_H8300S) |
---|
2264 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t#2,%s0\n\tshlr.b\t%s0"; |
---|
2265 | else |
---|
2266 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0\n\tshlr.b\t%s0\n\tshlr.b\t%s0"; |
---|
2267 | *cc_valid_p = 0; |
---|
2268 | return SHIFT_SPECIAL; |
---|
2269 | case SHIFT_ASHIFTRT: |
---|
2270 | if (TARGET_H8300) |
---|
2271 | *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0"; |
---|
2272 | else if (TARGET_H8300H) |
---|
2273 | *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0"; |
---|
2274 | else if (TARGET_H8300S) |
---|
2275 | *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t#2,%s0\n\tshar.b\t%s0"; |
---|
2276 | *cc_valid_p = 0; |
---|
2277 | return SHIFT_SPECIAL; |
---|
2278 | } |
---|
2279 | } |
---|
2280 | else if (count == 12) |
---|
2281 | { |
---|
2282 | switch (shift_type) |
---|
2283 | { |
---|
2284 | case SHIFT_ASHIFT: |
---|
2285 | if (TARGET_H8300S) |
---|
2286 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t#2,%t0\n\tshal.b\t#2,%t0"; |
---|
2287 | else |
---|
2288 | *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0\n\tshal.b\t%t0\n\tshal.b\t%t0\n\tshal.b\t%t0"; |
---|
2289 | *cc_valid_p = 0; |
---|
2290 | return SHIFT_SPECIAL; |
---|
2291 | case SHIFT_LSHIFTRT: |
---|
2292 | if (TARGET_H8300S) |
---|
2293 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t#2,%s0\n\tshlr.b\t#2,%s0"; |
---|
2294 | else |
---|
2295 | *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0\n\tshlr.b\t%s0\n\tshlr.b\t%s0\n\tshlr.b\t%s0"; |
---|
2296 | *cc_valid_p = 0; |
---|
2297 | return SHIFT_SPECIAL; |
---|
2298 | case SHIFT_ASHIFTRT: |
---|
2299 | if (TARGET_H8300) |
---|
2300 | *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0"; |
---|
2301 | else if (TARGET_H8300H) |
---|
2302 | *assembler_p = "mov.b\t%t0,%s0\n\textw.w\t%T0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0"; |
---|
2303 | else if (TARGET_H8300S) |
---|
2304 | *assembler_p = "mov.b\t%t0,%s0\n\textw.w\t%T0\n\tshar.b\t#2,%s0\n\tshar.b\t#2,%s0"; |
---|
2305 | *cc_valid_p = 0; |
---|
2306 | return SHIFT_SPECIAL; |
---|
2307 | } |
---|
2308 | } |
---|
2309 | else if (!TARGET_H8300 && (count == 13 || count == 14) |
---|
2310 | || count == 15) |
---|
2311 | { |
---|
2312 | if (count == 15 && shift_type == SHIFT_ASHIFTRT) |
---|
2313 | { |
---|
2314 | *assembler_p = "shll\t%t0,%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0"; |
---|
2315 | *cc_valid_p = 0; |
---|
2316 | return SHIFT_SPECIAL; |
---|
2317 | } |
---|
2318 | else if (shift_type != SHIFT_ASHIFTRT) |
---|
2319 | { |
---|
2320 | *assembler_p = rotate_one[cpu][shift_type][shift_mode]; |
---|
2321 | if (TARGET_H8300S) |
---|
2322 | *assembler2_p = rotate_two[shift_type][shift_mode]; |
---|
2323 | else |
---|
2324 | *assembler2_p = NULL; |
---|
2325 | *cc_valid_p = 0; |
---|
2326 | return SHIFT_ROT_AND; |
---|
2327 | } |
---|
2328 | } |
---|
2329 | break; |
---|
2330 | |
---|
2331 | case SIshift: |
---|
2332 | if (count <= (TARGET_H8300 ? 2 : 4)) |
---|
2333 | return SHIFT_INLINE; |
---|
2334 | else if (TARGET_H8300S && count <= 10) |
---|
2335 | return SHIFT_INLINE; |
---|
2336 | else if (count == 8 && TARGET_H8300) |
---|
2337 | { |
---|
2338 | switch (shift_type) |
---|
2339 | { |
---|
2340 | case SHIFT_ASHIFT: |
---|
2341 | *assembler_p = "mov.b\t%y0,%z0n\tmov.b\t%x0,%y0\n\tmov.b\t%w0,%x0\n\tsub.b\t%w0,%w0"; |
---|
2342 | *cc_valid_p = 0; |
---|
2343 | return SHIFT_SPECIAL; |
---|
2344 | case SHIFT_LSHIFTRT: |
---|
2345 | *assembler_p = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tsub.b\t%z0,%z0"; |
---|
2346 | *cc_valid_p = 0; |
---|
2347 | return SHIFT_SPECIAL; |
---|
2348 | case SHIFT_ASHIFTRT: |
---|
2349 | *assembler_p = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tshll\t%z0\n\tsubx\t%z0,%z0"; |
---|
2350 | *cc_valid_p = 0; |
---|
2351 | return SHIFT_SPECIAL; |
---|
2352 | } |
---|
2353 | } |
---|
2354 | else if (count == 16) |
---|
2355 | { |
---|
2356 | switch (shift_type) |
---|
2357 | { |
---|
2358 | case SHIFT_ASHIFT: |
---|
2359 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0"; |
---|
2360 | *cc_valid_p = 0; |
---|
2361 | return SHIFT_SPECIAL; |
---|
2362 | case SHIFT_LSHIFTRT: |
---|
2363 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0"; |
---|
2364 | *cc_valid_p = 0; |
---|
2365 | return SHIFT_SPECIAL; |
---|
2366 | case SHIFT_ASHIFTRT: |
---|
2367 | if (TARGET_H8300) |
---|
2368 | *assembler_p = "mov.w\t%e0,%f0\n\tshll\t%z0\n\tsubx\t%z0,%z0\n\tmov.b\t%z0,%y0"; |
---|
2369 | else |
---|
2370 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0"; |
---|
2371 | *cc_valid_p = 0; |
---|
2372 | return SHIFT_SPECIAL; |
---|
2373 | } |
---|
2374 | } |
---|
2375 | else if (count == 17 && !TARGET_H8300) |
---|
2376 | { |
---|
2377 | switch (shift_type) |
---|
2378 | { |
---|
2379 | case SHIFT_ASHIFT: |
---|
2380 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t%S0"; |
---|
2381 | *cc_valid_p = 0; |
---|
2382 | return SHIFT_SPECIAL; |
---|
2383 | case SHIFT_LSHIFTRT: |
---|
2384 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t%S0"; |
---|
2385 | *cc_valid_p = 0; |
---|
2386 | return SHIFT_SPECIAL; |
---|
2387 | case SHIFT_ASHIFTRT: |
---|
2388 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t%S0"; |
---|
2389 | *cc_valid_p = 0; |
---|
2390 | return SHIFT_SPECIAL; |
---|
2391 | } |
---|
2392 | } |
---|
2393 | else if (count == 18 && !TARGET_H8300) |
---|
2394 | { |
---|
2395 | switch (shift_type) |
---|
2396 | { |
---|
2397 | case SHIFT_ASHIFT: |
---|
2398 | if (TARGET_H8300S) |
---|
2399 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t#2,%S0"; |
---|
2400 | else |
---|
2401 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t%S0\n\tshll.l\t%S0"; |
---|
2402 | *cc_valid_p = 0; |
---|
2403 | return SHIFT_SPECIAL; |
---|
2404 | case SHIFT_LSHIFTRT: |
---|
2405 | if (TARGET_H8300S) |
---|
2406 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t#2,%S0"; |
---|
2407 | else |
---|
2408 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t%S0\n\tshlr.l\t%S0"; |
---|
2409 | *cc_valid_p = 0; |
---|
2410 | return SHIFT_SPECIAL; |
---|
2411 | case SHIFT_ASHIFTRT: |
---|
2412 | if (TARGET_H8300S) |
---|
2413 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t#2,%S0"; |
---|
2414 | else |
---|
2415 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t%S0\n\tshar.l\t%S0"; |
---|
2416 | *cc_valid_p = 0; |
---|
2417 | return SHIFT_SPECIAL; |
---|
2418 | } |
---|
2419 | } |
---|
2420 | else if (count == 19 && !TARGET_H8300) |
---|
2421 | { |
---|
2422 | switch (shift_type) |
---|
2423 | { |
---|
2424 | case SHIFT_ASHIFT: |
---|
2425 | if (TARGET_H8300S) |
---|
2426 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t#2,%S0\n\tshll.l\t%S0"; |
---|
2427 | else |
---|
2428 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t%S0\n\tshll.l\t%S0\n\tshll.l\t%S0"; |
---|
2429 | *cc_valid_p = 0; |
---|
2430 | return SHIFT_SPECIAL; |
---|
2431 | case SHIFT_LSHIFTRT: |
---|
2432 | if (TARGET_H8300S) |
---|
2433 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t#2,%S0\n\tshlr.l\t%S0"; |
---|
2434 | else |
---|
2435 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t%S0\n\tshlr.l\t%S0\n\tshlr.l\t%S0"; |
---|
2436 | *cc_valid_p = 0; |
---|
2437 | return SHIFT_SPECIAL; |
---|
2438 | case SHIFT_ASHIFTRT: |
---|
2439 | if (TARGET_H8300S) |
---|
2440 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t#2,%S0\n\tshar.l\t%S0"; |
---|
2441 | else |
---|
2442 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t%S0\n\tshar.l\t%S0\n\tshar.l\t%S0"; |
---|
2443 | *cc_valid_p = 0; |
---|
2444 | return SHIFT_SPECIAL; |
---|
2445 | } |
---|
2446 | } |
---|
2447 | else if (count == 20 && TARGET_H8300S) |
---|
2448 | { |
---|
2449 | switch (shift_type) |
---|
2450 | { |
---|
2451 | case SHIFT_ASHIFT: |
---|
2452 | *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t#2,%S0\n\tshll.l\t#2,%S0"; |
---|
2453 | *cc_valid_p = 0; |
---|
2454 | return SHIFT_SPECIAL; |
---|
2455 | case SHIFT_LSHIFTRT: |
---|
2456 | *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t#2,%S0\n\tshlr.l\t#2,%S0"; |
---|
2457 | *cc_valid_p = 0; |
---|
2458 | return SHIFT_SPECIAL; |
---|
2459 | case SHIFT_ASHIFTRT: |
---|
2460 | *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t#2,%S0\n\tshar.l\t#2,%S0"; |
---|
2461 | *cc_valid_p = 0; |
---|
2462 | return SHIFT_SPECIAL; |
---|
2463 | } |
---|
2464 | } |
---|
2465 | else if (count >= 28 && count <= 30 && !TARGET_H8300) |
---|
2466 | { |
---|
2467 | if (shift_type == SHIFT_ASHIFTRT) |
---|
2468 | { |
---|
2469 | return SHIFT_LOOP; |
---|
2470 | } |
---|
2471 | else |
---|
2472 | { |
---|
2473 | *assembler_p = rotate_one[cpu][shift_type][shift_mode]; |
---|
2474 | if (TARGET_H8300S) |
---|
2475 | *assembler2_p = rotate_two[shift_type][shift_mode]; |
---|
2476 | else |
---|
2477 | *assembler2_p = NULL; |
---|
2478 | *cc_valid_p = 0; |
---|
2479 | return SHIFT_ROT_AND; |
---|
2480 | } |
---|
2481 | } |
---|
2482 | else if (count == 31) |
---|
2483 | { |
---|
2484 | if (shift_type == SHIFT_ASHIFTRT) |
---|
2485 | { |
---|
2486 | if (TARGET_H8300) |
---|
2487 | *assembler_p = "shll\t%z0\n\tsubx %w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0"; |
---|
2488 | else |
---|
2489 | *assembler_p = "shll\t%e0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0"; |
---|
2490 | *cc_valid_p = 0; |
---|
2491 | return SHIFT_SPECIAL; |
---|
2492 | } |
---|
2493 | else |
---|
2494 | { |
---|
2495 | if (TARGET_H8300) |
---|
2496 | { |
---|
2497 | if (shift_type == SHIFT_ASHIFT) |
---|
2498 | *assembler_p = "sub.w\t%e0,%e0\n\tshlr\t%w0\n\tmov.w\t%e0,%f0\n\trotxr\t%z0"; |
---|
2499 | else |
---|
2500 | *assembler_p = "sub.w\t%f0,%f0\n\tshll\t%z0\n\tmov.w\t%f0,%e0\n\trotxl\t%w0"; |
---|
2501 | *cc_valid_p = 0; |
---|
2502 | return SHIFT_SPECIAL; |
---|
2503 | } |
---|
2504 | else |
---|
2505 | { |
---|
2506 | *assembler_p = rotate_one[cpu][shift_type][shift_mode]; |
---|
2507 | if (TARGET_H8300S) |
---|
2508 | *assembler2_p = rotate_two[shift_type][shift_mode]; |
---|
2509 | else |
---|
2510 | *assembler2_p = NULL; |
---|
2511 | *cc_valid_p = 0; |
---|
2512 | return SHIFT_ROT_AND; |
---|
2513 | } |
---|
2514 | } |
---|
2515 | } |
---|
2516 | break; |
---|
2517 | |
---|
2518 | default: |
---|
2519 | abort (); |
---|
2520 | } |
---|
2521 | |
---|
2522 | return alg; |
---|
2523 | } |
---|
2524 | |
---|
2525 | /* Emit the assembler code for doing shifts. */ |
---|
2526 | |
---|
2527 | char * |
---|
2528 | emit_a_shift (insn, operands) |
---|
2529 | rtx insn; |
---|
2530 | rtx *operands; |
---|
2531 | { |
---|
2532 | static int loopend_lab; |
---|
2533 | char *assembler; |
---|
2534 | char *assembler2; |
---|
2535 | int cc_valid; |
---|
2536 | rtx inside = PATTERN (insn); |
---|
2537 | rtx shift = operands[3]; |
---|
2538 | enum machine_mode mode = GET_MODE (shift); |
---|
2539 | enum rtx_code code = GET_CODE (shift); |
---|
2540 | enum shift_type shift_type; |
---|
2541 | enum shift_mode shift_mode; |
---|
2542 | |
---|
2543 | loopend_lab++; |
---|
2544 | |
---|
2545 | switch (mode) |
---|
2546 | { |
---|
2547 | case QImode: |
---|
2548 | shift_mode = QIshift; |
---|
2549 | break; |
---|
2550 | case HImode: |
---|
2551 | shift_mode = HIshift; |
---|
2552 | break; |
---|
2553 | case SImode: |
---|
2554 | shift_mode = SIshift; |
---|
2555 | break; |
---|
2556 | default: |
---|
2557 | abort (); |
---|
2558 | } |
---|
2559 | |
---|
2560 | switch (code) |
---|
2561 | { |
---|
2562 | case ASHIFTRT: |
---|
2563 | shift_type = SHIFT_ASHIFTRT; |
---|
2564 | break; |
---|
2565 | case LSHIFTRT: |
---|
2566 | shift_type = SHIFT_LSHIFTRT; |
---|
2567 | break; |
---|
2568 | case ASHIFT: |
---|
2569 | shift_type = SHIFT_ASHIFT; |
---|
2570 | break; |
---|
2571 | default: |
---|
2572 | abort (); |
---|
2573 | } |
---|
2574 | |
---|
2575 | if (GET_CODE (operands[2]) != CONST_INT) |
---|
2576 | { |
---|
2577 | /* Indexing by reg, so have to loop and test at top */ |
---|
2578 | output_asm_insn ("mov.b %X2,%X4", operands); |
---|
2579 | fprintf (asm_out_file, "\tble .Lle%d\n", loopend_lab); |
---|
2580 | |
---|
2581 | /* Get the assembler code to do one shift. */ |
---|
2582 | get_shift_alg (cpu_type, shift_type, mode, 1, &assembler, |
---|
2583 | &assembler2, &cc_valid); |
---|
2584 | } |
---|
2585 | else |
---|
2586 | { |
---|
2587 | int n = INTVAL (operands[2]); |
---|
2588 | enum shift_alg alg; |
---|
2589 | |
---|
2590 | /* If the count is negative, make it 0. */ |
---|
2591 | if (n < 0) |
---|
2592 | n = 0; |
---|
2593 | /* If the count is too big, truncate it. |
---|
2594 | ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to |
---|
2595 | do the intuitive thing. */ |
---|
2596 | else if (n > GET_MODE_BITSIZE (mode)) |
---|
2597 | n = GET_MODE_BITSIZE (mode); |
---|
2598 | |
---|
2599 | alg = get_shift_alg (cpu_type, shift_type, mode, n, &assembler, |
---|
2600 | &assembler2, &cc_valid); |
---|
2601 | |
---|
2602 | switch (alg) |
---|
2603 | { |
---|
2604 | case SHIFT_INLINE: |
---|
2605 | /* Emit two bit shifts first. */ |
---|
2606 | while (n > 1 && assembler2 != NULL) |
---|
2607 | { |
---|
2608 | output_asm_insn (assembler2, operands); |
---|
2609 | n -= 2; |
---|
2610 | } |
---|
2611 | |
---|
2612 | /* Now emit one bit shifts for any residual. */ |
---|
2613 | while (n > 0) |
---|
2614 | { |
---|
2615 | output_asm_insn (assembler, operands); |
---|
2616 | n -= 1; |
---|
2617 | } |
---|
2618 | |
---|
2619 | /* Keep track of CC. */ |
---|
2620 | if (cc_valid) |
---|
2621 | { |
---|
2622 | cc_status.value1 = operands[0]; |
---|
2623 | cc_status.flags |= cc_valid; |
---|
2624 | } |
---|
2625 | return ""; |
---|
2626 | |
---|
2627 | case SHIFT_ROT_AND: |
---|
2628 | { |
---|
2629 | int m = GET_MODE_BITSIZE (mode) - n; |
---|
2630 | int mask = (shift_type == SHIFT_ASHIFT |
---|
2631 | ? ((1 << GET_MODE_BITSIZE (mode) - n) - 1) << n |
---|
2632 | : (1 << GET_MODE_BITSIZE (mode) - n) - 1); |
---|
2633 | char insn_buf[200]; |
---|
2634 | /* Not all possibilities of rotate are supported. They shouldn't |
---|
2635 | be generated, but let's watch for 'em. */ |
---|
2636 | if (assembler == 0) |
---|
2637 | abort (); |
---|
2638 | |
---|
2639 | /* Emit two bit rotates first. */ |
---|
2640 | while (m > 1 && assembler2 != NULL) |
---|
2641 | { |
---|
2642 | output_asm_insn (assembler2, operands); |
---|
2643 | m -= 2; |
---|
2644 | } |
---|
2645 | |
---|
2646 | /* Now single bit rotates for any residual. */ |
---|
2647 | while (m > 0) |
---|
2648 | { |
---|
2649 | output_asm_insn (assembler, operands); |
---|
2650 | m -= 1; |
---|
2651 | } |
---|
2652 | |
---|
2653 | /* Now mask off the high bits. */ |
---|
2654 | if (TARGET_H8300) |
---|
2655 | { |
---|
2656 | switch (mode) |
---|
2657 | { |
---|
2658 | case QImode: |
---|
2659 | sprintf (insn_buf, "and #%d,%%X0", |
---|
2660 | mask, n); |
---|
2661 | cc_status.value1 = operands[0]; |
---|
2662 | cc_status.flags |= CC_NO_CARRY; |
---|
2663 | break; |
---|
2664 | case HImode: |
---|
2665 | sprintf (insn_buf, "and #%d,%%s0\n\tand #%d,%%t0", |
---|
2666 | mask & 255, mask >> 8, n); |
---|
2667 | break; |
---|
2668 | case SImode: |
---|
2669 | abort (); |
---|
2670 | } |
---|
2671 | } |
---|
2672 | else |
---|
2673 | { |
---|
2674 | sprintf (insn_buf, "and.%c #%d,%%%c0", |
---|
2675 | "bwl"[shift_mode], mask, |
---|
2676 | mode == QImode ? 'X' : mode == HImode ? 'T' : 'S'); |
---|
2677 | cc_status.value1 = operands[0]; |
---|
2678 | cc_status.flags |= CC_NO_CARRY; |
---|
2679 | } |
---|
2680 | output_asm_insn (insn_buf, operands); |
---|
2681 | return ""; |
---|
2682 | } |
---|
2683 | case SHIFT_SPECIAL: |
---|
2684 | output_asm_insn (assembler, operands); |
---|
2685 | return ""; |
---|
2686 | } |
---|
2687 | |
---|
2688 | /* A loop to shift by a "large" constant value. |
---|
2689 | If we have shift-by-2 insns, use them. */ |
---|
2690 | if (assembler2 != NULL) |
---|
2691 | { |
---|
2692 | fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n / 2, |
---|
2693 | names_big[REGNO (operands[4])]); |
---|
2694 | fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); |
---|
2695 | output_asm_insn (assembler2, operands); |
---|
2696 | output_asm_insn ("add #0xff,%X4", operands); |
---|
2697 | fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); |
---|
2698 | if (n % 2) |
---|
2699 | output_asm_insn (assembler, operands); |
---|
2700 | return ""; |
---|
2701 | } |
---|
2702 | else |
---|
2703 | { |
---|
2704 | fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n, |
---|
2705 | names_big[REGNO (operands[4])]); |
---|
2706 | fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); |
---|
2707 | output_asm_insn (assembler, operands); |
---|
2708 | output_asm_insn ("add #0xff,%X4", operands); |
---|
2709 | fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); |
---|
2710 | return ""; |
---|
2711 | } |
---|
2712 | } |
---|
2713 | |
---|
2714 | fprintf (asm_out_file, ".Llt%d:\n", loopend_lab); |
---|
2715 | output_asm_insn (assembler, operands); |
---|
2716 | output_asm_insn ("add #0xff,%X4", operands); |
---|
2717 | fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab); |
---|
2718 | fprintf (asm_out_file, ".Lle%d:\n", loopend_lab); |
---|
2719 | |
---|
2720 | return ""; |
---|
2721 | } |
---|
2722 | |
---|
2723 | /* Fix the operands of a gen_xxx so that it could become a bit |
---|
2724 | operating insn. */ |
---|
2725 | |
---|
2726 | int |
---|
2727 | fix_bit_operand (operands, what, type) |
---|
2728 | rtx *operands; |
---|
2729 | char what; |
---|
2730 | enum rtx_code type; |
---|
2731 | { |
---|
2732 | /* The bit_operand predicate accepts any memory during RTL generation, but |
---|
2733 | only 'U' memory afterwards, so if this is a MEM operand, we must force |
---|
2734 | it to be valid for 'U' by reloading the address. */ |
---|
2735 | |
---|
2736 | if (GET_CODE (operands[2]) == CONST_INT) |
---|
2737 | { |
---|
2738 | if (CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), what)) |
---|
2739 | { |
---|
2740 | /* Ok to have a memory dest. */ |
---|
2741 | if (GET_CODE (operands[0]) == MEM && !EXTRA_CONSTRAINT (operands[0], 'U')) |
---|
2742 | { |
---|
2743 | rtx mem; |
---|
2744 | mem = gen_rtx (MEM, GET_MODE (operands[0]), |
---|
2745 | copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); |
---|
2746 | RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[0]); |
---|
2747 | MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[0]); |
---|
2748 | MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[0]); |
---|
2749 | operands[0] = mem; |
---|
2750 | } |
---|
2751 | |
---|
2752 | if (GET_CODE (operands[1]) == MEM && !EXTRA_CONSTRAINT (operands[1], 'U')) |
---|
2753 | { |
---|
2754 | rtx mem; |
---|
2755 | mem = gen_rtx (MEM, GET_MODE (operands[1]), |
---|
2756 | copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); |
---|
2757 | RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[1]); |
---|
2758 | MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[1]); |
---|
2759 | MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[1]); |
---|
2760 | operands[1] = mem; |
---|
2761 | } |
---|
2762 | return 0; |
---|
2763 | } |
---|
2764 | } |
---|
2765 | |
---|
2766 | /* Dest and src op must be register. */ |
---|
2767 | |
---|
2768 | operands[1] = force_reg (QImode, operands[1]); |
---|
2769 | { |
---|
2770 | rtx res = gen_reg_rtx (QImode); |
---|
2771 | emit_insn (gen_rtx (SET, VOIDmode, res, gen_rtx (type, QImode, operands[1], operands[2]))); |
---|
2772 | emit_insn (gen_rtx (SET, VOIDmode, operands[0], res)); |
---|
2773 | } |
---|
2774 | return 1; |
---|
2775 | } |
---|
2776 | |
---|
2777 | /* Return nonzero if FUNC is an interrupt function as specified |
---|
2778 | by the "interrupt" attribute. */ |
---|
2779 | |
---|
2780 | static int |
---|
2781 | h8300_interrupt_function_p (func) |
---|
2782 | tree func; |
---|
2783 | { |
---|
2784 | tree a; |
---|
2785 | |
---|
2786 | if (TREE_CODE (func) != FUNCTION_DECL) |
---|
2787 | return 0; |
---|
2788 | |
---|
2789 | a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func)); |
---|
2790 | return a != NULL_TREE; |
---|
2791 | } |
---|
2792 | |
---|
2793 | /* Return nonzero if FUNC is an OS_Task function as specified |
---|
2794 | by the "OS_Task" attribute. */ |
---|
2795 | |
---|
2796 | static int |
---|
2797 | h8300_os_task_function_p (func) |
---|
2798 | tree func; |
---|
2799 | { |
---|
2800 | tree a; |
---|
2801 | |
---|
2802 | if (TREE_CODE (func) != FUNCTION_DECL) |
---|
2803 | return 0; |
---|
2804 | |
---|
2805 | a = lookup_attribute ("OS_Task", DECL_MACHINE_ATTRIBUTES (func)); |
---|
2806 | return a != NULL_TREE; |
---|
2807 | } |
---|
2808 | |
---|
2809 | /* Return nonzero if FUNC is a monitor function as specified |
---|
2810 | by the "monitor" attribute. */ |
---|
2811 | |
---|
2812 | static int |
---|
2813 | h8300_monitor_function_p (func) |
---|
2814 | tree func; |
---|
2815 | { |
---|
2816 | tree a; |
---|
2817 | |
---|
2818 | if (TREE_CODE (func) != FUNCTION_DECL) |
---|
2819 | return 0; |
---|
2820 | |
---|
2821 | a = lookup_attribute ("monitor", DECL_MACHINE_ATTRIBUTES (func)); |
---|
2822 | return a != NULL_TREE; |
---|
2823 | } |
---|
2824 | |
---|
2825 | /* Return nonzero if FUNC is a function that should be called |
---|
2826 | through the function vector. */ |
---|
2827 | |
---|
2828 | int |
---|
2829 | h8300_funcvec_function_p (func) |
---|
2830 | tree func; |
---|
2831 | { |
---|
2832 | tree a; |
---|
2833 | |
---|
2834 | if (TREE_CODE (func) != FUNCTION_DECL) |
---|
2835 | return 0; |
---|
2836 | |
---|
2837 | a = lookup_attribute ("function_vector", DECL_MACHINE_ATTRIBUTES (func)); |
---|
2838 | return a != NULL_TREE; |
---|
2839 | } |
---|
2840 | |
---|
2841 | /* Return nonzero if DECL is a variable that's in the eight bit |
---|
2842 | data area. */ |
---|
2843 | |
---|
2844 | int |
---|
2845 | h8300_eightbit_data_p (decl) |
---|
2846 | tree decl; |
---|
2847 | { |
---|
2848 | tree a; |
---|
2849 | |
---|
2850 | if (TREE_CODE (decl) != VAR_DECL) |
---|
2851 | return 0; |
---|
2852 | |
---|
2853 | a = lookup_attribute ("eightbit_data", DECL_MACHINE_ATTRIBUTES (decl)); |
---|
2854 | return a != NULL_TREE; |
---|
2855 | } |
---|
2856 | |
---|
2857 | /* Return nonzero if DECL is a variable that's in the tiny |
---|
2858 | data area. */ |
---|
2859 | |
---|
2860 | int |
---|
2861 | h8300_tiny_data_p (decl) |
---|
2862 | tree decl; |
---|
2863 | { |
---|
2864 | tree a; |
---|
2865 | |
---|
2866 | if (TREE_CODE (decl) != VAR_DECL) |
---|
2867 | return 0; |
---|
2868 | |
---|
2869 | a = lookup_attribute ("tiny_data", DECL_MACHINE_ATTRIBUTES (decl)); |
---|
2870 | return a != NULL_TREE; |
---|
2871 | } |
---|
2872 | |
---|
2873 | /* Return nonzero if ATTR is a valid attribute for DECL. |
---|
2874 | ATTRIBUTES are any existing attributes and ARGS are the arguments |
---|
2875 | supplied with ATTR. |
---|
2876 | |
---|
2877 | Supported attributes: |
---|
2878 | |
---|
2879 | interrupt_handler: output a prologue and epilogue suitable for an |
---|
2880 | interrupt handler. |
---|
2881 | |
---|
2882 | function_vector: This function should be called through the |
---|
2883 | function vector. |
---|
2884 | |
---|
2885 | eightbit_data: This variable lives in the 8-bit data area and can |
---|
2886 | be referenced with 8-bit absolute memory addresses. |
---|
2887 | |
---|
2888 | tiny_data: This variable lives in the tiny data area and can be |
---|
2889 | referenced with 16-bit absolute memory references. */ |
---|
2890 | |
---|
2891 | int |
---|
2892 | h8300_valid_machine_decl_attribute (decl, attributes, attr, args) |
---|
2893 | tree decl; |
---|
2894 | tree attributes; |
---|
2895 | tree attr; |
---|
2896 | tree args; |
---|
2897 | { |
---|
2898 | if (args != NULL_TREE) |
---|
2899 | return 0; |
---|
2900 | |
---|
2901 | if (is_attribute_p ("interrupt_handler", attr) |
---|
2902 | || is_attribute_p ("OS_Task", attr) |
---|
2903 | || is_attribute_p ("monitor", attr) |
---|
2904 | || is_attribute_p ("function_vector", attr)) |
---|
2905 | return TREE_CODE (decl) == FUNCTION_DECL; |
---|
2906 | |
---|
2907 | if (is_attribute_p ("eightbit_data", attr) |
---|
2908 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) |
---|
2909 | { |
---|
2910 | if (DECL_INITIAL (decl) == NULL_TREE) |
---|
2911 | { |
---|
2912 | warning ("Only initialized variables can be placed into the 8-bit area."); |
---|
2913 | return 0; |
---|
2914 | } |
---|
2915 | DECL_SECTION_NAME (decl) = build_string (7, ".eight"); |
---|
2916 | return 1; |
---|
2917 | } |
---|
2918 | |
---|
2919 | if (is_attribute_p ("tiny_data", attr) |
---|
2920 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) |
---|
2921 | { |
---|
2922 | if (DECL_INITIAL (decl) == NULL_TREE) |
---|
2923 | { |
---|
2924 | warning ("Only initialized variables can be placed into the 8-bit area."); |
---|
2925 | return 0; |
---|
2926 | } |
---|
2927 | DECL_SECTION_NAME (decl) = build_string (6, ".tiny"); |
---|
2928 | return 1; |
---|
2929 | } |
---|
2930 | |
---|
2931 | return 0; |
---|
2932 | } |
---|
2933 | |
---|
2934 | extern struct obstack *saveable_obstack; |
---|
2935 | |
---|
2936 | h8300_encode_label (decl) |
---|
2937 | tree decl; |
---|
2938 | { |
---|
2939 | char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0); |
---|
2940 | int len = strlen (str); |
---|
2941 | char *newstr; |
---|
2942 | |
---|
2943 | newstr = obstack_alloc (saveable_obstack, len + 2); |
---|
2944 | |
---|
2945 | strcpy (newstr + 1, str); |
---|
2946 | *newstr = '*'; |
---|
2947 | XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr; |
---|
2948 | } |
---|
2949 | |
---|
2950 | char * |
---|
2951 | output_simode_bld (bild, log2, operands) |
---|
2952 | int bild; |
---|
2953 | int log2; |
---|
2954 | rtx operands[]; |
---|
2955 | { |
---|
2956 | /* Clear the destination register. */ |
---|
2957 | if (TARGET_H8300H || TARGET_H8300S) |
---|
2958 | output_asm_insn ("sub.l\t%S0,%S0", operands); |
---|
2959 | else |
---|
2960 | output_asm_insn ("sub.w\t%e0,%e0\n\tsub.w\t%f0,%f0", operands); |
---|
2961 | |
---|
2962 | /* Get the bit number we want to load. */ |
---|
2963 | if (log2) |
---|
2964 | operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2]))); |
---|
2965 | |
---|
2966 | /* Now output the bit load or bit inverse load, and store it in |
---|
2967 | the destination. */ |
---|
2968 | if (bild) |
---|
2969 | output_asm_insn ("bild\t%Z2,%Y1\n\tbst\t#0,%w0", operands); |
---|
2970 | else |
---|
2971 | output_asm_insn ("bld\t%Z2,%Y1\n\tbst\t#0,%w0", operands); |
---|
2972 | |
---|
2973 | /* All done. */ |
---|
2974 | return ""; |
---|
2975 | } |
---|
2976 | |
---|
2977 | /* Given INSN and it's current length LENGTH, return the adjustment |
---|
2978 | (in bytes) to correctly compute INSN's length. |
---|
2979 | |
---|
2980 | We use this to get the lengths of various memory references correct. */ |
---|
2981 | |
---|
2982 | h8300_adjust_insn_length (insn, length) |
---|
2983 | rtx insn; |
---|
2984 | int length; |
---|
2985 | { |
---|
2986 | rtx pat = PATTERN (insn); |
---|
2987 | |
---|
2988 | /* Adjust length for reg->mem and mem->reg copies. */ |
---|
2989 | if (GET_CODE (pat) == SET |
---|
2990 | && (GET_CODE (SET_SRC (pat)) == MEM |
---|
2991 | || GET_CODE (SET_DEST (pat)) == MEM)) |
---|
2992 | { |
---|
2993 | /* This insn might need a length adjustment. */ |
---|
2994 | rtx addr; |
---|
2995 | |
---|
2996 | if (GET_CODE (SET_SRC (pat)) == MEM) |
---|
2997 | addr = XEXP (SET_SRC (pat), 0); |
---|
2998 | else |
---|
2999 | addr = XEXP (SET_DEST (pat), 0); |
---|
3000 | |
---|
3001 | /* On the H8/300, only one adjustment is necessary; if the |
---|
3002 | address mode is register indirect, then this insn is two |
---|
3003 | bytes shorter than indicated in the machine description. */ |
---|
3004 | if (TARGET_H8300 && GET_CODE (addr) == REG) |
---|
3005 | return -2; |
---|
3006 | |
---|
3007 | /* On the H8/300H and H8/S, register indirect is 6 bytes shorter than |
---|
3008 | indicated in the machine description. */ |
---|
3009 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
3010 | && GET_CODE (addr) == REG) |
---|
3011 | return -6; |
---|
3012 | |
---|
3013 | /* On the H8/300H and H8/300S, reg + d, for small displacements is 4 |
---|
3014 | bytes shorter than indicated in the machine description. */ |
---|
3015 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
3016 | && GET_CODE (addr) == PLUS |
---|
3017 | && GET_CODE (XEXP (addr, 0)) == REG |
---|
3018 | && GET_CODE (XEXP (addr, 1)) == CONST_INT |
---|
3019 | && INTVAL (XEXP (addr, 1)) > -32768 |
---|
3020 | && INTVAL (XEXP (addr, 1)) < 32767) |
---|
3021 | return -4; |
---|
3022 | |
---|
3023 | /* On the H8/300H and H8/300S, abs:16 is two bytes shorter than the |
---|
3024 | more general abs:24. */ |
---|
3025 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
3026 | && GET_CODE (addr) == SYMBOL_REF |
---|
3027 | && TINY_DATA_NAME_P (XSTR (addr, 0))) |
---|
3028 | return -2; |
---|
3029 | } |
---|
3030 | |
---|
3031 | /* Loading some constants needs adjustment. */ |
---|
3032 | if (GET_CODE (pat) == SET |
---|
3033 | && GET_CODE (SET_SRC (pat)) == CONST_INT |
---|
3034 | && GET_MODE (SET_DEST (pat)) == SImode |
---|
3035 | && INTVAL (SET_SRC (pat)) != 0) |
---|
3036 | { |
---|
3037 | if (TARGET_H8300 |
---|
3038 | && ((INTVAL (SET_SRC (pat)) & 0xffff) == 0 |
---|
3039 | || ((INTVAL (SET_SRC (pat)) >> 16) & 0xffff) == 0)) |
---|
3040 | return -2; |
---|
3041 | |
---|
3042 | if (TARGET_H8300H || TARGET_H8300S) |
---|
3043 | { |
---|
3044 | int val = INTVAL (SET_SRC (pat)); |
---|
3045 | |
---|
3046 | if (val == (val & 0xff) |
---|
3047 | || val == (val & 0xff00)) |
---|
3048 | return -6; |
---|
3049 | |
---|
3050 | if (val == -4 || val == -2 || val == -1) |
---|
3051 | return -6; |
---|
3052 | } |
---|
3053 | } |
---|
3054 | |
---|
3055 | /* Shifts need various adjustments. */ |
---|
3056 | if (GET_CODE (pat) == PARALLEL |
---|
3057 | && GET_CODE (XVECEXP (pat, 0, 0)) == SET |
---|
3058 | && (GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFTRT |
---|
3059 | || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == LSHIFTRT |
---|
3060 | || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFT)) |
---|
3061 | { |
---|
3062 | rtx src = SET_SRC (XVECEXP (pat, 0, 0)); |
---|
3063 | enum machine_mode mode = GET_MODE (src); |
---|
3064 | |
---|
3065 | if (GET_CODE (XEXP (src, 1)) != CONST_INT) |
---|
3066 | return 0; |
---|
3067 | |
---|
3068 | /* QImode shifts by small constants take one insn |
---|
3069 | per shift. So the adjustment is 20 (md length) - |
---|
3070 | # shifts * 2. */ |
---|
3071 | if (mode == QImode && INTVAL (XEXP (src, 1)) <= 4) |
---|
3072 | return -(20 - INTVAL (XEXP (src, 1)) * 2); |
---|
3073 | |
---|
3074 | /* Similarly for HImode and SImode shifts by |
---|
3075 | small constants on the H8/300H and H8/300S. */ |
---|
3076 | if ((TARGET_H8300H || TARGET_H8300S) |
---|
3077 | && (mode == HImode || mode == SImode) |
---|
3078 | && INTVAL (XEXP (src, 1)) <= 4) |
---|
3079 | return -(20 - INTVAL (XEXP (src, 1)) * 2); |
---|
3080 | |
---|
3081 | /* HImode shifts by small constants for the H8/300. */ |
---|
3082 | if (mode == HImode |
---|
3083 | && INTVAL (XEXP (src, 1)) <= 4) |
---|
3084 | return -(20 - (INTVAL (XEXP (src, 1)) |
---|
3085 | * (GET_CODE (src) == ASHIFT ? 2 : 4))); |
---|
3086 | |
---|
3087 | /* SImode shifts by small constants for the H8/300. */ |
---|
3088 | if (mode == SImode |
---|
3089 | && INTVAL (XEXP (src, 1)) <= 2) |
---|
3090 | return -(20 - (INTVAL (XEXP (src, 1)) |
---|
3091 | * (GET_CODE (src) == ASHIFT ? 6 : 8))); |
---|
3092 | |
---|
3093 | /* XXX ??? Could check for more shift/rotate cases here. */ |
---|
3094 | } |
---|
3095 | |
---|
3096 | return 0; |
---|
3097 | } |
---|