Mercurial > hg > index.cgi
comparison extra/gcc6809lw-4.6.4-1.patch @ 340:b0fb675d1ed4
Add gcc 4.6.4 version of gcc6809
Make a copy of the gcc 4.6.1 patch labelled for 4.6.4 since it does build.
Also update the gcc6809 notes to mention that a patch for earlier minor
revisions may work for later ones in the same release stream.
author | William Astle <lost@l-w.ca> |
---|---|
date | Wed, 01 Oct 2014 09:25:13 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
339:6138e304ab9a | 340:b0fb675d1ed4 |
---|---|
1 diff -urN gcc-4.6.1-orig/config.sub gcc-4.6.1/config.sub | |
2 --- gcc-4.6.1-orig/config.sub 2010-05-25 07:22:07.000000000 -0600 | |
3 +++ gcc-4.6.1/config.sub 2011-09-17 14:07:51.597643628 -0600 | |
4 @@ -313,7 +313,7 @@ | |
5 c6x) | |
6 basic_machine=tic6x-unknown | |
7 ;; | |
8 - m6811 | m68hc11 | m6812 | m68hc12 | picochip) | |
9 + m6809 | m6811 | m68hc11 | m6812 | m68hc12 | picochip) | |
10 # Motorola 68HC11/12. | |
11 basic_machine=$basic_machine-unknown | |
12 os=-none | |
13 @@ -354,7 +354,7 @@ | |
14 | i*86-* | i860-* | i960-* | ia64-* \ | |
15 | ip2k-* | iq2000-* \ | |
16 | lm32-* \ | |
17 - | m32c-* | m32r-* | m32rle-* \ | |
18 + | m32c-* | m32r-* | m32rle-* | m6809-* \ | |
19 | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | |
20 | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | |
21 | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | |
22 @@ -509,6 +509,10 @@ | |
23 basic_machine=arm-unknown | |
24 os=-cegcc | |
25 ;; | |
26 + coco) | |
27 + basic_machine=coco | |
28 + os=-none | |
29 + ;; | |
30 convex-c1) | |
31 basic_machine=c1-convex | |
32 os=-bsd | |
33 diff -urN gcc-4.6.1-orig/configure gcc-4.6.1/configure | |
34 --- gcc-4.6.1-orig/configure 2011-03-16 12:27:36.000000000 -0600 | |
35 +++ gcc-4.6.1/configure 2011-09-17 14:06:01.187643616 -0600 | |
36 @@ -3441,6 +3441,9 @@ | |
37 m32r-*-*) | |
38 noconfigdirs="$noconfigdirs ${libgcj}" | |
39 ;; | |
40 + m6809*) | |
41 + noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 target-libgloss ${libgcj}" | |
42 + ;; | |
43 m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*) | |
44 noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}" | |
45 libgloss_dir=m68hc11 | |
46 diff -urN gcc-4.6.1-orig/configure.ac gcc-4.6.1/configure.ac | |
47 --- gcc-4.6.1-orig/configure.ac 2011-03-16 12:27:36.000000000 -0600 | |
48 +++ gcc-4.6.1/configure.ac 2011-09-17 14:06:01.187643616 -0600 | |
49 @@ -887,6 +887,9 @@ | |
50 m32r-*-*) | |
51 noconfigdirs="$noconfigdirs ${libgcj}" | |
52 ;; | |
53 + m6809*) | |
54 + noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 target-libgloss ${libgcj}" | |
55 + ;; | |
56 m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*) | |
57 noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}" | |
58 libgloss_dir=m68hc11 | |
59 diff -urN gcc-4.6.1-orig/gcc/calls.c gcc-4.6.1/gcc/calls.c | |
60 --- gcc-4.6.1-orig/gcc/calls.c 2011-06-06 05:46:14.000000000 -0600 | |
61 +++ gcc-4.6.1/gcc/calls.c 2011-09-17 14:06:01.217643616 -0600 | |
62 @@ -2434,7 +2434,7 @@ | |
63 call sequence. | |
64 Also do the adjustments before a throwing call, otherwise | |
65 exception handling can fail; PR 19225. */ | |
66 - if (pending_stack_adjust >= 32 | |
67 + if (pending_stack_adjust >= 8 | |
68 || (pending_stack_adjust > 0 | |
69 && (flags & ECF_MAY_BE_ALLOCA)) | |
70 || (pending_stack_adjust > 0 | |
71 diff -urN gcc-4.6.1-orig/gcc/config/m6809/crt0.S gcc-4.6.1/gcc/config/m6809/crt0.S | |
72 --- gcc-4.6.1-orig/gcc/config/m6809/crt0.S 1969-12-31 17:00:00.000000000 -0700 | |
73 +++ gcc-4.6.1/gcc/config/m6809/crt0.S 2011-09-17 14:06:01.227643616 -0600 | |
74 @@ -0,0 +1,180 @@ | |
75 +;;; | |
76 +;;; Copyright 2006, 2007, 2008, 2009 by Brian Dominy <brian@oddchange.com> | |
77 +;;; | |
78 +;;; This file is part of GCC. | |
79 +;;; | |
80 +;;; GCC is free software; you can redistribute it and/or modify | |
81 +;;; it under the terms of the GNU General Public License as published by | |
82 +;;; the Free Software Foundation; either version 3, or (at your option) | |
83 +;;; any later version. | |
84 +;;; | |
85 +;;; GCC is distributed in the hope that it will be useful, | |
86 +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
87 +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
88 +;;; GNU General Public License for more details. | |
89 + | |
90 +;;; You should have received a copy of the GNU General Public License | |
91 +;;; along with GCC; see the file COPYING3. If not see | |
92 +;;; <http://www.gnu.org/licenses/>. | |
93 + | |
94 + /* Declare external for main() */ | |
95 + .globl _main | |
96 + | |
97 + | |
98 +/* The startup is heavily dependent on the type of machine and | |
99 +OS environment that is available at the start point. | |
100 +For the most part, the general idea is the same across machines, | |
101 +but the implementation is vastly different. This is managed via | |
102 +conditional compiles throughout the startup code for each of the | |
103 +supported machines. */ | |
104 + | |
105 +#ifdef TARGET_COCO /* CoCo memory map */ | |
106 + | |
107 +#define COCO_RAMROM_MODE 0xFFDE | |
108 +#define COCO_ALLRAM_MODE 0xFFDF | |
109 +#define COCO_PAGE1 0xFFD5 | |
110 + | |
111 +/* SAM M1 and M0 adjusts the memory size */ | |
112 + | |
113 +#define BASIC_WARMSTART_FLAG 0x0071 | |
114 +#define BASIC_START 0xA027 | |
115 + | |
116 +#define __STACK_TOP 0x6800 | |
117 + | |
118 +#else /* Simulator (default) memory map */ | |
119 + | |
120 +#define SIM_EXIT_REG 0xFF01 | |
121 + | |
122 +#define __STACK_TOP 0xFE00 | |
123 + | |
124 +#endif | |
125 + | |
126 + | |
127 + /* Declare all linker sections, and combine them into a single bank */ | |
128 + .bank prog | |
129 + .area .text (BANK=prog) | |
130 + .area .data (BANK=prog) | |
131 + .area .ctors (BANK=prog) | |
132 + .word 0 | |
133 + .area .dtors (BANK=prog) | |
134 + .word 0 | |
135 + .area .bss (BANK=prog) | |
136 + | |
137 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
138 + ;;; | |
139 + ;;; __exit : Exit point from the program | |
140 + ;;; For simulation, this writes to a special I/O register that | |
141 + ;;; the simulator interprets as end-of-program. | |
142 + ;;; | |
143 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
144 + .area .text | |
145 + .globl __exit | |
146 +__exit: | |
147 +#ifdef TARGET_COCO | |
148 + ;; Go back to ROM/RAM mode | |
149 + sta COCO_RAMROM_MODE | |
150 + clr BASIC_WARMSTART_FLAG | |
151 + jmp BASIC_START | |
152 +#else | |
153 + tfr x,d | |
154 + stb SIM_EXIT_REG | |
155 + bra __exit | |
156 +#endif | |
157 + | |
158 + | |
159 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
160 + ;;; | |
161 + ;;; __start : Entry point to the program | |
162 + ;;; | |
163 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
164 + .area .text | |
165 + .globl __start | |
166 +__start: | |
167 + | |
168 +#ifdef HAVE_DIRECT | |
169 + ;; Initialize the direct page pointer | |
170 + lda #<s_.direct | |
171 + tfr a,dp | |
172 +#endif | |
173 + | |
174 +#ifdef TARGET_COCO | |
175 + ;; Turn off interrupts | |
176 + orcc #(0x10|0x40) | |
177 + | |
178 + ;; Setup All RAM Mode | |
179 + sta COCO_ALLRAM_MODE | |
180 +#endif /* TARGET_COCO */ | |
181 + | |
182 + ;; Initialize the stack | |
183 + lds #__STACK_TOP - 2 | |
184 + | |
185 + ;; Call any "initializer" functions | |
186 + ldu #s_.ctors | |
187 +__ctors_loop: | |
188 + ldy ,u++ | |
189 + cmpy #0 | |
190 + beq __ctors_done | |
191 + jsr ,y | |
192 + bra __ctors_loop | |
193 +__ctors_done: | |
194 + | |
195 + ;; Enable interrupts on the simulator | |
196 +#ifndef TARGET_COCO | |
197 + andcc #~(0x10|0x40) | |
198 +#endif | |
199 + | |
200 + ;; Set up the environment | |
201 + | |
202 + ;; Set up argc/argv arrays | |
203 + | |
204 + ;; Call the main function. The exit code will | |
205 + ;; be returned in the X register, unless compiled | |
206 + ;; with -mdret, in which case it comes back in D. | |
207 + jsr _main | |
208 + | |
209 + ;; Call any finalizer functions | |
210 + ldu #s_.dtors | |
211 +__dtors_loop: | |
212 + ldy ,u++ | |
213 + cmpy #0 | |
214 + beq __dtors_done | |
215 + jsr ,y | |
216 + bra __dtors_loop | |
217 +__dtors_done: | |
218 + | |
219 + ;; If main returns, then invoke _exit() to stop the program | |
220 + ;; The C library doesn't support -mdret yet, so move the | |
221 + ;; argument first. | |
222 +#ifdef __DRET__ | |
223 + tfr d,x | |
224 +#endif | |
225 + jmp _exit | |
226 + | |
227 + | |
228 + | |
229 + ;;; | |
230 + ;;; __crt0_vector : Default handler for interrupts | |
231 + ;;; | |
232 + .area .text | |
233 +___crt0_vector: | |
234 + ;; The default behavior is to simply ignore all | |
235 + ;; non-reset interrupts. | |
236 + rti | |
237 + | |
238 + | |
239 + ;;; | |
240 + ;;; vector : The interrupt vector table | |
241 + ;;; The linker will ensure that this gets loaded at address 0xFFF0. | |
242 + ;;; | |
243 + .area vector | |
244 +vectors: | |
245 + .word ___crt0_vector | |
246 + .word ___crt0_vector | |
247 + .word ___crt0_vector | |
248 + .word ___crt0_vector | |
249 + .word ___crt0_vector | |
250 + .word ___crt0_vector | |
251 + .word ___crt0_vector | |
252 + .word __start | |
253 + | |
254 + .end __start | |
255 diff -urN gcc-4.6.1-orig/gcc/config/m6809/libgcc1.s gcc-4.6.1/gcc/config/m6809/libgcc1.s | |
256 --- gcc-4.6.1-orig/gcc/config/m6809/libgcc1.s 1969-12-31 17:00:00.000000000 -0700 | |
257 +++ gcc-4.6.1/gcc/config/m6809/libgcc1.s 2011-09-17 14:06:01.227643616 -0600 | |
258 @@ -0,0 +1,511 @@ | |
259 +/* libgcc routines for m6809 | |
260 + Copyright (C) 2006 Free Software Foundation, Inc. | |
261 + | |
262 +This file is part of GCC. | |
263 + | |
264 +GCC is free software; you can redistribute it and/or modify | |
265 +it under the terms of the GNU General Public License as published by | |
266 +the Free Software Foundation; either version 3, or (at your option) | |
267 +any later version. | |
268 + | |
269 +GCC is distributed in the hope that it will be useful, | |
270 +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
271 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
272 +GNU General Public License for more details. | |
273 + | |
274 +You should have received a copy of the GNU General Public License | |
275 +along with GCC; see the file COPYING3. If not see | |
276 +<http://www.gnu.org/licenses/>. */ | |
277 + | |
278 +/* As a special exception, if you link this library with other files, | |
279 + some of which are compiled with GCC, to produce an executable, | |
280 + this library does not by itself cause the resulting executable | |
281 + to be covered by the GNU General Public License. | |
282 + This exception does not however invalidate any other reasons why | |
283 + the executable file might be covered by the GNU General Public License. */ | |
284 + | |
285 + | |
286 +#define SIGFPE jmp _abort | |
287 + | |
288 + | |
289 + ; Shift functions | |
290 + ; On input, D is value to be shifted, and X has shift count. | |
291 + ; Result is also in D. | |
292 + | |
293 +#ifdef L_ashlhi3 | |
294 + .area .text | |
295 + .globl _ashlhi3 | |
296 +_ashlhi3: | |
297 + pshs x | |
298 +1$: | |
299 + leax -1,x | |
300 + cmpx #-1 | |
301 + beq 2$ | |
302 + aslb | |
303 + rola | |
304 + bra 1$ | |
305 +2$: | |
306 + puls x,pc | |
307 +#endif | |
308 + | |
309 +#ifdef L_ashrhi3 | |
310 + .area .text | |
311 + .globl _ashrhi3 | |
312 +_ashrhi3: | |
313 + pshs x | |
314 +1$: | |
315 + leax -1,x | |
316 + cmpx #-1 | |
317 + beq 2$ | |
318 + asra | |
319 + rorb | |
320 + bra 1$ | |
321 +2$: | |
322 + puls x,pc | |
323 +#endif | |
324 + | |
325 + | |
326 +#ifdef L_lshrhi3 | |
327 + .area .text | |
328 + .globl _lshrhi3 | |
329 +_lshrhi3: | |
330 + pshs x | |
331 +1$: | |
332 + leax -1,x | |
333 + cmpx #-1 | |
334 + beq 2$ | |
335 + lsra | |
336 + rorb | |
337 + bra 1$ | |
338 +2$: | |
339 + puls x,pc | |
340 +#endif | |
341 + | |
342 + | |
343 + | |
344 +#ifdef L_softregs | |
345 + .area direct | |
346 + .globl m0, m1, m2, m3, m4, m5, m6, m7 | |
347 + .globl m8, m9, m10, m11, m12, m13, m14, m15 | |
348 +m0: .blkb 1 | |
349 +m1: .blkb 1 | |
350 +m2: .blkb 1 | |
351 +m3: .blkb 1 | |
352 +m4: .blkb 1 | |
353 +m5: .blkb 1 | |
354 +m6: .blkb 1 | |
355 +m7: .blkb 1 | |
356 +m8: .blkb 1 | |
357 +m9: .blkb 1 | |
358 +m10: .blkb 1 | |
359 +m11: .blkb 1 | |
360 +m12: .blkb 1 | |
361 +m13: .blkb 1 | |
362 +m14: .blkb 1 | |
363 +m15: .blkb 1 | |
364 +#endif | |
365 + | |
366 + | |
367 +#ifdef L_ashlsi3_one | |
368 + .area .text | |
369 + .globl _ashlsi3_one | |
370 +_ashlsi3_one: | |
371 + asl 3,x | |
372 + rol 2,x | |
373 + rol 1,x | |
374 + rol ,x | |
375 + rts | |
376 +#endif | |
377 + | |
378 +#ifdef L_ashlsi3 | |
379 + /* X points to the SImode (source/dest) | |
380 + B is the count */ | |
381 +_ashlsi3: | |
382 + pshs u | |
383 + cmpb #16 | |
384 + blt try8 | |
385 + subb #16 | |
386 + ; Shift by 16 | |
387 + ldu 2,x | |
388 + stu ,x | |
389 +try8: | |
390 + cmpb #8 | |
391 + blt try_rest | |
392 + subb #8 | |
393 + ; Shift by 8 | |
394 + | |
395 +try_rest: | |
396 + tstb | |
397 + beq done | |
398 +do_rest: | |
399 + ; Shift by 1 | |
400 + asl 3,x | |
401 + rol 2,x | |
402 + rol 1,x | |
403 + rol ,x | |
404 + decb | |
405 + bne do_rest | |
406 +done: | |
407 + puls u,pc | |
408 +#endif | |
409 + | |
410 +#ifdef L_ashrsi3_one | |
411 + .area .text | |
412 + .globl _ashlsi3_one | |
413 +_ashrsi3_one: | |
414 + asr ,x | |
415 + ror 1,x | |
416 + ror 2,x | |
417 + ror 3,x | |
418 + rts | |
419 +#endif | |
420 + | |
421 + | |
422 +#ifdef L_lshrsi3_one | |
423 + .area .text | |
424 + .globl _lshrsi3_one | |
425 +_lshrsi3_one: | |
426 + lsr ,x | |
427 + ror 1,x | |
428 + ror 2,x | |
429 + ror 3,x | |
430 + rts | |
431 +#endif | |
432 + | |
433 + | |
434 +#ifdef L_clzsi2 | |
435 + .area .text | |
436 + .globl ___clzhi2 | |
437 + ; Input: X = 16-bit unsigned integer | |
438 + ; Output: X = number of leading zeros | |
439 + ; This function destroys the value in D. | |
440 +___clzhi2: | |
441 + pshs x | |
442 + ; Find the offset of the leftmost '1' bit in | |
443 + ; the left half of the word. | |
444 + ; | |
445 + ; Bits are numbered in the table with 1 meaning the | |
446 + ; LSB and 8 meaning the MSB. | |
447 + ; | |
448 + ; If nonzero, then clz is 8-a. | |
449 + tfr x,d | |
450 + ldx #___clz_tab | |
451 + tfr a,b | |
452 + clra | |
453 + ldb d,x | |
454 + bne upper_bit_set | |
455 + | |
456 +lower_bit_set: | |
457 + ; If the upper byte is zero, then check the lower | |
458 + ; half of the word. Return 16-a. | |
459 + puls d | |
460 + clra | |
461 + ldb d,x | |
462 + negb | |
463 + addb #16 | |
464 + bra done | |
465 + | |
466 +upper_bit_set: | |
467 + negb | |
468 + addb #8 | |
469 + puls x | |
470 + | |
471 +done: | |
472 + tfr d,x | |
473 + puls pc | |
474 +#endif | |
475 + | |
476 +#ifdef L_clzdi2 | |
477 + .area .text | |
478 + .globl ___clzsi2 | |
479 + ; Input: 32-bit unsigned integer is on the stack, just | |
480 + ; above the return address | |
481 + ; Output: X = number of leading zeros | |
482 +___clzsi2: | |
483 + ; Check the upper 16-bit word | |
484 + ; If it is not zero, then return clzhi2(X). | |
485 + ; A branch can be used instead of a call since no | |
486 + ; postprocessing is needed. Use long branch form | |
487 + ; though since functions may not be near each other. | |
488 + ldx 2,s | |
489 + lbne ___clzhi2 | |
490 + ldx 4,s | |
491 + jsr ___clzhi2 | |
492 + leax 16,x | |
493 + rts | |
494 +#endif | |
495 + | |
496 +#ifdef L_ctzsi2 | |
497 + .area .text | |
498 + .globl ___ctzhi2 | |
499 + ; Input: X = 16-bit unsigned integer | |
500 + ; Output: X = number of trailing zeros | |
501 + ; F(x) = 15 - clzhi2(X & -x) | |
502 + ; This function destroys the value in D. | |
503 +___ctzhi2: | |
504 + tfr x,d | |
505 + coma | |
506 + comb | |
507 + addd #1 | |
508 + pshs a | |
509 + pshs b | |
510 + tfr x,d | |
511 + andb ,s+ | |
512 + anda ,s+ | |
513 + tfr d,x | |
514 + jsr ___clzhi2 | |
515 + tfr x,d | |
516 + subd #16 | |
517 + coma | |
518 + comb | |
519 + tfr d,x | |
520 + rts | |
521 +#endif | |
522 + | |
523 + | |
524 +#ifdef L_ctzdi2 | |
525 + .area .text | |
526 + .globl ___ctzsi2 | |
527 + ; Input: 32-bit unsigned integer is on the stack, just | |
528 + ; above the return address | |
529 + ; Output: X = number of leading zeros | |
530 +___ctzsi2: | |
531 + ; Check the lower 16-bit word | |
532 + ; If it is not zero, then return ctzhi2(X). | |
533 + ; A branch can be used instead of a call since no | |
534 + ; postprocessing is needed. Use long branch form | |
535 + ; though since functions may not be near each other. | |
536 + ldx 4,s | |
537 + lbne ___ctzhi2 | |
538 + ldx 2,s | |
539 + jsr ___ctzhi2 | |
540 + leax 16,x | |
541 + rts | |
542 +#endif | |
543 + | |
544 + | |
545 +#ifdef L_mulhi3 | |
546 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
547 +;;; ___mulhi3 - signed/unsigned multiply | |
548 +;;; Called by GCC to implement 16x16 multiplication | |
549 +;;; Arguments: Two 16-bit values, one in stack, one in X. | |
550 +;;; Result: 16-bit result in X | |
551 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
552 + .area .text | |
553 + .globl _mulhi3 | |
554 +_mulhi3: | |
555 + pshs x | |
556 + lda 5,s ; left msb * right lsb * 256 | |
557 + ldb ,s | |
558 + mul | |
559 + tfr b,a | |
560 + clrb | |
561 + tfr d,x | |
562 + ldb 1,s ; left lsb * right msb * 256 | |
563 + lda 4,s | |
564 + mul | |
565 + tfr b,a | |
566 + clrb | |
567 + leax d,x | |
568 + ldb 1,s ; left lsb * right lsb | |
569 + lda 5,s | |
570 + mul | |
571 + leax d,x | |
572 + puls d,pc ; kill D to remove initial push | |
573 +#endif | |
574 + | |
575 + | |
576 +#ifdef L_divhi3 | |
577 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
578 +;;; ___divhi3 - signed division | |
579 +;;; Arguments: Dividend in X, divisor on the stack | |
580 +;;; Returns result in X. | |
581 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
582 + .area .text | |
583 + .globl _divhi3 | |
584 +_divhi3: | |
585 + ldd 2,s | |
586 + bne do_div ; check dividend | |
587 + SIGFPE | |
588 +do_div: | |
589 + pshs x | |
590 + jsr _seuclid | |
591 + puls x,pc | |
592 +#endif | |
593 + | |
594 + | |
595 +#ifdef L_modhi3 | |
596 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
597 +;;; ___modhi3 - signed modulo | |
598 +;;; Arguments: Dividend in X, divisor on the stack | |
599 +;;; Returns result in X. | |
600 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
601 + .area .text | |
602 + .globl _modhi3 | |
603 +_modhi3: | |
604 + ldd 2,s | |
605 + bne do_mod ; check dividend | |
606 + SIGFPE | |
607 +do_mod: | |
608 + pshs x | |
609 + jsr _seuclid | |
610 + leas 2,s | |
611 + tfr d,x | |
612 + rts | |
613 +#endif | |
614 + | |
615 + | |
616 + | |
617 +#ifdef L_udivhi3 | |
618 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
619 +;;; ___udivhi3 - unsigned division | |
620 +;;; Arguments: Dividend in X, divisor on the stack | |
621 +;;; Returns result in X. | |
622 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
623 + .area .text | |
624 + .globl _udivhi3 | |
625 +_udivhi3: | |
626 + ldd 2,s | |
627 + bne do_udiv ; check dividend | |
628 + SIGFPE | |
629 +do_udiv: | |
630 + pshs x | |
631 + jsr _euclid | |
632 + puls x,pc | |
633 +#endif | |
634 + | |
635 + | |
636 +#ifdef L_umodhi3 | |
637 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
638 +;;; ___umodhi3 - unsigned modulo | |
639 +;;; Arguments: Dividend in X, divisor on the stack | |
640 +;;; Returns result in X. | |
641 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
642 + .area .text | |
643 + .globl _umodhi3 | |
644 +_umodhi3: | |
645 + ldd 2,s | |
646 + bne do_umod ; check dividend | |
647 + SIGFPE | |
648 +do_umod: | |
649 + pshs x | |
650 + jsr _euclid | |
651 + leas 2,s | |
652 + tfr d,x | |
653 + rts | |
654 +#endif | |
655 + | |
656 + | |
657 +#ifdef L_euclid | |
658 +; unsigned euclidean division | |
659 +; calling: (left / right) | |
660 +; push left | |
661 +; ldd right | |
662 +; jsr _euclid | |
663 +; quotient on the stack (left) | |
664 +; modulus in d | |
665 + | |
666 + .area .text | |
667 + .globl _euclid | |
668 + left=5 | |
669 + right=1 ; word | |
670 + count=0 ; byte | |
671 + CARRY=1 ; alias | |
672 +_euclid: | |
673 + leas -3,s ; 2 local variables | |
674 + clr count,s ; prescale divisor | |
675 + inc count,s | |
676 + tsta | |
677 +presc: | |
678 + bmi presc_done | |
679 + inc count,s | |
680 + aslb | |
681 + rola | |
682 + bra presc | |
683 +presc_done: | |
684 + std right,s | |
685 + ldd left,s | |
686 + clr left,s ; quotient = 0 | |
687 + clr left+1,s | |
688 +mod1: | |
689 + subd right,s ; check subtract | |
690 + bcc mod2 | |
691 + addd right,s | |
692 + andcc #~CARRY | |
693 + bra mod3 | |
694 +mod2: | |
695 + orcc #CARRY | |
696 +mod3: | |
697 + rol left+1,s ; roll in carry | |
698 + rol left,s | |
699 + lsr right,s | |
700 + ror right+1,s | |
701 + dec count,s | |
702 + bne mod1 | |
703 + leas 3,s | |
704 + rts | |
705 +#endif | |
706 + | |
707 +#ifdef L_seuclid | |
708 +; signed euclidean division | |
709 +; calling: (left / right) | |
710 +; push left | |
711 +; ldd right | |
712 +; jsr _seuclid | |
713 +; quotient on the stack (left) | |
714 +; modulus in d | |
715 + .area .text | |
716 + .globl _seuclid | |
717 + left=6 | |
718 + right=2 | |
719 + quot_sign=1 | |
720 + mod_sign=0 | |
721 +_seuclid: | |
722 + leas -4,s ; 3 local variables | |
723 + std right,s | |
724 + clr mod_sign,s | |
725 + clr quot_sign,s | |
726 + ldd left,s | |
727 + bge mod_abs | |
728 + inc mod_sign,s ; sign(mod) = sign(left) | |
729 + inc quot_sign,s | |
730 + bsr negd ; abs(left) -> D | |
731 +mod_abs: | |
732 + pshs b,a ; push abs(left) | |
733 + ldd right+2,s ; all references shifted by 2 | |
734 + bge quot_abs | |
735 + dec quot_sign+2,s ; sign(quot) = sign(left) XOR sign(right) | |
736 + bsr negd ; abs(right) -> D | |
737 +quot_abs: | |
738 + jsr _euclid ; call (unsigned) euclidean division | |
739 + std right+2,s | |
740 + puls a,b ; quot -> D | |
741 + tst quot_sign,s ; all references no longer shifted | |
742 + beq quot_done | |
743 + bsr negd | |
744 +quot_done: | |
745 + std left,s ; quot -> left | |
746 + ldd right,s | |
747 + tst mod_sign,s | |
748 + beq mod_done | |
749 + bsr negd | |
750 +mod_done: | |
751 + leas 4,s ; destroy stack frame | |
752 + rts | |
753 + | |
754 +negd: ; self-explanatory ! | |
755 + nega | |
756 + negb | |
757 + sbca #0 | |
758 + rts | |
759 +#endif | |
760 + | |
761 + | |
762 + | |
763 +#ifdef L_pending_addsi3 | |
764 +_addsi3: | |
765 + rts | |
766 +#endif /* L_pending_addsi3 */ | |
767 + | |
768 + | |
769 + | |
770 diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.c gcc-4.6.1/gcc/config/m6809/m6809.c | |
771 --- gcc-4.6.1-orig/gcc/config/m6809/m6809.c 1969-12-31 17:00:00.000000000 -0700 | |
772 +++ gcc-4.6.1/gcc/config/m6809/m6809.c 2011-09-18 19:48:42.137654855 -0600 | |
773 @@ -0,0 +1,3013 @@ | |
774 +/*------------------------------------------------------------------- | |
775 + FILE: m6809.c | |
776 +-------------------------------------------------------------------*/ | |
777 +/* Subroutines for insn-output.c for MC6809. | |
778 + Copyright (C) 1989-2007 Free Software Foundation, Inc. | |
779 + | |
780 + MC6809 Version by Tom Jones (jones@sal.wisc.edu) | |
781 + Space Astronomy Laboratory | |
782 + University of Wisconsin at Madison | |
783 + | |
784 + minor changes to adapt it to gcc-2.5.8 by Matthias Doerfel | |
785 + ( msdoerfe@informatik.uni-erlangen.de ) | |
786 + also added #pragma interrupt (inspired by gcc-6811) | |
787 + | |
788 + minor changes to adapt it to gcc-2.8.0 by Eric Botcazou | |
789 + (ebotcazou@multimania.com) | |
790 + | |
791 + minor changes to adapt it to gcc-2.95.3 by Eric Botcazou | |
792 + (ebotcazou@multimania.com) | |
793 + | |
794 + major cleanup, improvements, and upgrade to gcc 3.4 by Brian Dominy | |
795 + (brian@oddchange.com) | |
796 + | |
797 + additional adjustments, etc., for gcc 4.6.1 by William Astle (lost@l-w.ca) | |
798 + | |
799 +This file is part of GCC. | |
800 + | |
801 +GCC is free software; you can redistribute it and/or modify | |
802 +it under the terms of the GNU General Public License as published by | |
803 +the Free Software Foundation; either version 3, or (at your option) | |
804 +any later version. | |
805 + | |
806 +GCC is distributed in the hope that it will be useful, | |
807 +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
808 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
809 +GNU General Public License for more details. | |
810 + | |
811 +You should have received a copy of the GNU General Public License | |
812 +along with GCC; see the file COPYING3. If not see | |
813 +<http://www.gnu.org/licenses/>. */ | |
814 + | |
815 +#include <string.h> | |
816 +#include <time.h> | |
817 +#include <sys/types.h> | |
818 +#include <sys/timeb.h> | |
819 +#include <stdio.h> | |
820 +#include "config.h" | |
821 +#include "system.h" | |
822 +#include "coretypes.h" | |
823 +#include "tm.h" | |
824 +#include "tree.h" | |
825 +#include "rtl.h" | |
826 +#include "tm_p.h" | |
827 +#include "regs.h" | |
828 +#include "flags.h" | |
829 +#include "hard-reg-set.h" | |
830 +#include "real.h" | |
831 +#include "tree.h" | |
832 +#include "insn-config.h" | |
833 +#include "conditions.h" | |
834 +#include "insn-flags.h" | |
835 +#include "output.h" | |
836 +#include "insn-attr.h" | |
837 +#include "function.h" | |
838 +#include "target.h" | |
839 +#include "target-def.h" | |
840 +#include "expr.h" | |
841 +#include "recog.h" | |
842 +#include "cpplib.h" | |
843 +#include "c-family/c-pragma.h" | |
844 +#include "c-family/c-common.h" | |
845 +#include "toplev.h" | |
846 +#include "optabs.h" | |
847 +#include "version.h" | |
848 +#include "df.h" | |
849 +#include "rtlhooks-def.h" | |
850 + | |
851 +/* macro to return TRUE if length of operand mode is one byte */ | |
852 +#define BYTE_MODE(X) ((GET_MODE_SIZE (GET_MODE (X))) == 1) | |
853 + | |
854 + | |
855 +/* REAL_REG_P(x) is a true if the rtx 'x' represents a real CPU | |
856 +register and not a fake one that is emulated in software. */ | |
857 +#define REAL_REG_P(x) (REG_P(x) && !M_REG_P(x)) | |
858 + | |
859 +/*------------------------------------------------------------------- | |
860 + Target hooks, moved from target.h | |
861 +-------------------------------------------------------------------*/ | |
862 +static void m6809_encode_section_info (tree decl, rtx rtl, int new_decl_p ATTRIBUTE_UNUSED); | |
863 + | |
864 +#undef TARGET_ENCODE_SECTION_INFO | |
865 +#define TARGET_ENCODE_SECTION_INFO m6809_encode_section_info | |
866 + | |
867 +#undef TARGET_ASM_FILE_START | |
868 +#define TARGET_ASM_FILE_START m6809_asm_file_start | |
869 + | |
870 +#undef TARGET_ASM_ALIGNED_HI_OP | |
871 +#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" | |
872 + | |
873 +#undef TARGET_ASM_ALIGNED_SI_OP | |
874 +#define TARGET_ASM_ALIGNED_SI_OP NULL | |
875 + | |
876 +#undef TARGET_ASM_UNALIGNED_HI_OP | |
877 +#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t" | |
878 + | |
879 +#undef TARGET_ASM_UNALIGNED_SI_OP | |
880 +#define TARGET_ASM_UNALIGNED_SI_OP NULL | |
881 + | |
882 +#undef TARGET_RTX_COSTS | |
883 +#define TARGET_RTX_COSTS m6809_rtx_costs | |
884 + | |
885 +#undef TARGET_ATTRIBUTE_TABLE | |
886 +#define TARGET_ATTRIBUTE_TABLE m6809_attribute_table | |
887 + | |
888 +#undef TARGET_INIT_BUILTINS | |
889 +#define TARGET_INIT_BUILTINS m6809_init_builtins | |
890 + | |
891 +#undef TARGET_EXPAND_BUILTIN | |
892 +#define TARGET_EXPAND_BUILTIN m6809_expand_builtin | |
893 + | |
894 +#undef TARGET_DEFAULT_TARGET_FLAGS | |
895 +#define TARGET_DEFAULT_TARGET_FLAGS (MASK_REG_ARGS | MASK_DIRECT) | |
896 + | |
897 +#undef TARGET_FUNCTION_OK_FOR_SIBCALL | |
898 +#define TARGET_FUNCTION_OK_FOR_SIBCALL m6809_function_ok_for_sibcall | |
899 + | |
900 +#undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
901 +#define TARGET_ASM_TRAMPOLINE_TEMPLATE m6809_asm_trampoline_template | |
902 + | |
903 +#undef TARGET_TRAMPOLINE_INIT | |
904 +#define TARGET_TRAMPOLINE_INIT m6809_initialize_trampoline | |
905 + | |
906 +#undef TARGET_FRAME_POINTER_REQUIRED | |
907 +#define TARGET_FRAME_POINTER_REQUIRED m6809_frame_pointer_required | |
908 + | |
909 +#undef TARGET_OPTION_OVERRIDE | |
910 +#define TARGET_OPTION_OVERRIDE m6809_override_options | |
911 + | |
912 +/* External variables used */ | |
913 +extern int reload_completed; /* set in toplev.c */ | |
914 +extern FILE *asm_out_file; | |
915 + | |
916 +static int last_mem_size; /* operand size (bytes) */ | |
917 + | |
918 +/* True if the section was recently changed and another .area | |
919 + * directive needs to be output before emitting the next label. */ | |
920 +int section_changed = 0; | |
921 + | |
922 +/* Section names. The defaults here are used until an | |
923 + * __attribute__((section)) is seen that changes it. */ | |
924 +char code_section_op[128] = "\t.area .text"; | |
925 +char data_section_op[128] = "\t.area .data"; | |
926 +char bss_section_op[128] = "\t.area .bss"; | |
927 +const char *code_bank_option = 0; | |
928 + | |
929 +/* TRUE if the direct mode prefix might be valid in this context. | |
930 + * This is set by 'print_address' prior to calling output_addr_const, | |
931 + * which performs into 'print_direct_prefix' to do the final checks. */ | |
932 +static int check_direct_prefix_flag; | |
933 + | |
934 +/* Nonzero if an address is being printed in a context which does not | |
935 + * permit any PIC modifications to the address */ | |
936 +static int pic_ok_for_addr_p = 1; | |
937 + | |
938 +/* Current code page. This supports machines which can do bank | |
939 + * switching to allow for more than 64KB of code/data. */ | |
940 +char far_code_page[64]; | |
941 + | |
942 +/* Current bank name */ | |
943 +static char current_bank_name[8] = "-1"; | |
944 + | |
945 +/* Default bank name */ | |
946 +static char default_code_bank_name[8] = "-1"; | |
947 + | |
948 +/* Direct memory reserved as soft registers */ | |
949 +unsigned int m6809_soft_regs = 0; | |
950 + | |
951 +/* ABI version */ | |
952 +unsigned int m6809_abi_version = M6809_ABI_VERSION_REGS; | |
953 + | |
954 + | |
955 +/** | |
956 + * Called after options have been parsed. | |
957 + * If overrides have been specified on the command-line, then | |
958 + * these values are copied into the main storage variables. | |
959 + */ | |
960 +void | |
961 +m6809_override_options (void) | |
962 +{ | |
963 + /* Handle -mfar-code-page */ | |
964 + if (far_code_page_option == 0) | |
965 + far_code_page_option = "__default_code_page"; | |
966 + strcpy (far_code_page, far_code_page_option); | |
967 + | |
968 + /* Handle -mcode-section, -mdata-section, and -mbss-section */ | |
969 + if (code_section_ptr != 0) | |
970 + sprintf (code_section_op, "\t.area %s", code_section_ptr); | |
971 + if (data_section_ptr != 0) | |
972 + sprintf (data_section_op, "\t.area %s", data_section_ptr); | |
973 + if (bss_section_ptr != 0) | |
974 + sprintf (bss_section_op, "\t.area %s", bss_section_ptr); | |
975 + | |
976 + /* Handle -mcode-bank */ | |
977 + if (code_bank_option != 0) | |
978 + sprintf (default_code_bank_name, "%s", code_bank_option); | |
979 + | |
980 + /* Handle -mabi-version or -mno-reg-args */ | |
981 + if (m6809_abi_version_ptr != 0) | |
982 + { | |
983 + if (!strcmp (m6809_abi_version_ptr, "stack")) | |
984 + m6809_abi_version = M6809_ABI_VERSION_STACK; | |
985 + else if (!strcmp (m6809_abi_version_ptr, "regs")) | |
986 + m6809_abi_version = M6809_ABI_VERSION_REGS; | |
987 + else if (!strcmp (m6809_abi_version_ptr, "bx")) | |
988 + m6809_abi_version = M6809_ABI_VERSION_BX; | |
989 + else if (!strcmp (m6809_abi_version_ptr, "latest")) | |
990 + m6809_abi_version = M6809_ABI_VERSION_LATEST; | |
991 + else | |
992 + m6809_abi_version = atoi (m6809_abi_version_ptr); | |
993 + } | |
994 + | |
995 + /* The older -mno-reg-args option is deprecated, and treated | |
996 + as -mabi=stack. */ | |
997 + if (!TARGET_REG_ARGS) | |
998 + { | |
999 + warning (WARNING_OPT "-mno-reg-args deprecated; use -mabi=stack instead."); | |
1000 + m6809_abi_version = M6809_ABI_VERSION_STACK; | |
1001 + } | |
1002 + | |
1003 + /* -fexceptions is unsupported */ | |
1004 + flag_exceptions = 0; | |
1005 + flag_non_call_exceptions = 0; | |
1006 + flag_unwind_tables = 0; | |
1007 +} | |
1008 + | |
1009 + | |
1010 +/** | |
1011 + * Output prefix that directs the assembler to use a direct-mode | |
1012 + * instruction if globally enabled, address is a symbol, and symbol | |
1013 + * has been marked as in direct page. Also, never do this if | |
1014 + * using the indirect mode. */ | |
1015 +void | |
1016 +print_direct_prefix (FILE * file, rtx addr) | |
1017 +{ | |
1018 + if (TARGET_DIRECT && | |
1019 + (GET_CODE (addr) == SYMBOL_REF) && | |
1020 + SYMBOL_REF_FLAG (addr) && | |
1021 + check_direct_prefix_flag) | |
1022 + { | |
1023 + putc ('*', file); | |
1024 + } | |
1025 +} | |
1026 + | |
1027 + | |
1028 +/** Prints an operand (that is not an address) in assembly from RTL. */ | |
1029 +void | |
1030 +print_operand (FILE * file, rtx x, int code) | |
1031 +{ | |
1032 + if (REG_P (x)) { | |
1033 + /* gcc currently allocates the entire 16-bit 'd' register | |
1034 + * even when it only needs an 8-bit value. So here it | |
1035 + * is tricked into printing only the lower 8-bit 'b' | |
1036 + * register into the assembly output. | |
1037 + * | |
1038 + * Eventually gcc should be modified to allocate a/b | |
1039 + * independently and this hack can be removed. | |
1040 + * | |
1041 + * Occasionally, we may want to do an operation using | |
1042 + * the 'a' register instead of 'b'; use the 'A' code | |
1043 + * to specify that. | |
1044 + */ | |
1045 + if (code == 'A') | |
1046 + fputs ("a", file); | |
1047 + else if ((BYTE_MODE (x)) && (REGNO (x) == HARD_D_REGNUM)) | |
1048 + fputs ("b", file); | |
1049 + else if (M_REG_P (x) && code == 'L') | |
1050 + /* Soft registers can be treated like memory and accessed | |
1051 + * at a particular offset. TODO : handle 'W' */ | |
1052 + fputs (reg_names[REGNO (x)+1], file); | |
1053 + else | |
1054 + fputs (reg_names[REGNO (x)], file); | |
1055 + } | |
1056 + | |
1057 + else if (MEM_P (x)) { | |
1058 + last_mem_size = GET_MODE_SIZE (GET_MODE (x)); | |
1059 + if (code == 'L') { /* LSH of word address */ | |
1060 + if (GET_CODE (XEXP (x, 0)) == MEM) | |
1061 + { | |
1062 + /* Offseting an indirect addressing mode is not supported */ | |
1063 + error ("expression too complex for 6809 (offset indirect mode)"); | |
1064 + debug_rtx (x); | |
1065 + } | |
1066 + else | |
1067 + x = adjust_address (x, QImode, 1); | |
1068 + } | |
1069 + else if (code == 'M') { /* MSH of word address */ | |
1070 + if (GET_CODE (XEXP (x, 0)) == MEM) | |
1071 + { | |
1072 + /* Offseting an indirect addressing mode is not supported */ | |
1073 + error ("expression too complex for 6809 (offset indirect mode)"); | |
1074 + debug_rtx (x); | |
1075 + } | |
1076 + else | |
1077 + x = adjust_address (x, QImode, 0); | |
1078 + } | |
1079 + else if (code == 'W') { /* least significant half of 32-bit */ | |
1080 + x = adjust_address (x, HImode, 2); | |
1081 + } | |
1082 + | |
1083 + pic_ok_for_addr_p = (code != 'C'); | |
1084 + output_address (XEXP (x, 0)); | |
1085 + } | |
1086 + | |
1087 + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode) { | |
1088 + union { double d; int i[2]; } u; | |
1089 + u.i[0] = CONST_DOUBLE_LOW (x); | |
1090 + u.i[1] = CONST_DOUBLE_HIGH (x); | |
1091 + fprintf (file, "#%#9.9g", u.d); | |
1092 + } | |
1093 + | |
1094 + else if (code == 'R') { | |
1095 + fprintf (file, "%s", | |
1096 + m6809_get_regs_printable (INTVAL (x))); | |
1097 + } | |
1098 + | |
1099 + else { | |
1100 + if (code == 'L') { /* LSH of word address */ | |
1101 + x = gen_rtx_CONST_INT (VOIDmode, (INTVAL(x) & 0xff)); | |
1102 + } | |
1103 + else if (code == 'M') { /* MSH of word address */ | |
1104 + x = gen_rtx_CONST_INT (VOIDmode, ((INTVAL(x) >> 8) & 0xff)); | |
1105 + } | |
1106 + | |
1107 + putc ('#', file); | |
1108 + output_addr_const (file, x); | |
1109 + } | |
1110 +} | |
1111 + | |
1112 + | |
1113 +/** Prints an address operand to assembler from its RTL representation. */ | |
1114 +void | |
1115 +print_operand_address (FILE *file, rtx addr) | |
1116 +{ | |
1117 + register rtx base = 0; | |
1118 + register rtx offset = 0; | |
1119 + int regno; | |
1120 + int indirect_flag = 0; | |
1121 + | |
1122 + check_direct_prefix_flag = 0; | |
1123 + | |
1124 + /*** check for indirect addressing ***/ | |
1125 + if (MEM_P (addr)) { | |
1126 + last_mem_size = GET_MODE_SIZE (GET_MODE (addr)); | |
1127 + addr = XEXP (addr, 0); | |
1128 + if (pic_ok_for_addr_p) | |
1129 + { | |
1130 + indirect_flag = 1; | |
1131 + fprintf (file, "["); | |
1132 + } | |
1133 + } | |
1134 + | |
1135 + | |
1136 + switch (GET_CODE (addr)) { | |
1137 + case REG: | |
1138 + regno = REGNO (addr); | |
1139 + fprintf (file, ",%s", reg_names[regno]); | |
1140 + break; | |
1141 + | |
1142 + case PRE_DEC: | |
1143 + regno = REGNO (XEXP (addr, 0)); | |
1144 + fputs (((last_mem_size == 1) ? ",-" : ",--"), file); | |
1145 + fprintf (file, "%s", reg_names[regno]); | |
1146 + break; | |
1147 + | |
1148 + case POST_INC: | |
1149 + regno = REGNO (XEXP (addr, 0)); | |
1150 + fprintf (file, ",%s", reg_names[regno]); | |
1151 + fputs (((last_mem_size == 1) ? "+" : "++"), file); | |
1152 + break; | |
1153 + | |
1154 + case PLUS: | |
1155 + base = XEXP (addr, 0); | |
1156 + if (MEM_P (base)) | |
1157 + base = XEXP (base, 0); | |
1158 + | |
1159 + offset = XEXP (addr, 1); | |
1160 + if (MEM_P (offset)) | |
1161 + offset = XEXP (offset, 0); | |
1162 + | |
1163 + if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset))) { | |
1164 + if (!indirect_flag) | |
1165 + check_direct_prefix_flag = 1; | |
1166 + output_addr_const (file, base); | |
1167 + check_direct_prefix_flag = 0; | |
1168 + fputs ("+", file); | |
1169 + output_addr_const (file, offset); | |
1170 + } | |
1171 + | |
1172 + else if ((CONSTANT_ADDRESS_P (base)) && (A_REG_P (offset))) { | |
1173 + output_addr_const (file, base); | |
1174 + fprintf (file, ",%s", reg_names[REGNO (offset)]); | |
1175 + } | |
1176 + | |
1177 + else if ((CONSTANT_ADDRESS_P (offset)) && (A_REG_P (base))) { | |
1178 + output_addr_const (file, offset); | |
1179 + fprintf (file, ",%s", reg_names[REGNO (base)]); | |
1180 + } | |
1181 + | |
1182 + /*** accumulator offset ***/ | |
1183 + else if (((D_REG_P (offset)) || (Q_REG_P (offset))) | |
1184 + && (A_REG_P (base))) { | |
1185 + fprintf (file, "%s,%s", | |
1186 + reg_names[REGNO (offset)], reg_names[REGNO (base)]); | |
1187 + } | |
1188 + | |
1189 + else if (((D_REG_P (base)) || (Q_REG_P (base))) | |
1190 + && (A_REG_P (offset))) { | |
1191 + fprintf (file, "%s,%s", | |
1192 + reg_names[REGNO (base)], reg_names[REGNO (offset)]); | |
1193 + } | |
1194 + | |
1195 + else if (GET_CODE (base) == PRE_DEC) { | |
1196 + regno = REGNO (XEXP (base, 0)); | |
1197 + fputs (((last_mem_size == 1) ? ",-" : ",--"), file); | |
1198 + fprintf (file, "%s", reg_names[regno]); | |
1199 + } | |
1200 + | |
1201 + else | |
1202 + abort (); | |
1203 + | |
1204 + break; | |
1205 + | |
1206 + default: | |
1207 + /* Set this global before calling output_addr_const() */ | |
1208 + if (!indirect_flag) | |
1209 + check_direct_prefix_flag = 1; | |
1210 + | |
1211 + /* When printing a SYMBOL_REF in PIC mode, do not print the leading | |
1212 + * '#' and follow it by ',pcr' to enable relative addressing. */ | |
1213 + if (flag_pic && pic_ok_for_addr_p && GET_CODE (addr) == SYMBOL_REF) | |
1214 + { | |
1215 + ASM_OUTPUT_SYMBOL_REF (file, addr); | |
1216 + fputs (",pcr", file); | |
1217 + pic_ok_for_addr_p = 1; | |
1218 + } | |
1219 + else | |
1220 + { | |
1221 + output_addr_const (file, addr); | |
1222 + } | |
1223 + | |
1224 + check_direct_prefix_flag = 0; | |
1225 + break; | |
1226 + } | |
1227 + | |
1228 + if (indirect_flag) | |
1229 + fprintf (file, "]"); | |
1230 +} | |
1231 + | |
1232 +/*------------------------------------------------------------------- | |
1233 + Update the CC Status | |
1234 +--------------------------------------------------------------------- | |
1235 + Set the cc_status for the results of an insn whose pattern is EXP. | |
1236 + We assume that jumps don't affect the condition codes. | |
1237 + All else, clobbers the condition codes, by assumption. | |
1238 + | |
1239 + We assume that ALL add, minus, etc. instructions effect the condition | |
1240 + codes. | |
1241 +-------------------------------------------------------------------*/ | |
1242 +void | |
1243 +notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED) | |
1244 +{ | |
1245 + int src_code; | |
1246 + int dst_code; | |
1247 + | |
1248 + /*** recognize SET insn's ***/ | |
1249 + if (GET_CODE (exp) == SET) | |
1250 + { | |
1251 + src_code = GET_CODE (SET_SRC (exp)); | |
1252 + dst_code = GET_CODE (SET_DEST (exp)); | |
1253 + | |
1254 + /* Jumps do not alter the cc's. */ | |
1255 + if (SET_DEST (exp) == pc_rtx) | |
1256 + return; | |
1257 + | |
1258 + /* Moving one register into another register (tfr): | |
1259 + Doesn't alter the cc's. */ | |
1260 + if (REG_P (SET_DEST (exp)) && (REG_P (SET_SRC (exp)))) | |
1261 + return; | |
1262 + | |
1263 + /* Moving memory into a register (load): Sets cc's. */ | |
1264 + if (REG_P (SET_DEST (exp)) && src_code == MEM) { | |
1265 + cc_status.value1 = SET_SRC (exp); | |
1266 + cc_status.value2 = SET_DEST (exp); | |
1267 + return; | |
1268 + } | |
1269 + | |
1270 + /* Moving register into memory (store): Sets cc's. */ | |
1271 + if (dst_code == MEM && REG_P (SET_SRC (exp))) { | |
1272 + cc_status.value1 = SET_SRC (exp); | |
1273 + cc_status.value2 = SET_DEST (exp); | |
1274 + return; | |
1275 + } | |
1276 + | |
1277 + /* Function calls clobber the cc's. */ | |
1278 + else if (GET_CODE (SET_SRC (exp)) == CALL) { | |
1279 + CC_STATUS_INIT; | |
1280 + return; | |
1281 + } | |
1282 + | |
1283 + /* Tests and compares set the cc's in predictable ways. */ | |
1284 + else if (SET_DEST (exp) == cc0_rtx) | |
1285 + { | |
1286 + cc_status.flags = 0; | |
1287 + cc_status.value1 = SET_SRC (exp); | |
1288 + cc_status.value2 = SET_DEST (exp); | |
1289 + return; | |
1290 + } | |
1291 + | |
1292 + else if (A_REG_P (SET_DEST (exp))) | |
1293 + { | |
1294 + CC_STATUS_INIT; | |
1295 + return; | |
1296 + } | |
1297 + | |
1298 + else | |
1299 + { | |
1300 + /* Certain instructions affect the condition codes. */ | |
1301 + switch (src_code) | |
1302 + { | |
1303 + case PLUS: | |
1304 + case MINUS: | |
1305 + case NEG: | |
1306 + case ASHIFT: | |
1307 + /* These instructions set the condition codes, | |
1308 + * and may modify the V bit. */ | |
1309 + cc_status.flags |= CC_NO_OVERFLOW; | |
1310 + /* FALLTHRU */ | |
1311 + | |
1312 + case AND: | |
1313 + case IOR: | |
1314 + case XOR: | |
1315 + case ASHIFTRT: | |
1316 + case LSHIFTRT: | |
1317 + /* These instructions set the condition codes, | |
1318 + * but cannot overflow (V=0). */ | |
1319 + cc_status.value1 = SET_SRC (exp); | |
1320 + cc_status.value2 = SET_DEST (exp); | |
1321 + break; | |
1322 + | |
1323 + default: | |
1324 + /* Everything else is clobbered */ | |
1325 + CC_STATUS_INIT; | |
1326 + } | |
1327 + return; | |
1328 + } | |
1329 + } /* SET */ | |
1330 + | |
1331 + else if (GET_CODE (exp) == PARALLEL | |
1332 + && GET_CODE (XVECEXP (exp, 0, 0)) == SET) | |
1333 + { | |
1334 + if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) | |
1335 + return; | |
1336 + if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) | |
1337 + { | |
1338 + CC_STATUS_INIT; | |
1339 + cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); | |
1340 + return; | |
1341 + } | |
1342 + } | |
1343 + | |
1344 + /*** default action if we haven't recognized something | |
1345 + and returned earlier ***/ | |
1346 + CC_STATUS_INIT; | |
1347 +} | |
1348 + | |
1349 + | |
1350 +/** Returns nonzero if the expression EXP can be implemented using one | |
1351 + * of the 6809's single operand instructions. */ | |
1352 +int | |
1353 +m6809_single_operand_operator (rtx exp) | |
1354 +{ | |
1355 + rtx op1; | |
1356 + HOST_WIDE_INT val; | |
1357 + enum rtx_code code; | |
1358 + | |
1359 + debug_rtx(exp); | |
1360 + | |
1361 + code = GET_CODE (exp); | |
1362 + | |
1363 + /* Unary operators always qualify */ | |
1364 + switch (code) | |
1365 + { | |
1366 + case NEG: | |
1367 + case NOT: | |
1368 + return 1; | |
1369 + | |
1370 + default: | |
1371 + break; | |
1372 + } | |
1373 + | |
1374 + /* Binary operators can only qualify if the second | |
1375 + * argument is a CONST_INT of certain value. */ | |
1376 + op1 = XEXP (exp, 1); | |
1377 + if (GET_CODE (op1) != CONST_INT) | |
1378 + return 0; | |
1379 + val = INTVAL (op1); | |
1380 + switch (code) | |
1381 + { | |
1382 + case PLUS: | |
1383 + case MINUS: | |
1384 + if (val == -1 || val == 1) | |
1385 + return 1; | |
1386 + break; | |
1387 + | |
1388 + case ASHIFT: | |
1389 + case ASHIFTRT: | |
1390 + case LSHIFTRT: | |
1391 + case ROTATE: | |
1392 + case ROTATERT: | |
1393 + if (val == 1) | |
1394 + return 1; | |
1395 + break; | |
1396 + | |
1397 + default: | |
1398 + break; | |
1399 + } | |
1400 + | |
1401 + return 0; | |
1402 +} | |
1403 + | |
1404 + | |
1405 +/** Return a bitarray of the hard registers which are used by a function. */ | |
1406 +unsigned int | |
1407 +m6809_get_live_regs (void) | |
1408 +{ | |
1409 + unsigned int regs = 0; | |
1410 + int regno; | |
1411 + | |
1412 + if (frame_pointer_needed) | |
1413 + regs |= (1 << HARD_FRAME_POINTER_REGNUM); | |
1414 + | |
1415 + for (regno = HARD_X_REGNUM; regno <= HARD_U_REGNUM; regno++) | |
1416 + if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) | |
1417 + regs |= (1 << regno); | |
1418 + | |
1419 + return regs; | |
1420 +} | |
1421 + | |
1422 + | |
1423 +/** Return a printable version of a list of hard registers, suitable | |
1424 + * for use in a PSHx or PULx insn. */ | |
1425 +const char * | |
1426 +m6809_get_regs_printable (unsigned int regs) | |
1427 +{ | |
1428 + static char list[64]; | |
1429 + char *listp = list; | |
1430 + unsigned int regno; | |
1431 + | |
1432 + for (regno=0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
1433 + if ((regs & (1 << regno)) && !S_REGNO_P (regno)) | |
1434 + listp += sprintf (listp, | |
1435 + (listp == list) ? "%s" : ",%s", reg_names[regno]); | |
1436 + | |
1437 + return list; | |
1438 +} | |
1439 + | |
1440 + | |
1441 +/** Return the total number of bytes covered by a set of hard registers. */ | |
1442 +unsigned int | |
1443 +m6809_get_regs_size (unsigned int regs) | |
1444 +{ | |
1445 + unsigned int regno; | |
1446 + unsigned int size = 0; | |
1447 + | |
1448 + for (regno=0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
1449 + { | |
1450 + /* Only count register in the given register set */ | |
1451 + if (REGSET_CONTAINS_P (regno, regs)) | |
1452 + { | |
1453 + /* Add 1 or 2 byte, depending on the size of the register. | |
1454 + * Since 'D' may be in both sets, check for WORD_REGSET first. */ | |
1455 + if (REGSET_CONTAINS_P(regno, WORD_REGSET)) | |
1456 + size += 2; | |
1457 + else if (REGSET_CONTAINS_P(regno, BYTE_REGSET)) | |
1458 + size++; | |
1459 + } | |
1460 + } | |
1461 + return size; | |
1462 +} | |
1463 + | |
1464 + | |
1465 +/* Given the target of call instruction in X, | |
1466 + * return the tree node that contains the function declaration for | |
1467 + * that target. | |
1468 + * | |
1469 + * If the rtx or the tree do not appear valid for any reason, | |
1470 + * then return NULL_TREE. | |
1471 + */ | |
1472 +static tree call_target_decl (rtx x) | |
1473 +{ | |
1474 + tree decl; | |
1475 + | |
1476 + /* Make sure the target is really a MEM. */ | |
1477 + if (!x || !MEM_P (x)) | |
1478 + return NULL_TREE; | |
1479 + | |
1480 + /* Make sure the address is a SYMBOL_REF. */ | |
1481 + x = XEXP (x, 0); | |
1482 + if (!x || (GET_CODE (x) != SYMBOL_REF)) | |
1483 + return NULL_TREE; | |
1484 + | |
1485 + /* Get the declaration of this symbol */ | |
1486 + decl = SYMBOL_REF_DECL (x); | |
1487 + | |
1488 + /* Make sure the declaration is really a function. */ | |
1489 + if (!decl || (TREE_CODE(decl) != FUNCTION_DECL)) | |
1490 + return NULL_TREE; | |
1491 + | |
1492 + return decl; | |
1493 +} | |
1494 + | |
1495 + | |
1496 +/** Returns nonzero if a function, whose declaration is in DECL, | |
1497 + * was declared to have the attribute given by ATTR_NAME. */ | |
1498 +int | |
1499 +m6809_function_has_type_attr_p (tree decl, const char *attr_name) | |
1500 +{ | |
1501 + tree type; | |
1502 + | |
1503 + type = TREE_TYPE (decl); | |
1504 + return lookup_attribute (attr_name, TYPE_ATTRIBUTES (type)) != NULL; | |
1505 +} | |
1506 + | |
1507 + | |
1508 + | |
1509 +/** Returns nonzero if the current function was declared to have the | |
1510 + * attribute given by ATTR_NAME. */ | |
1511 +int | |
1512 +m6809_current_function_has_type_attr_p (const char *attr_name) | |
1513 +{ | |
1514 + return m6809_function_has_type_attr_p (current_function_decl, attr_name); | |
1515 +} | |
1516 + | |
1517 + | |
1518 +/** Return nonzero if the current function has no return value. */ | |
1519 +int | |
1520 +m6809_current_function_is_void (void) | |
1521 +{ | |
1522 + return (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))); | |
1523 +} | |
1524 + | |
1525 + | |
1526 +/** Get the value of a declaration's 'bank', as set by the 'bank' | |
1527 + * attribute. If no bank was declared, it returns NULL by default. */ | |
1528 +const char * | |
1529 +m6809_get_decl_bank (tree decl) | |
1530 +{ | |
1531 + tree attr; | |
1532 + | |
1533 + /* Lookup the 'bank' attribute. If it does not exist, then | |
1534 + * return NULL */ | |
1535 + attr = lookup_attribute ("bank", DECL_ATTRIBUTES (decl)); | |
1536 + if (attr == NULL_TREE) | |
1537 + return NULL; | |
1538 + | |
1539 + /* Make sure it has a value assigned to it */ | |
1540 + attr = TREE_VALUE (attr); | |
1541 + if (attr == NULL_TREE) | |
1542 + { | |
1543 + warning (WARNING_OPT "banked function did not declare a bank number"); | |
1544 + return NULL; | |
1545 + } | |
1546 + | |
1547 + /* Return the bank name */ | |
1548 + attr = TREE_VALUE (attr); | |
1549 + return TREE_STRING_POINTER (attr); | |
1550 +} | |
1551 + | |
1552 + | |
1553 +void | |
1554 +m6809_declare_function_name (FILE *asm_out_file, const char *name, tree decl) | |
1555 +{ | |
1556 + /* Check the function declaration for special properties. | |
1557 + * | |
1558 + * If the function was declare with __attribute__((bank)), output | |
1559 + * assembler definitions to force the function to go into the named | |
1560 + * bank. | |
1561 + */ | |
1562 + const char *bank_name = m6809_get_decl_bank (decl); | |
1563 + if (bank_name != NULL) | |
1564 + { | |
1565 + /* Declare __self_bank as a local assembler value that denotes | |
1566 + * which bank the current function is in. This is required only | |
1567 + * when the bank actually changes. */ | |
1568 + if (strcmp (bank_name, current_bank_name)) | |
1569 + { | |
1570 + fprintf (asm_out_file, "__self_bank\t.equ %s\n", bank_name); | |
1571 + strcpy (current_bank_name, bank_name); | |
1572 + } | |
1573 + | |
1574 + /* Declare a global assembler value that denotes which bank the | |
1575 + * named function is in. */ | |
1576 + fprintf (asm_out_file, "__%s_bank\t.gblequ %s\n", name, bank_name); | |
1577 + | |
1578 + /* Force the current function into a new area */ | |
1579 + fprintf (asm_out_file, "\t.bank bank_%s (FSFX=_%s)\n", | |
1580 + bank_name, bank_name); | |
1581 + fprintf (asm_out_file, "\t.area bank_%s (BANK=bank_%s)\n", | |
1582 + bank_name, bank_name); | |
1583 + } | |
1584 + | |
1585 + /* Emit the label for the function's name */ | |
1586 + ASM_OUTPUT_LABEL (asm_out_file, name); | |
1587 +} | |
1588 + | |
1589 +#if 0 | |
1590 +/** | |
1591 + * Handle pragmas. Note that only the last branch pragma seen in the | |
1592 + * source has any affect on code generation. | |
1593 + */ | |
1594 + | |
1595 +#define BAD_PRAGMA(msgid, arg) \ | |
1596 + do { warning (WARNING_OPT msgid, arg); return -1; } while (0) | |
1597 + | |
1598 +static int | |
1599 +pragma_parse (const char *name, tree *sect) | |
1600 +{ | |
1601 + tree s, x; | |
1602 + | |
1603 + if (pragma_lex (&x) != CPP_OPEN_PAREN) | |
1604 + BAD_PRAGMA ("missing '(' after '#pragma %s' - ignored", name); | |
1605 + | |
1606 + if (pragma_lex (&s) != CPP_STRING) | |
1607 + BAD_PRAGMA ("missing section name in '#pragma %s' - ignored", name); | |
1608 + | |
1609 + if (pragma_lex (&x) != CPP_CLOSE_PAREN) | |
1610 + BAD_PRAGMA ("missing ')' for '#pragma %s' - ignored", name); | |
1611 + | |
1612 + if (pragma_lex (&x) != CPP_EOF) | |
1613 + warning (WARNING_OPT "junk at end of '#pragma %s'", name); | |
1614 + | |
1615 + *sect = s; | |
1616 + return 0; | |
1617 +} | |
1618 + | |
1619 + | |
1620 +/* | |
1621 + * Handle #pragma section. | |
1622 + * This is deprecated; code should use __attribute__(section("name")) | |
1623 + * instead. | |
1624 + */ | |
1625 +void pragma_section (cpp_reader *pfile ATTRIBUTE_UNUSED) | |
1626 +{ | |
1627 + tree sect; | |
1628 + | |
1629 + if (pragma_parse ("section", §)) | |
1630 + return; | |
1631 + | |
1632 + snprintf (code_section_op, 6+TREE_STRING_LENGTH (sect), | |
1633 + ".area\t%s", TREE_STRING_POINTER (sect)); | |
1634 + snprintf (data_section_op, 6+TREE_STRING_LENGTH (sect), | |
1635 + ".area\t%s", TREE_STRING_POINTER (sect)); | |
1636 + | |
1637 + /* Mark a flag that sections have changed. Upon emitting another | |
1638 + * declaration, the new .area directive will be written. */ | |
1639 + section_changed++; | |
1640 +} | |
1641 +#endif | |
1642 + | |
1643 +/** | |
1644 + * Check a `double' value for validity for a particular machine mode. | |
1645 + * Called by the CHECK_FLOAT_VALUE() machine-dependent macro. | |
1646 + */ | |
1647 +int | |
1648 +check_float_value (enum machine_mode mode, double *d, int overflow) | |
1649 +{ | |
1650 + if (mode == SFmode) { | |
1651 + if (*d > 1.7014117331926443e+38) { | |
1652 + error("magnitude of constant too large for `float'"); | |
1653 + *d = 1.7014117331926443e+38; | |
1654 + } | |
1655 + else if (*d < -1.7014117331926443e+38) { | |
1656 + error("magnitude of constant too large for `float'"); | |
1657 + *d = -1.7014117331926443e+38; | |
1658 + } | |
1659 + else if ((*d > 0) && (*d < 2.9387358770557188e-39)) { | |
1660 + warning(WARNING_OPT "`float' constant truncated to zero"); | |
1661 + *d = 0.0; | |
1662 + } | |
1663 + else if ((*d < 0) && (*d > -2.9387358770557188e-39)) { | |
1664 + warning(WARNING_OPT "`float' constant truncated to zero"); | |
1665 + *d = 0.0; | |
1666 + } | |
1667 + } | |
1668 + return overflow; | |
1669 +} | |
1670 + | |
1671 + | |
1672 + | |
1673 +/** Declare that the target supports named output sections. */ | |
1674 +bool m6809_have_named_section = (bool)1; | |
1675 + | |
1676 + | |
1677 +/** Write to the assembler file a directive to place | |
1678 + * subsequent objects to a different section in the | |
1679 + * object file. ASxxxx uses the "area" directive for | |
1680 + * this purpose. It does not however support generalized | |
1681 + * alignment, and can only place items on an odd/even | |
1682 + * boundary. */ | |
1683 +void | |
1684 +m6809_asm_named_section ( | |
1685 + const char *name, | |
1686 + unsigned int flags ATTRIBUTE_UNUSED, | |
1687 + tree decl) | |
1688 +{ | |
1689 + fprintf (asm_out_file, "\t.area\t%s\n", name); | |
1690 +} | |
1691 + | |
1692 + | |
1693 +enum reg_class | |
1694 +m6809_preferred_reload_class (rtx x, enum reg_class regclass) | |
1695 +{ | |
1696 + /* Check cases based on type code of rtx */ | |
1697 + switch (GET_CODE(x)) | |
1698 + { | |
1699 + case CONST_INT: | |
1700 + /* Constants that can fit into 1 byte should be | |
1701 + * loaded into a Q_REGS reg */ | |
1702 + if (((unsigned) (INTVAL(x) + 0x80) < 0x100) && | |
1703 + (regclass > A_REGS)) | |
1704 + return Q_REGS; | |
1705 + | |
1706 + /* 16-bit constants should be loaded into A_REGS | |
1707 + * when possible. gcc may already require A_REGS | |
1708 + * or D_REGS for certain types of instructions. | |
1709 + * This case applies mostly to simple copy operations | |
1710 + * to/from memory when any register will do, but | |
1711 + * it's best to avoid using D register since it is | |
1712 + * needed for other things. | |
1713 + */ | |
1714 + else if (((unsigned) (INTVAL(x) + 0x80) < 0x10000) && | |
1715 + (regclass > A_REGS)) | |
1716 + return A_REGS; | |
1717 + break; | |
1718 + | |
1719 + case SYMBOL_REF: | |
1720 + case LABEL_REF: | |
1721 + /* Addresses should always be loaded into A_REGS */ | |
1722 + if (regclass >= A_REGS) | |
1723 + return (A_REGS); | |
1724 + | |
1725 + default: | |
1726 + break; | |
1727 + } | |
1728 + | |
1729 + /* Check cases based on mode of rtx */ | |
1730 + if ((GET_MODE(x) == QImode) && (regclass != A_REGS)) | |
1731 + return Q_REGS; | |
1732 + | |
1733 + /* Default: return whatever class reload suggested */ | |
1734 + return regclass; | |
1735 +} | |
1736 + | |
1737 + | |
1738 +/** | |
1739 + * Check a new declaration for the "section" attribute. | |
1740 + * If it exists, and the target section is "direct", then mark | |
1741 + * the declaration (in RTL) to indicate special treatment. | |
1742 + * When the variable is referenced later, we test for this flag | |
1743 + * and can emit special asm text to force the assembler to use | |
1744 + * short instructions. | |
1745 + */ | |
1746 +static void | |
1747 +m6809_encode_section_info (tree decl, rtx rtl, int new_decl_p ATTRIBUTE_UNUSED) | |
1748 +{ | |
1749 + tree attr, id; | |
1750 + const char *name; | |
1751 + const char *decl_name; | |
1752 + | |
1753 + /* We only care about variable declarations, not functions */ | |
1754 + if (TREE_CODE (decl) != VAR_DECL) | |
1755 + return; | |
1756 + | |
1757 + /* For debugging purposes only; grab the decl's name */ | |
1758 + decl_name = IDENTIFIER_POINTER (DECL_NAME (decl)); | |
1759 + | |
1760 + /* Give up if the decl doesn't have any RTL */ | |
1761 + if (!DECL_RTL (decl)) | |
1762 + return; | |
1763 + | |
1764 + /* See if it has a section attribute */ | |
1765 + attr = lookup_attribute ("section", DECL_ATTRIBUTES (decl)); | |
1766 + if (!attr) | |
1767 + return; | |
1768 + | |
1769 + /* See if the section attribute has a value */ | |
1770 + id = TREE_VALUE (TREE_VALUE (attr)); | |
1771 + if (!id) | |
1772 + return; | |
1773 + name = TREE_STRING_POINTER (id); | |
1774 + if (!name) | |
1775 + return; | |
1776 + | |
1777 + /* See if the value is 'direct'. If so, mark it. */ | |
1778 + if (!strcmp (name, "direct")) | |
1779 + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; | |
1780 +} | |
1781 + | |
1782 + | |
1783 +/** | |
1784 + * Output code to perform a complex shift, for which there is no | |
1785 + * direct support in the instruction set. | |
1786 + * | |
1787 + * shift1 is an instruction pattern for performing a 1-bit modification. | |
1788 + * This code wraps that pattern in a loop to perform the shift N times, | |
1789 + * where N is given by the address register in operands[2]. | |
1790 + * | |
1791 + * To support 16-bit shifts, shift2 can also be provided: it is | |
1792 + * a second instruction to be included in the loop. 8-bit shift | |
1793 + * insns will pass NULL here. | |
1794 + * | |
1795 + * The insn length of shift1/shift2 is assumed to be 1 byte, | |
1796 + * which works in all of the cases it is needed so far. | |
1797 + */ | |
1798 +static void | |
1799 +m6809_gen_register_shift ( | |
1800 + rtx *operands, | |
1801 + const char *shift1, | |
1802 + const char *shift2 ) | |
1803 +{ | |
1804 + char beq_pattern[32]; | |
1805 + char bra_pattern[32]; | |
1806 + | |
1807 + int shiftlen = (shift1 && shift2) ? 2 : 1; | |
1808 + int cmplen = (REGNO (operands[2]) == HARD_X_REGNUM) ? 3 : 4; | |
1809 + | |
1810 + int beq_offset = 2 + shiftlen + 2; | |
1811 + int bra_offset = shiftlen + 2 + cmplen + 2; | |
1812 + | |
1813 + sprintf (beq_pattern, "beq\t.+%d", beq_offset); | |
1814 + sprintf (bra_pattern, "bra\t.-%d", bra_offset); | |
1815 + | |
1816 + output_asm_insn ("pshs\t%2", operands); | |
1817 + output_asm_insn ("lea%2\t-1,%2", operands); | |
1818 + output_asm_insn ("cmp%2\t#-1", operands); | |
1819 + output_asm_insn (beq_pattern, operands); | |
1820 + if (shift1) | |
1821 + output_asm_insn (shift1, operands); | |
1822 + if (shift2) | |
1823 + output_asm_insn (shift2, operands); | |
1824 + output_asm_insn (bra_pattern, operands); | |
1825 + output_asm_insn ("puls\t%2", operands); | |
1826 +} | |
1827 + | |
1828 + | |
1829 +/** Generate RTL for the upper 8-bits of a 16-bit constant. */ | |
1830 +rtx | |
1831 +gen_rtx_const_high (rtx r) | |
1832 +{ | |
1833 + unsigned char v = (INTVAL (r) >> 8) & 0xFF; | |
1834 + signed char s = (signed char)v; | |
1835 + return gen_int_mode (s, QImode); | |
1836 +} | |
1837 + | |
1838 + | |
1839 +/** Generate RTL for the lower 8-bits of a 16-bit constant. */ | |
1840 +rtx | |
1841 +gen_rtx_const_low (rtx r) | |
1842 +{ | |
1843 + unsigned char v = INTVAL (r) & 0xFF; | |
1844 + signed char s = (signed char)v; | |
1845 + return gen_int_mode (s, QImode); | |
1846 +} | |
1847 + | |
1848 + | |
1849 +/** Generate RTL to allocate/free bytes on the stack. | |
1850 + * CODE is given as MINUS when allocating and PLUS when freeing, | |
1851 + * to match the semantics of a downward-growing stack. SIZE | |
1852 + * is always given as a positive integer. | |
1853 + */ | |
1854 +static rtx | |
1855 +gen_rtx_stack_adjust (enum rtx_code code, int size) | |
1856 +{ | |
1857 + if (size <= 0) | |
1858 + return NULL_RTX; | |
1859 + | |
1860 + if (code == MINUS) | |
1861 + size = -size; | |
1862 + | |
1863 + return gen_rtx_SET (Pmode, stack_pointer_rtx, | |
1864 + gen_rtx_PLUS (Pmode, stack_pointer_rtx, | |
1865 + gen_int_mode (size, HImode))); | |
1866 +} | |
1867 + | |
1868 + | |
1869 +/** Generate RTL to push/pop a set of registers. */ | |
1870 +rtx | |
1871 +gen_rtx_register_pushpop (int op, int regs) | |
1872 +{ | |
1873 + rtx nregs = gen_int_mode (regs, QImode); | |
1874 + | |
1875 + if (op == UNSPEC_PUSH_RS) | |
1876 + return gen_register_push (nregs); | |
1877 + else | |
1878 + return gen_register_pop (nregs); | |
1879 +} | |
1880 + | |
1881 + | |
1882 +/* Given a register set REGS, where the bit positions correspond to | |
1883 + * hard register numbers, return another bitmask that represents the | |
1884 + * order in which those registers would be pushed/popped. | |
1885 + * Registers that are pushed first have higher bit positions. | |
1886 + * The pop order is just the reverse bitmask. | |
1887 + * These values are the same as the bitmasks actually used in the | |
1888 + * machine instructions. */ | |
1889 +static unsigned int | |
1890 +register_push_order (int regs) | |
1891 +{ | |
1892 + unsigned int order = 0; | |
1893 + | |
1894 + if (REGSET_CONTAINS_P (HARD_PC_REGNUM, regs)) | |
1895 + order |= 0x80; | |
1896 + if (REGSET_CONTAINS_P (HARD_U_REGNUM, regs)) | |
1897 + order |= 0x40; | |
1898 + if (REGSET_CONTAINS_P (HARD_Y_REGNUM, regs)) | |
1899 + order |= 0x20; | |
1900 + if (REGSET_CONTAINS_P (HARD_X_REGNUM, regs)) | |
1901 + order |= 0x10; | |
1902 + if (REGSET_CONTAINS_P (HARD_DP_REGNUM, regs)) | |
1903 + order |= 0x8; | |
1904 + if (REGSET_CONTAINS_P (HARD_B_REGNUM, regs)) | |
1905 + order |= 0x4; | |
1906 + if (REGSET_CONTAINS_P (HARD_A_REGNUM, regs)) | |
1907 + order |= 0x2; | |
1908 + if (REGSET_CONTAINS_P (HARD_CC_REGNUM, regs)) | |
1909 + order |= 0x1; | |
1910 + | |
1911 + if (REGSET_CONTAINS_P (HARD_D_REGNUM, regs)) | |
1912 + order |= (0x4 | 0x2); | |
1913 + return order; | |
1914 +} | |
1915 + | |
1916 + | |
1917 +/* Returns nonzero if two consecutive push or pop instructions, | |
1918 + * as determined by the OP, can be merged into a single instruction. | |
1919 + * The first instruction in the sequence pushes/pops REGS1; the | |
1920 + * second applies to REGS2. | |
1921 + * | |
1922 + * If true, the resulting instruction can use (regs1 | regs2) | |
1923 + * safely. | |
1924 + */ | |
1925 +int | |
1926 +m6809_can_merge_pushpop_p (int op, int regs1, int regs2) | |
1927 +{ | |
1928 + /* Register sets must not overlap */ | |
1929 + if (regs1 & regs2) | |
1930 + return 0; | |
1931 + | |
1932 + if (op == UNSPEC_PUSH_RS) | |
1933 + return (register_push_order (regs1) > register_push_order (regs2)); | |
1934 + else if (op == UNSPEC_POP_RS) | |
1935 + return (register_push_order (regs1) < register_push_order (regs2)); | |
1936 + else | |
1937 + return 0; | |
1938 +} | |
1939 + | |
1940 + | |
1941 +/** Emit instructions for making a library call. | |
1942 + * MODE is the mode of the operation. | |
1943 + * NAME is the library function name. | |
1944 + * OPERANDS is the rtx array provided by the recognizer. | |
1945 + * COUNT is the number of input operands to the call, and | |
1946 + * should be 1 for a unary op or 2 for a binary op. | |
1947 + */ | |
1948 +void | |
1949 +emit_libcall_insns (enum machine_mode mode, | |
1950 + const char *name, | |
1951 + rtx *operands, | |
1952 + int count) | |
1953 +{ | |
1954 + /* Generate an rtx for the call target. */ | |
1955 + rtx symbol = gen_rtx_SYMBOL_REF (Pmode, name); | |
1956 + | |
1957 + /* Emit the library call. Slightly different based | |
1958 + on the number of operands */ | |
1959 + if (count == 2) | |
1960 + emit_library_call (symbol, LCT_NORMAL, mode, | |
1961 + 2, operands[1], mode, operands[2], mode); | |
1962 + else | |
1963 + emit_library_call (symbol, LCT_NORMAL, mode, | |
1964 + 1, operands[1], mode); | |
1965 + | |
1966 + /* The library call is expected to put its result | |
1967 + in LIBCALL_VALUE, so need to copy it into the destination. */ | |
1968 + emit_move_insn (operands[0], LIBCALL_VALUE(mode)); | |
1969 +} | |
1970 + | |
1971 + | |
1972 +/** | |
1973 + * A small helper function that writes out a single branch instruction. | |
1974 + * OPCODE is the short name, e.g. "ble". | |
1975 + * OPERANDS has the rtx for the target label. | |
1976 + * LONG_P is nonzero if we are emitting a long branch, and need to | |
1977 + * prepend an 'l' to the opcode name. | |
1978 + */ | |
1979 +void output_branch_insn1 (const char *opcode, rtx *operands, int long_p) | |
1980 +{ | |
1981 + char pattern[64]; | |
1982 + sprintf (pattern, "%s%s\t%%l0", long_p ? "l" : "", opcode); | |
1983 + output_asm_insn (pattern, operands); | |
1984 +} | |
1985 + | |
1986 +/** | |
1987 + * Output a branch/conditional branch insn of the proper | |
1988 + * length. code identifies the particular branch insn. | |
1989 + * operands holds the branch target in operands[0]. | |
1990 + * length says what the size of this insn should be. | |
1991 + * Based on the length, we know whether it should be a | |
1992 + * short (8-bit) or long (16-bit) branch. | |
1993 + */ | |
1994 +const char * | |
1995 +output_branch_insn (enum rtx_code code, rtx *operands, int length) | |
1996 +{ | |
1997 + int shortform; | |
1998 + | |
1999 + /* Decide whether or not to use the long or short form. | |
2000 + * Calculate automatically based on insn lengths. */ | |
2001 + shortform = ((length > 2) ? 0 : 1); | |
2002 + | |
2003 + /* Determine the proper opcode. | |
2004 + * Use the short (2-byte) opcode if the target is within | |
2005 + * reach. Otherwise, use jmp (3-byte opcode), unless | |
2006 + * compiling with -fpic, in which case we'll need to use | |
2007 + * lbra (4-byte opcode). | |
2008 + */ | |
2009 + switch (code) | |
2010 + { | |
2011 + case LABEL_REF: | |
2012 + if (shortform) | |
2013 + output_branch_insn1 ("bra", operands, 0); | |
2014 + else if (flag_pic) | |
2015 + output_branch_insn1 ("bra", operands, 1); | |
2016 + else | |
2017 + output_branch_insn1 ("jmp", operands, 0); | |
2018 + break; | |
2019 + case EQ: | |
2020 + output_branch_insn1 ("beq", operands, !shortform); | |
2021 + break; | |
2022 + case NE: | |
2023 + output_branch_insn1 ("bne", operands, !shortform); | |
2024 + break; | |
2025 + case GT: | |
2026 + output_branch_insn1 ("bgt", operands, !shortform); | |
2027 + break; | |
2028 + case GTU: | |
2029 + output_branch_insn1 ("bhi", operands, !shortform); | |
2030 + break; | |
2031 + case LT: | |
2032 + if (cc_prev_status.flags & CC_NO_OVERFLOW) | |
2033 + { | |
2034 + output_branch_insn1 ("bmi", operands, !shortform); | |
2035 + } | |
2036 + else | |
2037 + { | |
2038 + output_branch_insn1 ("blt", operands, !shortform); | |
2039 + } | |
2040 + break; | |
2041 + case LTU: | |
2042 + output_branch_insn1 ("blo", operands, !shortform); | |
2043 + break; | |
2044 + case GE: | |
2045 + if (cc_prev_status.flags & CC_NO_OVERFLOW) | |
2046 + { | |
2047 + output_branch_insn1 ("bpl", operands, !shortform); | |
2048 + } | |
2049 + else | |
2050 + { | |
2051 + output_branch_insn1 ("bge", operands, !shortform); | |
2052 + } | |
2053 + break; | |
2054 + case GEU: | |
2055 + output_branch_insn1 ("bhs", operands, !shortform); | |
2056 + break; | |
2057 + case LE: | |
2058 + if (cc_prev_status.flags & CC_NO_OVERFLOW) | |
2059 + { | |
2060 + output_branch_insn1 ("bmi", operands, !shortform); | |
2061 + output_branch_insn1 ("beq", operands, !shortform); | |
2062 + } | |
2063 + else | |
2064 + { | |
2065 + output_branch_insn1 ("ble", operands, !shortform); | |
2066 + } | |
2067 + break; | |
2068 + case LEU: | |
2069 + output_branch_insn1 ("bls", operands, !shortform); | |
2070 + break; | |
2071 + default: | |
2072 + abort(); | |
2073 + break; | |
2074 + } | |
2075 + return ""; | |
2076 +} | |
2077 + | |
2078 + | |
2079 +/** Returns the "cost" of an RTL expression. | |
2080 + * In general, the expression "COSTS_N_INSNS(1)" is used to represent | |
2081 + * the cost of a fast 8-bit arithmetic instruction that operates on | |
2082 + * a reg/mem or a reg/immed. Other costs are relative to this. | |
2083 + * | |
2084 + * Notes: | |
2085 + * - The cost of a REG is always zero; this cannot be changed. | |
2086 + * | |
2087 + * - On the 6809, instructions on two registers will nearly always take | |
2088 + * longer than those that operate on a register and a constant/memory, | |
2089 + * because of the way the instruction set is structured. | |
2090 + * | |
2091 + * TODO: multiply HImode by 2 should be done via shifts, instead of add. | |
2092 + */ | |
2093 +static bool | |
2094 +m6809_rtx_costs (rtx X, int code, int outer_code ATTRIBUTE_UNUSED, | |
2095 + int *total, bool speed) | |
2096 +{ | |
2097 + int has_const_arg = 0; | |
2098 + HOST_WIDE_INT const_arg; | |
2099 + enum machine_mode mode; | |
2100 + int nargs = 1; | |
2101 + rtx op0, op1; | |
2102 + | |
2103 + /* Data RTXs return a value between 0-3, depending on complexity. | |
2104 + All of these are less than COSTS_N_INSNS(1). */ | |
2105 + switch (code) | |
2106 + { | |
2107 + case CC0: | |
2108 + case PC: | |
2109 + *total = 0; | |
2110 + return true; | |
2111 + | |
2112 + case CONST_INT: | |
2113 + if (X == const0_rtx) | |
2114 + { | |
2115 + *total = 0; | |
2116 + return true; | |
2117 + } | |
2118 + else if ((unsigned) INTVAL (X) < 077) | |
2119 + { | |
2120 + *total = 1; | |
2121 + return true; | |
2122 + } | |
2123 + else | |
2124 + { | |
2125 + *total = 2; | |
2126 + return true; | |
2127 + } | |
2128 + | |
2129 + case LABEL_REF: case CONST: | |
2130 + *total = 2; | |
2131 + return true; | |
2132 + | |
2133 + case SYMBOL_REF: | |
2134 + /* References to memory are made cheaper if they have | |
2135 + * the 'direct' mode attribute set */ | |
2136 + *total = (SYMBOL_REF_FLAG (X)) ? 1 : 2; | |
2137 + return true; | |
2138 + | |
2139 + case MEM: | |
2140 + /* See what form of address was given */ | |
2141 + X = XEXP (X, 0); | |
2142 + switch (GET_CODE (X)) | |
2143 + { | |
2144 + case SYMBOL_REF: | |
2145 + *total = (SYMBOL_REF_FLAG (X)) ? 1 : 2; | |
2146 + break; | |
2147 + | |
2148 + case CONST_INT: | |
2149 + *total = 2; | |
2150 + break; | |
2151 + | |
2152 + case MEM: | |
2153 + *total = COSTS_N_INSNS (1) + 2; | |
2154 + break; | |
2155 + | |
2156 + default: | |
2157 + break; | |
2158 + } | |
2159 + return true; | |
2160 + | |
2161 + case CONST_DOUBLE: | |
2162 + /* TODO : not sure about this value. */ | |
2163 + *total = 3; | |
2164 + return true; | |
2165 + | |
2166 + default: | |
2167 + break; | |
2168 + } | |
2169 + | |
2170 + /* Decode the rtx */ | |
2171 + mode = GET_MODE (X); | |
2172 + op0 = XEXP (X, 0); | |
2173 + op1 = XEXP (X, 1); | |
2174 + | |
2175 + /* We don't implement anything in SImode or greater. */ | |
2176 + if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode)) | |
2177 + { | |
2178 + *total = COSTS_N_INSNS (100); | |
2179 + return true; | |
2180 + } | |
2181 + | |
2182 + /* Figure out if there is a constant argument, and its value. */ | |
2183 + if (GET_RTX_CLASS (code) == RTX_BIN_ARITH | |
2184 + || GET_RTX_CLASS (code) == RTX_COMM_ARITH) | |
2185 + { | |
2186 + nargs = 2; | |
2187 + if (GET_CODE (op1) == CONST_INT) | |
2188 + { | |
2189 + has_const_arg = 1; | |
2190 + const_arg = INTVAL (op1); | |
2191 + } | |
2192 + } | |
2193 + | |
2194 + /* Penalize a reg/reg operation by adding MEMORY_MOVE_COST, | |
2195 + * Ignore soft registers, since these are really in memory. | |
2196 + * | |
2197 + * TODO: penalize HImode reg/reg for most operations, except maybe | |
2198 + * additions since index registers allow for that. | |
2199 + * | |
2200 + * TODO: shifts by constant N do not always require N instructions; | |
2201 + * some of this can be done cheaper. The number of actual insns can be | |
2202 + * predicted well. | |
2203 + */ | |
2204 + if (nargs == 2 && REAL_REG_P (op0) && REAL_REG_P (op1)) | |
2205 + { | |
2206 + *total = MEMORY_MOVE_COST (mode, Q_REGS, 0); | |
2207 + } | |
2208 + else | |
2209 + { | |
2210 + *total = 0; | |
2211 + } | |
2212 + | |
2213 + /* Operator RTXs are counted as COSTS_N_INSNS(N), where N is | |
2214 + the estimated number of actual machine instructions needed to | |
2215 + perform the computation. Some small adjustments are made since | |
2216 + some "instructions" are more complex than others. */ | |
2217 + switch (code) | |
2218 + { | |
2219 + case PLUS: case MINUS: case COMPARE: | |
2220 + /* 6809 handles these natively in QImode, and in HImode as long | |
2221 + * as operand 1 is constant. */ | |
2222 + if (mode == QImode || (mode == HImode && has_const_arg)) | |
2223 + *total += COSTS_N_INSNS (1); | |
2224 + else | |
2225 + *total += COSTS_N_INSNS (GET_MODE_SIZE (mode)); | |
2226 + | |
2227 + /* -1, 0, and 1 can be done using inherent instructions | |
2228 + * for PLUS and MINUS in QImode, so don't add extra cost. */ | |
2229 + if (has_const_arg | |
2230 + && (mode == QImode || mode == HImode) | |
2231 + && (const_arg == -1 || const_arg == 0 || const_arg == 1) | |
2232 + && (code == PLUS || code == MINUS)) | |
2233 + { | |
2234 + return true; | |
2235 + } | |
2236 + break; | |
2237 + | |
2238 + case AND: case IOR: case XOR: | |
2239 + case NEG: case NOT: | |
2240 + /* 6809 handles these natively in QImode, but requires | |
2241 + * splitting in HImode. Treat these as 2 insns. */ | |
2242 + *total += COSTS_N_INSNS (1) * GET_MODE_SIZE (mode); | |
2243 + break; | |
2244 + | |
2245 + case ASHIFT: case ASHIFTRT: case LSHIFTRT: | |
2246 + case ROTATE: case ROTATERT: | |
2247 + /* 6809 can do shift/rotates of a QImode by a constant in | |
2248 + * 1 insn times the shift count, or in HImode by a constant | |
2249 + * by splitting to 2 insns. | |
2250 + * | |
2251 + * Shift by a nonconstant will take significantly longer | |
2252 + * than any of these. */ | |
2253 + if (has_const_arg) | |
2254 + { | |
2255 + const_arg %= (GET_MODE_SIZE (mode) * 8); | |
2256 + if (const_arg == 0) | |
2257 + { | |
2258 + *total += COSTS_N_INSNS(1); | |
2259 + return true; | |
2260 + } | |
2261 + | |
2262 + /* HImode shifts greater than 8 get optimized due | |
2263 + * to register transfer from b to a; this cuts down the | |
2264 + * cost. */ | |
2265 + if (const_arg >= 8) | |
2266 + { | |
2267 + *total += COSTS_N_INSNS (1); | |
2268 + const_arg -= 8; | |
2269 + } | |
2270 + | |
2271 + /* The computed cost is 'const_arg' 1-bit shifts, doubled | |
2272 + if in HImode, minus the cost of the constant itself which | |
2273 + will be added in later but really shouldn't be. */ | |
2274 + *total += COSTS_N_INSNS (const_arg) * GET_MODE_SIZE (mode) - 1; | |
2275 + return true; | |
2276 + } | |
2277 + else | |
2278 + { | |
2279 + /* It may take up to 7 iterations of about 6-7 real | |
2280 + * instructions, so make this expensive. */ | |
2281 + *total += COSTS_N_INSNS (50); | |
2282 + } | |
2283 + break; | |
2284 + | |
2285 + case MULT: | |
2286 + { | |
2287 + /* Multiply is cheap when both arguments are 8-bits. They | |
2288 + could be QImode, or QImode widened to HImode, or a constant | |
2289 + that fits into 8-bits. As long as both operands qualify, | |
2290 + we can use a single mul instruction. | |
2291 + | |
2292 + Assume that fast multiply can be used, and change this if we find | |
2293 + differently... */ | |
2294 + int ok_for_qihi3 = 1; | |
2295 + | |
2296 + /* Check the first operand */ | |
2297 + switch (GET_MODE (op0)) | |
2298 + { | |
2299 + case QImode: | |
2300 + break; | |
2301 + case HImode: | |
2302 + if (GET_CODE (op0) != SIGN_EXTEND && GET_CODE (op0) != ZERO_EXTEND) | |
2303 + ok_for_qihi3 = 0; | |
2304 + break; | |
2305 + default: | |
2306 + ok_for_qihi3 = 0; | |
2307 + break; | |
2308 + } | |
2309 + | |
2310 + /* Likewise, check the second operand. This is where constants may appear. */ | |
2311 + switch (GET_MODE (op1)) | |
2312 + { | |
2313 + case QImode: | |
2314 + break; | |
2315 + case HImode: | |
2316 + if (GET_CODE (op1) != SIGN_EXTEND && GET_CODE (op1) != ZERO_EXTEND) | |
2317 + ok_for_qihi3 = 0; | |
2318 + break; | |
2319 + case VOIDmode: | |
2320 + if (!CONST_OK_FOR_LETTER_P (const_arg, 'K')) | |
2321 + ok_for_qihi3 = 0; | |
2322 + break; | |
2323 + default: | |
2324 + ok_for_qihi3 = 0; | |
2325 + break; | |
2326 + } | |
2327 + | |
2328 + /* Fast multiply takes about 4 times as many cycles as a normal | |
2329 + arithmetic operation. Otherwise, it will take an expensive libcall. */ | |
2330 + if (ok_for_qihi3) | |
2331 + *total += COSTS_N_INSNS (4); | |
2332 + else | |
2333 + *total = COSTS_N_INSNS (50); | |
2334 + break; | |
2335 + } | |
2336 + | |
2337 + case DIV: case UDIV: case MOD: case UMOD: | |
2338 + /* These all require more expensive libcalls. */ | |
2339 + *total += COSTS_N_INSNS (100); | |
2340 + break; | |
2341 + | |
2342 + /* TODO : TRUNCATE, SIGN_EXTEND, and ZERO_EXTEND */ | |
2343 + | |
2344 + /* These can normally be done with autoincrement, etc., so | |
2345 + * don't charge for them. */ | |
2346 + case PRE_DEC: | |
2347 + case PRE_INC: | |
2348 + case POST_DEC: | |
2349 + case POST_INC: | |
2350 + break; | |
2351 + | |
2352 + default: | |
2353 + break; | |
2354 + } | |
2355 + | |
2356 + /* Always return false, and let the caller gather the costs | |
2357 + * of the operands */ | |
2358 + return false; | |
2359 +} | |
2360 + | |
2361 + | |
2362 +static tree | |
2363 +m6809_handle_fntype_attribute (tree *node, tree name, | |
2364 + tree args ATTRIBUTE_UNUSED, | |
2365 + int flags ATTRIBUTE_UNUSED, | |
2366 + bool *no_add_attrs) | |
2367 +{ | |
2368 + if (TREE_CODE (*node) != FUNCTION_TYPE) | |
2369 + { | |
2370 + warning (WARNING_OPT "'%s' only valid for functions", | |
2371 + IDENTIFIER_POINTER (name)); | |
2372 + *no_add_attrs = TRUE; | |
2373 + } | |
2374 + | |
2375 + return NULL_TREE; | |
2376 +} | |
2377 + | |
2378 + | |
2379 +static tree | |
2380 +m6809_handle_data_type_attribute (tree *node ATTRIBUTE_UNUSED, | |
2381 + tree name ATTRIBUTE_UNUSED, | |
2382 + tree args ATTRIBUTE_UNUSED, | |
2383 + int flags ATTRIBUTE_UNUSED, | |
2384 + bool *no_add_attrs ATTRIBUTE_UNUSED) | |
2385 +{ | |
2386 + return NULL_TREE; | |
2387 +} | |
2388 + | |
2389 + | |
2390 + | |
2391 +static tree | |
2392 +m6809_handle_default_attribute (tree *node ATTRIBUTE_UNUSED, | |
2393 + tree name ATTRIBUTE_UNUSED, | |
2394 + tree args ATTRIBUTE_UNUSED, | |
2395 + int flags ATTRIBUTE_UNUSED, | |
2396 + bool *no_add_attrs ATTRIBUTE_UNUSED ) | |
2397 +{ | |
2398 + return NULL_TREE; | |
2399 +} | |
2400 + | |
2401 + | |
2402 +/* Table of valid machine attributes */ | |
2403 +const struct attribute_spec m6809_attribute_table[] = { /* | |
2404 +{ name, min, max, decl, type, fntype, handler } */ | |
2405 +{ "interrupt", 0, 0, false, true, true, m6809_handle_fntype_attribute }, | |
2406 +{ "naked", 0, 0, false, true, true, m6809_handle_fntype_attribute }, | |
2407 +{ "far", 0, 1, false, true, true, m6809_handle_fntype_attribute }, | |
2408 +{ "bank", 0, 1, true, false, false, m6809_handle_default_attribute }, | |
2409 +{ "boolean", 0, 0, false, true, false, m6809_handle_data_type_attribute }, | |
2410 +{ NULL, 0, 0, false, true, false, NULL }, | |
2411 +}; | |
2412 + | |
2413 + | |
2414 +/** Initialize builtin routines for the 6809. */ | |
2415 +void | |
2416 +m6809_init_builtins (void) | |
2417 +{ | |
2418 + /* Create type trees for each function signature required. | |
2419 + * | |
2420 + * void_ftype_void = void f(void) | |
2421 + * void_ftype_uchar = void f(unsigned char) | |
2422 + * uchar_ftype_uchar2 = unsigned char f (unsigned char, unsigned char) | |
2423 + */ | |
2424 + tree void_ftype_void = | |
2425 + build_function_type (void_type_node, void_list_node); | |
2426 + | |
2427 + tree void_ftype_uchar = | |
2428 + build_function_type (void_type_node, | |
2429 + tree_cons (NULL_TREE, unsigned_char_type_node, void_list_node)); | |
2430 + | |
2431 + tree uchar_ftype_uchar2 = | |
2432 + build_function_type (unsigned_char_type_node, | |
2433 + tree_cons (NULL_TREE, unsigned_char_type_node, | |
2434 + tree_cons (NULL_TREE, unsigned_char_type_node, void_list_node))); | |
2435 + | |
2436 + /* Register each builtin function. */ | |
2437 + add_builtin_function ("__builtin_swi", void_ftype_void, | |
2438 + M6809_SWI, BUILT_IN_MD, NULL, NULL_TREE); | |
2439 + | |
2440 + add_builtin_function ("__builtin_swi2", void_ftype_void, | |
2441 + M6809_SWI2, BUILT_IN_MD, NULL, NULL_TREE); | |
2442 + | |
2443 + add_builtin_function ("__builtin_swi3", void_ftype_void, | |
2444 + M6809_SWI3, BUILT_IN_MD, NULL, NULL_TREE); | |
2445 + | |
2446 + add_builtin_function ("__builtin_cwai", void_ftype_uchar, | |
2447 + M6809_CWAI, BUILT_IN_MD, NULL, NULL_TREE); | |
2448 + | |
2449 + add_builtin_function ("__builtin_sync", void_ftype_void, | |
2450 + M6809_SYNC, BUILT_IN_MD, NULL, NULL_TREE); | |
2451 + | |
2452 + add_builtin_function ("__builtin_nop", void_ftype_void, | |
2453 + M6809_NOP, BUILT_IN_MD, NULL, NULL_TREE); | |
2454 + | |
2455 + add_builtin_function ("__builtin_blockage", void_ftype_void, | |
2456 + M6809_BLOCKAGE, BUILT_IN_MD, NULL, NULL_TREE); | |
2457 + | |
2458 + add_builtin_function ("__builtin_add_decimal", uchar_ftype_uchar2, | |
2459 + M6809_ADD_DECIMAL, BUILT_IN_MD, NULL, NULL_TREE); | |
2460 + | |
2461 + add_builtin_function ("__builtin_add_carry", uchar_ftype_uchar2, | |
2462 + M6809_ADD_CARRY, BUILT_IN_MD, NULL, NULL_TREE); | |
2463 + | |
2464 + add_builtin_function ("__builtin_sub_carry", uchar_ftype_uchar2, | |
2465 + M6809_SUB_CARRY, BUILT_IN_MD, NULL, NULL_TREE); | |
2466 +} | |
2467 + | |
2468 + | |
2469 +/** Used by m6809_expand_builtin, given a tree ARGLIST which | |
2470 + * refers to the operands of a builtin call, return an rtx | |
2471 + * that represents the nth operand, as denoted by OPNUM, which | |
2472 + * is a zero-based integer. MODE gives the expected mode | |
2473 + * of the operand. | |
2474 + * | |
2475 + * This rtx is suitable for use in the emitted RTL for the | |
2476 + * builtin instruction. */ | |
2477 +rtx | |
2478 +m6809_builtin_operand (tree arglist, enum machine_mode mode, int opnum) | |
2479 +{ | |
2480 + tree arg; | |
2481 + rtx r; | |
2482 + | |
2483 + arg = CALL_EXPR_ARG (arglist, opnum); | |
2484 + | |
2485 + /* Convert the tree to RTL */ | |
2486 + r = expand_expr (arg, NULL_RTX, mode, EXPAND_NORMAL); | |
2487 + if (r == NULL_RTX) | |
2488 + return NULL_RTX; | |
2489 + return r; | |
2490 +} | |
2491 + | |
2492 + | |
2493 +/** Expand a builtin that was registered in init_builtins into | |
2494 + * RTL. */ | |
2495 +rtx | |
2496 +m6809_expand_builtin (tree exp, | |
2497 + rtx target, | |
2498 + rtx subtarget ATTRIBUTE_UNUSED, | |
2499 + enum machine_mode mode ATTRIBUTE_UNUSED, | |
2500 + int ignore ATTRIBUTE_UNUSED ) | |
2501 +{ | |
2502 + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); | |
2503 + tree arglist = exp; | |
2504 + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); | |
2505 + rtx r0, r1; | |
2506 + | |
2507 + switch (fcode) | |
2508 + { | |
2509 + case M6809_SWI: | |
2510 + r0 = gen_rtx_CONST_INT (VOIDmode, 1); | |
2511 + emit_insn (target = gen_m6809_swi (r0)); | |
2512 + return target; | |
2513 + | |
2514 + case M6809_SWI2: | |
2515 + r0 = gen_rtx_CONST_INT (VOIDmode, 2); | |
2516 + emit_insn (target = gen_m6809_swi (r0)); | |
2517 + return target; | |
2518 + | |
2519 + case M6809_SWI3: | |
2520 + r0 = gen_rtx_CONST_INT (VOIDmode, 3); | |
2521 + emit_insn (target = gen_m6809_swi (r0)); | |
2522 + return target; | |
2523 + | |
2524 + case M6809_CWAI: | |
2525 + r0 = m6809_builtin_operand (arglist, QImode, 0); | |
2526 + emit_insn (target = gen_m6809_cwai (r0)); | |
2527 + return target; | |
2528 + | |
2529 + case M6809_SYNC: | |
2530 + emit_insn (target = gen_m6809_sync ()); | |
2531 + return target; | |
2532 + | |
2533 + case M6809_ADD_CARRY: | |
2534 + r0 = m6809_builtin_operand (arglist, QImode, 0); | |
2535 + r1 = m6809_builtin_operand (arglist, QImode, 1); | |
2536 + if (!target) | |
2537 + target = gen_reg_rtx (QImode); | |
2538 + emit_insn (gen_addqi3_carry (target, r0, r1)); | |
2539 + return target; | |
2540 + | |
2541 + case M6809_SUB_CARRY: | |
2542 + r0 = m6809_builtin_operand (arglist, QImode, 0); | |
2543 + r1 = m6809_builtin_operand (arglist, QImode, 1); | |
2544 + if (!target) | |
2545 + target = gen_reg_rtx (QImode); | |
2546 + emit_insn (gen_subqi3_carry (target, r0, r1)); | |
2547 + return target; | |
2548 + | |
2549 + case M6809_NOP: | |
2550 + emit_insn (target = gen_nop ()); | |
2551 + return target; | |
2552 + | |
2553 + case M6809_BLOCKAGE: | |
2554 + emit_insn (target = gen_blockage ()); | |
2555 + return target; | |
2556 + | |
2557 + case M6809_ADD_DECIMAL: | |
2558 + r0 = m6809_builtin_operand (arglist, QImode, 0); | |
2559 + r1 = m6809_builtin_operand (arglist, QImode, 1); | |
2560 + if (!target) | |
2561 + target = gen_reg_rtx (QImode); | |
2562 + emit_insn (gen_addqi3_decimal (target, r0, r1)); | |
2563 + return target; | |
2564 + | |
2565 + default: | |
2566 + warning (WARNING_OPT "unknown builtin expansion ignored"); | |
2567 + return NULL_RTX; | |
2568 + } | |
2569 +} | |
2570 + | |
2571 + | |
2572 + | |
2573 +/* Returns nonzero if 'x' represents a function that was declared | |
2574 + * as __noreturn__. */ | |
2575 +int | |
2576 +noreturn_functionp (rtx x) | |
2577 +{ | |
2578 + tree decl = call_target_decl (x); | |
2579 + | |
2580 + if (decl == NULL_TREE) | |
2581 + return 0; | |
2582 + else | |
2583 + return TREE_THIS_VOLATILE (decl); | |
2584 +} | |
2585 + | |
2586 + | |
2587 +const char * | |
2588 +far_function_type_p (tree type) | |
2589 +{ | |
2590 + tree attr; | |
2591 + const char *page; | |
2592 + | |
2593 + /* Return whether or not this decl has the far attribute */ | |
2594 + attr = lookup_attribute ("far", TYPE_ATTRIBUTES (type)); | |
2595 + if (attr == NULL_TREE) | |
2596 + return NULL; | |
2597 + | |
2598 + /* If it is far, check for a value */ | |
2599 + attr = TREE_VALUE (attr); | |
2600 + if (attr == NULL_TREE) | |
2601 + { | |
2602 + warning (WARNING_OPT "far code page not specified, using local value"); | |
2603 + return far_code_page; | |
2604 + } | |
2605 + | |
2606 + /* We have a TREE_LIST of attribute values, get the first one. | |
2607 + * It should be an INTEGER_CST. */ | |
2608 + attr = TREE_VALUE (attr); | |
2609 + page = TREE_STRING_POINTER (attr); | |
2610 + return page; | |
2611 +} | |
2612 + | |
2613 + | |
2614 +/* For a far function, returns the identifier that states which page | |
2615 + * it resides in. Otherwise, returns NULL for ordinary functions. */ | |
2616 +const char * | |
2617 +far_functionp (rtx x) | |
2618 +{ | |
2619 + tree decl, decl_type; | |
2620 + const char *page; | |
2621 + | |
2622 + /* Find the FUNCTION_DECL corresponding to the rtx being called. */ | |
2623 + decl = call_target_decl (x); | |
2624 + if (decl == NULL_TREE) | |
2625 + return NULL; | |
2626 + | |
2627 + /* See if the function has the new 'banked' attribute. These | |
2628 + * are numeric instead of text */ | |
2629 + page = m6809_get_decl_bank (decl); | |
2630 + if (page) | |
2631 + return page; | |
2632 + | |
2633 + /* No, lookup the type of the function and see if the type | |
2634 + * specifies far or not. */ | |
2635 + decl_type = TREE_TYPE (decl); | |
2636 + if (decl_type == NULL_TREE) | |
2637 + return NULL; | |
2638 + return far_function_type_p (decl_type); | |
2639 +} | |
2640 + | |
2641 + | |
2642 + | |
2643 +/** Outputs the assembly language for a far call. */ | |
2644 +void | |
2645 +output_far_call_insn (rtx *operands, int has_return) | |
2646 +{ | |
2647 + static char page_data[64]; | |
2648 + const char *called_page; | |
2649 + | |
2650 + /* The logic is the same for functions whether or not there | |
2651 + * is a return value. Skip over the return value in this | |
2652 + * case, so that the call location is always operands[0]. */ | |
2653 + if (has_return) | |
2654 + operands++; | |
2655 + | |
2656 + /* Get the name of the page being called */ | |
2657 + called_page = far_functionp (operands[0]); | |
2658 + | |
2659 +#if 0 /* TODO : broken logic */ | |
2660 + /* See if the called page name is a 'bank' */ | |
2661 + if (isdigit (*called_page)) | |
2662 + { | |
2663 + /* New style banking */ | |
2664 + if (!strcmp (called_page, current_bank_name)) | |
2665 + { | |
2666 + /* Same page */ | |
2667 + output_asm_insn ("jsr\t%0", operands); | |
2668 + } | |
2669 + else | |
2670 + { | |
2671 + /* Different page */ | |
2672 + output_asm_insn ("jsr\t__far_call_handler\t;new style", operands); | |
2673 + output_asm_insn ("\t.dw\t%0", operands); | |
2674 + sprintf (page_data, "\t.db\t%s", called_page); | |
2675 + output_asm_insn (page_data, operands); | |
2676 + } | |
2677 + return; | |
2678 + } | |
2679 +#endif | |
2680 + | |
2681 + /* Are we calling a different page than we are running in? */ | |
2682 + if (!strcmp (called_page, far_code_page)) | |
2683 + { | |
2684 + /* Same page : no need to execute a far call */ | |
2685 + if (flag_pic) | |
2686 + output_asm_insn ("lbsr\t%C0", operands); | |
2687 + else | |
2688 + output_asm_insn ("jsr\t%0", operands); | |
2689 + } | |
2690 + else | |
2691 + { | |
2692 + /* Different page : need to emit far call thunk */ | |
2693 + | |
2694 + /* First output a call to the thunk for making far calls. */ | |
2695 + if (flag_pic) | |
2696 + output_asm_insn ("lbsr\t__far_call_handler", operands); | |
2697 + else | |
2698 + output_asm_insn ("jsr\t__far_call_handler\t;old style", operands); | |
2699 + | |
2700 + /* Now output the name of the call site */ | |
2701 + output_asm_insn ("\t.dw\t%C0", operands); | |
2702 + | |
2703 + /* Finally output the page number */ | |
2704 + sprintf (page_data, "\t.db\t%s", far_functionp (operands[0])); | |
2705 + output_asm_insn (page_data, operands); | |
2706 + } | |
2707 +} | |
2708 + | |
2709 + | |
2710 +int | |
2711 +m6809_init_cumulative_args (CUMULATIVE_ARGS cum ATTRIBUTE_UNUSED, | |
2712 + tree fntype, | |
2713 + rtx libname ATTRIBUTE_UNUSED) | |
2714 +{ | |
2715 + cum = 0; | |
2716 + | |
2717 + /* For far functions, the current implementation does not allow for | |
2718 + * stack parameters. So note whenever the called function is far | |
2719 + * and in a different page than the current one; such a function | |
2720 + * should give an error if a stack parameter is generated. */ | |
2721 + if (fntype) | |
2722 + { | |
2723 + const char *called_page = far_function_type_p (fntype); | |
2724 + if (called_page && strcmp (called_page, far_code_page) && !TARGET_FAR_STACK_PARAM) | |
2725 + cum |= CUM_STACK_INVALID; | |
2726 + } | |
2727 + | |
2728 + if (fntype && TYPE_ARG_TYPES (fntype) != 0 && | |
2729 + (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)) | |
2730 + { | |
2731 + /* has variable arguments, cannot use registers */ | |
2732 + cum |= (CUM_X_MASK | CUM_B_MASK | CUM_STACK_ONLY); | |
2733 + } | |
2734 + | |
2735 + if (m6809_abi_version == M6809_ABI_VERSION_STACK) | |
2736 + { | |
2737 + /* cannot use registers ; only use the stack */ | |
2738 + cum |= (CUM_STACK_ONLY | CUM_X_MASK | CUM_B_MASK); | |
2739 + } | |
2740 + | |
2741 + return cum; | |
2742 +} | |
2743 + | |
2744 + | |
2745 +rtx | |
2746 +m6809_function_arg_on_stack (CUMULATIVE_ARGS *cump) | |
2747 +{ | |
2748 + if (*cump & CUM_STACK_INVALID) | |
2749 + { | |
2750 + *cump &= ~CUM_STACK_INVALID; | |
2751 + error ("far function needs stack, will not work"); | |
2752 + } | |
2753 + return NULL_RTX; | |
2754 +} | |
2755 + | |
2756 +void m6809_asm_trampoline_template(FILE *f) | |
2757 +{ | |
2758 + fprintf(f, "ldy #0000\n"); | |
2759 + fprintf(f, "jmp 0x0000\n"); | |
2760 +} | |
2761 + | |
2762 +/* | |
2763 + * Trampoline output: | |
2764 + * | |
2765 + * ldu #&cxt 4 bytes --LDY- ?? ?? | |
2766 + * jmp fnaddr 3 bytes JMP ?? ?? | |
2767 + */ | |
2768 +void | |
2769 +m6809_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt) | |
2770 +{ | |
2771 + rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); | |
2772 + /* TODO - optimize by generating the entire trampoline code here, | |
2773 + * and removing the template altogether, since there are only two | |
2774 + * bytes there that matter. */ | |
2775 + emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt); | |
2776 + emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 5)), fnaddr); | |
2777 +} | |
2778 + | |
2779 + | |
2780 +/** Echo the version of the compiler and the name of the source file | |
2781 + * at the beginning of each assembler output file. asm_out_file | |
2782 + * is a global FILE * pointing to the output stream. */ | |
2783 +void | |
2784 +m6809_asm_file_start (void) | |
2785 +{ | |
2786 + const char *module_name; | |
2787 + | |
2788 + fprintf (asm_out_file, "\n;;; gcc for m6809 : %s %s\n", | |
2789 + __DATE__, __TIME__); | |
2790 + fprintf (asm_out_file, ";;; %s\n", version_string); | |
2791 + | |
2792 + fprintf (asm_out_file, ";;; ABI version %d\n", m6809_abi_version); | |
2793 + fprintf (asm_out_file, ";;; %s\n", | |
2794 + (TARGET_BYTE_INT ? "-mint8" : "-mint16")); | |
2795 + if (TARGET_EXPERIMENT) | |
2796 + fprintf (asm_out_file, ";;; -mexperiment\n"); | |
2797 + if (TARGET_WPC) | |
2798 + fprintf (asm_out_file, ";;; -mwpc\n"); | |
2799 + if (TARGET_6309) | |
2800 + fprintf (asm_out_file, ";;; -m6309\n"); | |
2801 + | |
2802 + /* Print the name of the module, which is taken as the base name | |
2803 + * of the input file. | |
2804 + * See the 'User-Defined Symbols' section of the assembler | |
2805 + * documentation for the rules on valid symbols. | |
2806 + */ | |
2807 + module_name = lbasename (main_input_filename); | |
2808 + | |
2809 + fprintf (asm_out_file, "\t.module\t"); | |
2810 + | |
2811 + if (*module_name >= '0' && *module_name <= '9') | |
2812 + fprintf (asm_out_file, "_"); | |
2813 + | |
2814 + while (*module_name) | |
2815 + { | |
2816 + if ((*module_name >= '0' && *module_name <= '9') | |
2817 + || (*module_name >= 'A' && *module_name <= 'Z') | |
2818 + || (*module_name >= 'a' && *module_name <= 'z') | |
2819 + || *module_name == '$' | |
2820 + || *module_name == '.' | |
2821 + || *module_name == '_') | |
2822 + { | |
2823 + fprintf (asm_out_file, "%c", *module_name); | |
2824 + } | |
2825 + else | |
2826 + { | |
2827 + fprintf (asm_out_file, "_"); | |
2828 + } | |
2829 + module_name++; | |
2830 + } | |
2831 + | |
2832 + fprintf (asm_out_file, "\n"); | |
2833 +} | |
2834 + | |
2835 + | |
2836 +/** Returns true if prologue/epilogue code is required for the | |
2837 + * current function being compiled. | |
2838 + * | |
2839 + * This is just the inverse of whether the function is declared as | |
2840 + * 'naked'. | |
2841 + */ | |
2842 +int | |
2843 +prologue_epilogue_required (void) | |
2844 +{ | |
2845 + return !m6809_current_function_has_type_attr_p ("naked") | |
2846 + && !m6809_current_function_has_type_attr_p ("noreturn"); | |
2847 +} | |
2848 + | |
2849 + | |
2850 +/** Expand RTL for function entry */ | |
2851 +void | |
2852 +emit_prologue_insns (void) | |
2853 +{ | |
2854 + rtx insn; | |
2855 + unsigned int live_regs = m6809_get_live_regs (); | |
2856 + unsigned int frame_size = get_frame_size (); | |
2857 + | |
2858 + /* Save all registers used, including the frame pointer */ | |
2859 + if (live_regs && !m6809_current_function_has_type_attr_p ("interrupt")) | |
2860 + { | |
2861 + insn = emit_insn ( | |
2862 + gen_rtx_register_pushpop (UNSPEC_PUSH_RS, live_regs)); | |
2863 + RTX_FRAME_RELATED_P (insn) = 1; | |
2864 + } | |
2865 + | |
2866 + /* Allocate space for local variables */ | |
2867 + if (frame_size != 0) | |
2868 + { | |
2869 + insn = emit_insn (gen_rtx_stack_adjust (MINUS, frame_size)); | |
2870 + RTX_FRAME_RELATED_P (insn) = 1; | |
2871 + } | |
2872 + | |
2873 + /* Set the frame pointer if it is needed */ | |
2874 + if (frame_pointer_needed) | |
2875 + { | |
2876 + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); | |
2877 + RTX_FRAME_RELATED_P (insn) = 1; | |
2878 + } | |
2879 +} | |
2880 + | |
2881 + | |
2882 +/** Expand RTL for function exit */ | |
2883 +void | |
2884 +emit_epilogue_insns (bool sibcall_p) | |
2885 +{ | |
2886 + unsigned int live_regs = m6809_get_live_regs (); | |
2887 + unsigned int frame_size = get_frame_size (); | |
2888 + | |
2889 + if (frame_size != 0) | |
2890 + emit_insn (gen_rtx_stack_adjust (PLUS, frame_size)); | |
2891 + | |
2892 + if (sibcall_p) | |
2893 + { | |
2894 + if (live_regs) | |
2895 + emit_insn (gen_rtx_register_pushpop (UNSPEC_POP_RS, live_regs)); | |
2896 + } | |
2897 + else | |
2898 + { | |
2899 + if (live_regs && !m6809_current_function_has_type_attr_p ("interrupt")) | |
2900 + emit_insn ( | |
2901 + gen_rtx_register_pushpop (UNSPEC_POP_RS, PC_REGBIT | live_regs)); | |
2902 + | |
2903 + if (m6809_current_function_has_type_attr_p ("interrupt")) | |
2904 + emit_jump_insn (gen_return_rti ()); | |
2905 + else | |
2906 + emit_jump_insn (gen_return_rts ()); | |
2907 + } | |
2908 +} | |
2909 + | |
2910 +#if 0 | |
2911 +/** Predefine some preprocessor names according to the currently | |
2912 + * selected compiler options */ | |
2913 +void | |
2914 +m6809_cpu_cpp_builtins (void) | |
2915 +{ | |
2916 + if (TARGET_6309) | |
2917 + { | |
2918 + builtin_define_std ("__M6309__"); | |
2919 + builtin_define_std ("__m6309__"); | |
2920 + } | |
2921 + else | |
2922 + { | |
2923 + builtin_define_std ("__M6809__"); | |
2924 + builtin_define_std ("__m6809__"); | |
2925 + } | |
2926 + | |
2927 + if (TARGET_BYTE_INT) | |
2928 + builtin_define_std ("__int8__"); | |
2929 + else | |
2930 + builtin_define_std ("__int16__"); | |
2931 + | |
2932 + switch (m6809_abi_version) | |
2933 + { | |
2934 + case M6809_ABI_VERSION_STACK: | |
2935 + builtin_define_std ("__regargs__"); | |
2936 + builtin_define_std ("__ABI_STACK__"); | |
2937 + break; | |
2938 + case M6809_ABI_VERSION_REGS: | |
2939 + builtin_define_std ("__ABI_REGS__"); | |
2940 + break; | |
2941 + case M6809_ABI_VERSION_BX: | |
2942 + builtin_define_std ("__ABI_BX__"); | |
2943 + break; | |
2944 + default: | |
2945 + break; | |
2946 + } | |
2947 + | |
2948 + if (TARGET_WPC) | |
2949 + builtin_define_std ("__WPC__"); | |
2950 + | |
2951 + if (TARGET_DRET) | |
2952 + builtin_define_std ("__DRET__"); | |
2953 +} | |
2954 +#endif | |
2955 + | |
2956 +#define MAX_ASM_ASCII_STRING 48 | |
2957 + | |
2958 +void | |
2959 +m6809_output_ascii (FILE *fp, const char *str, unsigned long size) | |
2960 +{ | |
2961 + unsigned long i; | |
2962 + bool use_ascii = true; | |
2963 + | |
2964 + /* If the size is too large, then break this up into multiple | |
2965 + outputs. The assembler can only output roughly 48 bytes at a | |
2966 + time. Note that if there are lots of escape sequences in | |
2967 + the string, this may fail. */ | |
2968 + if (size > MAX_ASM_ASCII_STRING) | |
2969 + { | |
2970 + m6809_output_ascii (fp, str, MAX_ASM_ASCII_STRING); | |
2971 + m6809_output_ascii (fp, str + MAX_ASM_ASCII_STRING, | |
2972 + size - MAX_ASM_ASCII_STRING); | |
2973 + return; | |
2974 + } | |
2975 + | |
2976 + /* Check for 8-bit codes, which cannot be embedded in an .ascii */ | |
2977 + for (i = 0; i < size; i++) | |
2978 + { | |
2979 + int c = str[i] & 0377; | |
2980 + if (c >= 0x80) | |
2981 + { | |
2982 + use_ascii = false; | |
2983 + break; | |
2984 + } | |
2985 + } | |
2986 + | |
2987 + if (use_ascii) | |
2988 + fprintf (fp, "\t.ascii \""); | |
2989 + | |
2990 + for (i = 0; i < size; i++) | |
2991 + { | |
2992 + int c = str[i] & 0377; | |
2993 + | |
2994 + if (use_ascii) | |
2995 + { | |
2996 + /* Just output the plain character if it is printable, | |
2997 + otherwise output the escape code for the character. | |
2998 + The assembler recognizes the same C-style octal escape sequences, | |
2999 + except that it only supports 7-bit codes. */ | |
3000 + if (c >= ' ' && c < 0177 && c != '\\' && c != '"') | |
3001 + putc (c, fp); | |
3002 + else switch (c) | |
3003 + { | |
3004 + case '\n': | |
3005 +#ifndef TARGET_COCO | |
3006 + fputs ("\\n", fp); | |
3007 + break; | |
3008 +#endif | |
3009 + /* On the CoCo, we fallthrough and treat '\n' like '\r'. */ | |
3010 + case '\r': | |
3011 + fputs ("\\r", fp); | |
3012 + break; | |
3013 + case '\t': | |
3014 + fputs ("\\t", fp); | |
3015 + break; | |
3016 + case '\f': | |
3017 + fputs ("\\f", fp); | |
3018 + break; | |
3019 + case 0: | |
3020 + fputs ("\\0", fp); | |
3021 + break; | |
3022 + default: | |
3023 + fprintf (fp, "\\%03o", c); | |
3024 + break; | |
3025 + } | |
3026 + } | |
3027 + else | |
3028 + { | |
3029 + fprintf (fp, "\t.byte\t0x%02X\n", c); | |
3030 + } | |
3031 + } | |
3032 + | |
3033 + if (use_ascii) | |
3034 + fprintf (fp, "\"\n"); | |
3035 +} | |
3036 + | |
3037 + | |
3038 +void | |
3039 +m6809_output_quoted_string (FILE *asm_file, const char *string) | |
3040 +{ | |
3041 + char c; | |
3042 + | |
3043 + if (strlen (string) > MAX_ASM_ASCII_STRING) | |
3044 + { | |
3045 + /* The string length is too large. We'll have to truncate it. | |
3046 + This is only called from debugging functions, so it's usually | |
3047 + not critical. */ | |
3048 + | |
3049 + char truncated_string[MAX_ASM_ASCII_STRING+1]; | |
3050 + | |
3051 + /* Copy as many characters as we can. */ | |
3052 + strncpy (truncated_string, string, MAX_ASM_ASCII_STRING); | |
3053 + truncated_string[MAX_ASM_ASCII_STRING] = '\0'; | |
3054 + string = truncated_string; | |
3055 + } | |
3056 + | |
3057 + /* Copied from toplev.c */ | |
3058 + | |
3059 + putc ('\"', asm_file); | |
3060 + while ((c = *string++) != 0) { | |
3061 + if (ISPRINT (c)) { | |
3062 + if (c == '\"' || c == '\\') | |
3063 + putc ('\\', asm_file); | |
3064 + putc (c, asm_file); | |
3065 + } | |
3066 + else | |
3067 + fprintf (asm_file, "\\%03o", (unsigned char) c); | |
3068 + } | |
3069 + putc ('\"', asm_file); | |
3070 +} | |
3071 + | |
3072 + | |
3073 +/** Output the assembly code for a shift instruction where the | |
3074 + * shift count is not constant. */ | |
3075 +void | |
3076 +m6809_output_shift_insn (int rtx_code, rtx *operands) | |
3077 +{ | |
3078 + struct shift_opcode *op; | |
3079 + | |
3080 + if (GET_CODE (operands[2]) == CONST_INT) | |
3081 + abort (); | |
3082 + | |
3083 + if (optimize_size && GET_MODE (operands[0]) == HImode) | |
3084 + { | |
3085 + switch (rtx_code) | |
3086 + { | |
3087 + case ASHIFT: | |
3088 + output_asm_insn ("jsr\t_ashlhi3", operands); | |
3089 + break; | |
3090 + case ASHIFTRT: | |
3091 + output_asm_insn ("jsr\t_ashrhi3", operands); | |
3092 + break; | |
3093 + case LSHIFTRT: | |
3094 + output_asm_insn ("jsr\t_lshrhi3", operands); | |
3095 + break; | |
3096 + } | |
3097 + } | |
3098 + else if (GET_MODE (operands[0]) == HImode) | |
3099 + { | |
3100 + switch (rtx_code) | |
3101 + { | |
3102 + case ASHIFT: | |
3103 + m6809_gen_register_shift (operands, "aslb", "rola"); | |
3104 + break; | |
3105 + case ASHIFTRT: | |
3106 + m6809_gen_register_shift (operands, "asra", "rorb"); | |
3107 + break; | |
3108 + case LSHIFTRT: | |
3109 + m6809_gen_register_shift (operands, "lsra", "rorb"); | |
3110 + break; | |
3111 + } | |
3112 + } | |
3113 + else | |
3114 + { | |
3115 + switch (rtx_code) | |
3116 + { | |
3117 + case ASHIFT: | |
3118 + m6809_gen_register_shift (operands, "aslb", NULL); | |
3119 + break; | |
3120 + case ASHIFTRT: | |
3121 + m6809_gen_register_shift (operands, "asrb", NULL); | |
3122 + break; | |
3123 + case LSHIFTRT: | |
3124 + m6809_gen_register_shift (operands, "lsrb", NULL); | |
3125 + break; | |
3126 + } | |
3127 + } | |
3128 +} | |
3129 + | |
3130 + | |
3131 +void | |
3132 +m6809_emit_move_insn (rtx dst, rtx src) | |
3133 +{ | |
3134 + emit_insn (gen_rtx_SET (VOIDmode, dst, src)); | |
3135 + if (ACC_A_REG_P (dst)) | |
3136 + emit_insn (gen_rtx_USE (VOIDmode, dst)); | |
3137 +} | |
3138 + | |
3139 + | |
3140 +/** Split a complex shift instruction into multiple CPU | |
3141 + * shift instructions. */ | |
3142 +void | |
3143 +m6809_split_shift (enum rtx_code code, rtx *operands) | |
3144 +{ | |
3145 + enum machine_mode mode; | |
3146 + int count; | |
3147 + | |
3148 + mode = GET_MODE (operands[0]); | |
3149 + count = INTVAL (operands[2]); | |
3150 + | |
3151 + /* Handle a shift count outside the range of 0 .. N-1, where | |
3152 + * N is the mode size in bits. We normalize the count, and | |
3153 + * for negative counts we also invert the direction of the | |
3154 + * shift. */ | |
3155 + if ((count < 0) || (count >= 8 * GET_MODE_SIZE (mode))) | |
3156 + { | |
3157 + if (count < 0) | |
3158 + { | |
3159 + count = -count; | |
3160 + code = (code == ASHIFT) ? ASHIFTRT : ASHIFT; | |
3161 + } | |
3162 + count %= (8 * GET_MODE_SIZE (mode)); | |
3163 + m6809_emit_move_insn (operands[0], | |
3164 + gen_rtx_fmt_ee (code, mode, operands[1], | |
3165 + gen_rtx_CONST_INT (VOIDmode, count))); | |
3166 + } | |
3167 + | |
3168 + /* Handle shift by zero explicitly as a no-op. */ | |
3169 + if (count == 0) | |
3170 + { | |
3171 + emit_insn (gen_nop ()); | |
3172 + return; | |
3173 + } | |
3174 + | |
3175 + /* Decompose the shift by a constant N > 8 into two | |
3176 + * shifts, first by 8 and then by N-8. | |
3177 + * This "speeds up" the process for large shifts that would be | |
3178 + * handled below, but allows for some optimization. | |
3179 + * In some cases shift by 8 can be implemented fast. If an | |
3180 + * instruction to shift by 8 is defined, it will be used here; | |
3181 + * otherwise it will be further decomposed as below. */ | |
3182 + if (mode == HImode && count > 8) | |
3183 + { | |
3184 + rtx output = operands[0]; | |
3185 + | |
3186 + m6809_emit_move_insn (operands[0], | |
3187 + gen_rtx_fmt_ee (code, mode, operands[1], | |
3188 + gen_rtx_CONST_INT (VOIDmode, 8))); | |
3189 + | |
3190 + /* Unsigned shifts always produce a zero in either the | |
3191 + * upper or lower half of the output; then, that part | |
3192 + * does not need to be shifted anymore. We modify the | |
3193 + * output and the subsequent instructions to operate in | |
3194 + * QImode only on the relevant part. */ | |
3195 + if (REG_P (output)) | |
3196 + { | |
3197 + if (code == ASHIFT) | |
3198 + { | |
3199 + output = gen_rtx_REG (QImode, HARD_A_REGNUM); | |
3200 + mode = QImode; | |
3201 + } | |
3202 + else | |
3203 + { | |
3204 + output = gen_rtx_REG (QImode, HARD_D_REGNUM); | |
3205 + mode = QImode; | |
3206 + } | |
3207 + } | |
3208 + | |
3209 + m6809_emit_move_insn (output, | |
3210 + gen_rtx_fmt_ee (code, mode, copy_rtx (output), | |
3211 + gen_rtx_CONST_INT (VOIDmode, count-8))); | |
3212 + return; | |
3213 + } | |
3214 + | |
3215 + /* Rewrite the unsigned shift of an 8-bit register by a large constant N | |
3216 + * (near to the maximum of 8) as a rotate and mask. */ | |
3217 + if (mode == QImode && REG_P (operands[0]) && count >= ((code == ASHIFTRT) ? 7 : 6)) | |
3218 + { | |
3219 + unsigned int mask; | |
3220 + unsigned int was_signed = (code == ASHIFTRT); | |
3221 + | |
3222 + code = (code == ASHIFT) ? ROTATERT : ROTATE; | |
3223 + if (code == ROTATE) | |
3224 + mask = (count == 6) ? 0x03 : 0x01; | |
3225 + else | |
3226 + mask = (count == 6) ? 0xC0 - 0x100 : 0x80 - 0x100; | |
3227 + count = 9 - count; | |
3228 + | |
3229 + do { | |
3230 + m6809_emit_move_insn (operands[0], | |
3231 + gen_rtx_fmt_ee (code, QImode, operands[1], const1_rtx)); | |
3232 + } while (--count != 0); | |
3233 + | |
3234 + m6809_emit_move_insn (operands[0], | |
3235 + gen_rtx_fmt_ee (AND, QImode, operands[1], | |
3236 + gen_rtx_CONST_INT (VOIDmode, mask))); | |
3237 + | |
3238 + if (was_signed) | |
3239 + { | |
3240 + emit_insn (gen_negqi2 (operands[0], copy_rtx (operands[0]))); | |
3241 + if (ACC_A_REG_P (operands[0])) | |
3242 + emit_insn (gen_rtx_USE (VOIDmode, operands[0])); | |
3243 + } | |
3244 + return; | |
3245 + } | |
3246 + | |
3247 + /* Decompose the shift by any constant N > 1 into a sequence | |
3248 + * of N shifts. | |
3249 + * This is done recursively, by creating a shift by 1 and a | |
3250 + * shift by N-1, as long as N>1. */ | |
3251 + if (count > 1) | |
3252 + { | |
3253 + m6809_emit_move_insn (operands[0], | |
3254 + gen_rtx_fmt_ee (code, mode, operands[1], const1_rtx)); | |
3255 + | |
3256 + m6809_emit_move_insn (operands[0], | |
3257 + gen_rtx_fmt_ee (code, mode, operands[1], | |
3258 + gen_rtx_CONST_INT (VOIDmode, count-1))); | |
3259 + return; | |
3260 + } | |
3261 + | |
3262 + /* Decompose the single shift of a 16-bit quantity into two | |
3263 + * CPU instructions, one for each 8-bit half. | |
3264 + */ | |
3265 + if (mode == HImode && count == 1) | |
3266 + { | |
3267 + rtx first, second; | |
3268 + enum rtx_code rotate_code; | |
3269 + | |
3270 + rotate_code = (code == ASHIFT) ? ROTATE : ROTATERT; | |
3271 + | |
3272 + /* Split the operand into two 8-bit entities. | |
3273 + * FIRST is the one that will get shifted via a regular CPU | |
3274 + * instruction. | |
3275 + * SECOND is the one that will have the result of the first shift | |
3276 + * rotated in. | |
3277 + * | |
3278 + * We initialize first and second as if we are doing a left shift, | |
3279 + * then swap the operands if it's a right shift. | |
3280 + */ | |
3281 + if (REG_P (operands[0])) | |
3282 + { | |
3283 + first = gen_rtx_REG (QImode, HARD_D_REGNUM); /* HARD_B_REGNUM? */ | |
3284 + second = gen_rtx_REG (QImode, HARD_A_REGNUM); | |
3285 + } | |
3286 + else | |
3287 + { | |
3288 + first = adjust_address (operands[0], QImode, 1); | |
3289 + second = adjust_address (operands[0], QImode, 0); | |
3290 + } | |
3291 + | |
3292 + if (rotate_code == ROTATERT) | |
3293 + { | |
3294 + rtx tmp; tmp = first; first = second; second = tmp; | |
3295 + } | |
3296 + | |
3297 + /* Decompose into a shift and a rotate instruction. */ | |
3298 + m6809_emit_move_insn (first, | |
3299 + gen_rtx_fmt_ee (code, QImode, copy_rtx (first), const1_rtx)); | |
3300 + m6809_emit_move_insn (second, | |
3301 + gen_rtx_fmt_ee (rotate_code, QImode, copy_rtx (second), const1_rtx)); | |
3302 + return; | |
3303 + } | |
3304 +} | |
3305 + | |
3306 + | |
3307 +/** Adjust register usage based on compile-time flags. */ | |
3308 +void | |
3309 +m6809_conditional_register_usage (void) | |
3310 +{ | |
3311 + unsigned int soft_regno; | |
3312 + | |
3313 +#ifdef CONFIG_SOFT_REGS_ALWAYS | |
3314 + m6809_soft_regs = CONFIG_SOFT_REGS_ALWAYS; | |
3315 +#else | |
3316 + if (!m6809_soft_reg_count) | |
3317 + return; | |
3318 + m6809_soft_regs = atoi (m6809_soft_reg_count); | |
3319 +#endif | |
3320 + | |
3321 + if (m6809_soft_regs == 0) | |
3322 + return; | |
3323 + | |
3324 + if (m6809_soft_regs > NUM_M_REGS) | |
3325 + m6809_soft_regs = NUM_M_REGS; | |
3326 + | |
3327 + /* Registers are marked FIXED by default. Free up if | |
3328 + the user wishes. */ | |
3329 + for (soft_regno = 1; soft_regno < m6809_soft_regs; soft_regno++) | |
3330 + { | |
3331 + fixed_regs[SOFT_M0_REGNUM + soft_regno] = 0; | |
3332 + | |
3333 + /* Mark the softregs as call-clobbered, so that they need | |
3334 + * not be saved/restored on function entry/exit. */ | |
3335 + call_used_regs[SOFT_M0_REGNUM + soft_regno] = 1; | |
3336 + } | |
3337 +} | |
3338 + | |
3339 + | |
3340 +/** Return a RTX representing how to return a value from a function. | |
3341 + VALTYPE gives the type of the value, FUNC identifies the function | |
3342 + itself. | |
3343 + | |
3344 + In general, we only care about the width of the result. */ | |
3345 +rtx | |
3346 +m6809_function_value (const tree valtype, const tree func ATTRIBUTE_UNUSED) | |
3347 +{ | |
3348 + unsigned int regno; | |
3349 + enum machine_mode mode; | |
3350 + | |
3351 + /* Get the mode (i.e. width) of the result. */ | |
3352 + mode = TYPE_MODE (valtype); | |
3353 + | |
3354 + if (lookup_attribute ("boolean", TYPE_ATTRIBUTES (valtype))) | |
3355 + regno = HARD_Z_REGNUM; | |
3356 + else if (mode == QImode || (TARGET_DRET && mode == HImode)) | |
3357 + regno = HARD_D_REGNUM; | |
3358 + else | |
3359 + regno = HARD_X_REGNUM; | |
3360 + return gen_rtx_REG (mode, regno); | |
3361 +} | |
3362 + | |
3363 + | |
3364 +/** Return 1 if REGNO is possibly needed to return the result | |
3365 +of a function, 0 otherwise. */ | |
3366 +int | |
3367 +m6809_function_value_regno_p (unsigned int regno) | |
3368 +{ | |
3369 + if (regno == HARD_Z_REGNUM) | |
3370 + return 1; | |
3371 + else if ((TARGET_BYTE_INT || TARGET_DRET) && regno == HARD_D_REGNUM) | |
3372 + return 1; | |
3373 + else if (!TARGET_DRET && regno == HARD_X_REGNUM) | |
3374 + return 1; | |
3375 + else | |
3376 + return 0; | |
3377 +} | |
3378 + | |
3379 + | |
3380 +#ifdef TRACE_PEEPHOLE | |
3381 +int | |
3382 +m6809_match_peephole2 (unsigned int peephole_id, unsigned int stage) | |
3383 +{ | |
3384 + if (stage == PEEP_END) | |
3385 + { | |
3386 + printf ("%s: peephole %d pattern and predicate matched\n", | |
3387 + main_input_filename, peephole_id); | |
3388 + fflush (stdout); | |
3389 + } | |
3390 + else if (stage == PEEP_COND) | |
3391 + { | |
3392 + printf ("%s: peephole %d? at least pattern matched\n", | |
3393 + main_input_filename, peephole_id); | |
3394 + fflush (stdout); | |
3395 + } | |
3396 + return 1; | |
3397 +} | |
3398 +#else | |
3399 +int | |
3400 +m6809_match_peephole2 (unsigned int peephole_id ATTRIBUTE_UNUSED, | |
3401 + unsigned int stage ATTRIBUTE_UNUSED) | |
3402 +{ | |
3403 + return 1; | |
3404 +} | |
3405 +#endif /* TRACE_PEEPHOLE */ | |
3406 + | |
3407 + | |
3408 +/** Return 1 if it is OK to store a value of MODE in REGNO. */ | |
3409 +int | |
3410 +m6809_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) | |
3411 +{ | |
3412 + /* Soft registers, as they are just memory, can really hold | |
3413 + values of any type. However we restrict them to values of | |
3414 + size HImode or QImode to prevent exhausting them for larger | |
3415 + values. | |
3416 + Word values cannot be placed into the first soft register, | |
3417 + as it is the low byte that is being placed there, which | |
3418 + corrupts the (non-soft) register before it. */ | |
3419 + if (M_REGNO_P (regno)) | |
3420 + { | |
3421 + switch (GET_MODE_SIZE (mode)) | |
3422 + { | |
3423 + case 1: | |
3424 + return 1; | |
3425 + case 2: | |
3426 + return regno != SOFT_M0_REGNUM; | |
3427 + default: | |
3428 + return 0; | |
3429 + } | |
3430 + } | |
3431 + | |
3432 + /* VOIDmode can be stored anywhere */ | |
3433 + else if (mode == VOIDmode) | |
3434 + return 1; | |
3435 + | |
3436 + /* Zero is a reserved register, but problems occur if we don't | |
3437 + say yes here??? */ | |
3438 + else if (regno == 0) | |
3439 + return 1; | |
3440 + | |
3441 + /* For other registers, return true only if the requested size | |
3442 + exactly matches the hardware size. */ | |
3443 + else if ((G_REGNO_P (regno)) && (GET_MODE_SIZE (mode) == 2)) | |
3444 + return 1; | |
3445 + else if ((BYTE_REGNO_P (regno)) && (GET_MODE_SIZE (mode) == 1)) | |
3446 + return 1; | |
3447 + else | |
3448 + return 0; | |
3449 +} | |
3450 + | |
3451 + | |
3452 +/* exp is the call expression. DECL is the called function, | |
3453 + * or NULL for an indirect call */ | |
3454 +bool | |
3455 +m6809_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) | |
3456 +{ | |
3457 + tree type, arg; | |
3458 + const char *name; | |
3459 + bool result = 0; | |
3460 + int argcount = 0; | |
3461 + int step = 1; | |
3462 + | |
3463 + /* If there is no DECL, it is an indirect call. | |
3464 + * Never optimize this??? */ | |
3465 + if (decl == NULL) | |
3466 + goto done; | |
3467 + | |
3468 + /* Never allow an interrupt handler to be optimized this way. */ | |
3469 + if (m6809_function_has_type_attr_p (decl, "interrupt")) | |
3470 + goto done; | |
3471 + | |
3472 + /* Skip sibcall if the type can't be found for | |
3473 + * some reason */ | |
3474 + step++; | |
3475 + name = IDENTIFIER_POINTER (DECL_NAME (decl)); | |
3476 + type = TREE_TYPE (decl); | |
3477 + if (type == NULL) | |
3478 + goto done; | |
3479 + | |
3480 + /* Skip sibcall if the target is a far function */ | |
3481 + step++; | |
3482 + if (far_function_type_p (type) != NULL) | |
3483 + goto done; | |
3484 + | |
3485 + /* Skip sibcall if the called function's arguments are | |
3486 + * variable */ | |
3487 + step++; | |
3488 + if (TYPE_ARG_TYPES (type) == NULL) | |
3489 + goto done; | |
3490 + | |
3491 + /* Allow sibcalls in other cases. */ | |
3492 + result = 1; | |
3493 +done: | |
3494 + /* printf ("%s ok for sibcall? %s, step %d, args %d\n", name, result ? "yes" : "no", step, argcount); */ | |
3495 + return result; | |
3496 +} | |
3497 + | |
3498 + | |
3499 +/** Emit code for the 'casesi' pattern. | |
3500 + * This pattern is only used in 8-bit mode, and can be disabled | |
3501 + * with -mold-case there as well. The rationale for this is to | |
3502 + * do a better job than the simpler but well-tested 'tablejump' | |
3503 + * method. | |
3504 + * | |
3505 + * For small jumptables, where the switch expression is an | |
3506 + * 8-bit value, the lookup can be done more efficiently | |
3507 + * using the "B,X" style index mode. */ | |
3508 +void | |
3509 +m6809_do_casesi (rtx index, rtx lower_bound, rtx range, | |
3510 + rtx table_label, rtx default_label) | |
3511 +{ | |
3512 + enum machine_mode mode; | |
3513 + rtx scaled; | |
3514 + rtx table_in_reg; | |
3515 + | |
3516 + /* expr.c has to be patched so that it does not promote | |
3517 + * the expression to SImode, but rather to HImode. | |
3518 + * Fail now if that isn't the case. */ | |
3519 + if (GET_MODE_SIZE (GET_MODE (index)) > GET_MODE_SIZE (HImode)) | |
3520 + error ("try_casesi promotion bug"); | |
3521 + | |
3522 + /* Determine whether or not we are going to work primarily in | |
3523 + * QImode or HImode. This depends on the size of the index | |
3524 + * into the lookup table. QImode can only be used when the | |
3525 + * index is less than 0x40, since it will be doubled but | |
3526 + * must remain unsigned. */ | |
3527 + if ((GET_CODE (range) == CONST_INT) && (INTVAL (range) < 0x40)) | |
3528 + mode = QImode; | |
3529 + else | |
3530 + mode = HImode; | |
3531 + | |
3532 + /* Convert to QImode if necessary */ | |
3533 + if (mode == QImode) | |
3534 + { | |
3535 + index = gen_lowpart_general (mode, index); | |
3536 + lower_bound = gen_lowpart_general (mode, lower_bound); | |
3537 + } | |
3538 + | |
3539 + /* Translate from case value to table index by subtraction */ | |
3540 + if (lower_bound != const0_rtx) | |
3541 + index = expand_binop (mode, sub_optab, index, lower_bound, | |
3542 + NULL_RTX, 0, OPTAB_LIB_WIDEN); | |
3543 + | |
3544 + /* Emit compare-and-jump to test for index out-of-range */ | |
3545 + emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1, | |
3546 + default_label); | |
3547 + | |
3548 + /* Put the table address is in a register */ | |
3549 + table_in_reg = gen_reg_rtx (Pmode); | |
3550 + emit_move_insn (table_in_reg, gen_rtx_LABEL_REF (Pmode, table_label)); | |
3551 + | |
3552 + /* Emit table lookup and jump */ | |
3553 + if (mode == QImode) | |
3554 + { | |
3555 + /* Scale the index */ | |
3556 + scaled = gen_reg_rtx (QImode); | |
3557 + emit_insn (gen_ashlqi3 (scaled, index, const1_rtx)); | |
3558 + | |
3559 + /* Emit the jump */ | |
3560 + emit_jump_insn (gen_tablejump_short_offset (scaled, table_in_reg)); | |
3561 + } | |
3562 + else | |
3563 + { | |
3564 + /* Scale the index */ | |
3565 + emit_insn (gen_ashlhi3 (index, index, const1_rtx)); | |
3566 + | |
3567 + /* Emit the jump */ | |
3568 + emit_jump_insn (gen_tablejump_long_offset (index, table_in_reg)); | |
3569 + } | |
3570 + | |
3571 + /* Copied from expr.c */ | |
3572 + if (!CASE_VECTOR_PC_RELATIVE && !flag_pic) | |
3573 + emit_barrier (); | |
3574 +} | |
3575 + | |
3576 + | |
3577 +/** Output the assembly code for a 32-bit add/subtract. */ | |
3578 +void | |
3579 +m6809_output_addsi3 (int rtx_code, rtx *operands) | |
3580 +{ | |
3581 + rtx xoperands[8]; | |
3582 + rtx dst = operands[0]; | |
3583 + | |
3584 + /* Prepare the operands by splitting each SImode into two HImodes | |
3585 + that can be operated independently. The high word of operand 1 | |
3586 + is further divided into two QImode components for use with 'adc' | |
3587 + style instructions. */ | |
3588 + xoperands[7] = operands[3]; | |
3589 + | |
3590 + xoperands[0] = adjust_address (dst, HImode, 2); | |
3591 + xoperands[3] = adjust_address (dst, HImode, 0); | |
3592 + | |
3593 +#if 1 | |
3594 + xoperands[2] = adjust_address (operands[1], HImode, 2); | |
3595 + xoperands[6] = adjust_address (operands[1], HImode, 0); | |
3596 + | |
3597 + /* Operand 2 may be a MEM or a CONST_INT */ | |
3598 + if (GET_CODE (operands[2]) == CONST_INT) | |
3599 + { | |
3600 + xoperands[1] = gen_int_mode (INTVAL (operands[2]) & 0xFFFF, HImode); | |
3601 + xoperands[4] = gen_int_mode ((INTVAL (operands[2]) >> 24) & 0xFF, QImode); | |
3602 + xoperands[5] = gen_int_mode ((INTVAL (operands[2]) >> 16) & 0xFF, QImode); | |
3603 + } | |
3604 + else | |
3605 + { | |
3606 + xoperands[1] = adjust_address (operands[2], HImode, 2); | |
3607 + xoperands[4] = adjust_address (operands[2], QImode, 0); | |
3608 + xoperands[5] = adjust_address (operands[2], QImode, 1); | |
3609 + } | |
3610 + | |
3611 +#endif | |
3612 + | |
3613 +#if 0 | |
3614 + xoperands[1] = adjust_address (operands[1], HImode, 2); | |
3615 + xoperands[4] = adjust_address (operands[1], QImode, 0); | |
3616 + xoperands[5] = adjust_address (operands[1], QImode, 1); | |
3617 + | |
3618 + /* Operand 2 may be a MEM or a CONST_INT */ | |
3619 + if (GET_CODE (operands[2]) == CONST_INT) | |
3620 + { | |
3621 + xoperands[2] = gen_int_mode ((INTVAL (operands[2])) & 0xFFFF, HImode); | |
3622 + xoperands[6] = gen_int_mode ((INTVAL (operands[2]) >> 16) & 0xFFFF, HImode); | |
3623 + } | |
3624 + else | |
3625 + { | |
3626 + xoperands[2] = adjust_address (operands[2], HImode, 2); | |
3627 + xoperands[6] = adjust_address (operands[2], HImode, 0); | |
3628 + } | |
3629 +#endif | |
3630 + | |
3631 + /* Output the assembly code. */ | |
3632 + if (rtx_code == PLUS) | |
3633 + { | |
3634 + output_asm_insn ("ld%7\t%2", xoperands); | |
3635 + output_asm_insn ("add%7\t%1", xoperands); | |
3636 + output_asm_insn ("st%7\t%0", xoperands); | |
3637 + output_asm_insn ("ld%7\t%6", xoperands); | |
3638 + output_asm_insn ("adcb\t%5", xoperands); | |
3639 + output_asm_insn ("adca\t%4", xoperands); | |
3640 + output_asm_insn ("st%7\t%3", xoperands); | |
3641 + } | |
3642 + else | |
3643 + { | |
3644 + output_asm_insn ("ld%7\t%2", xoperands); | |
3645 + output_asm_insn ("sub%7\t%1", xoperands); | |
3646 + output_asm_insn ("st%7\t%0", xoperands); | |
3647 + output_asm_insn ("ld%7\t%6", xoperands); | |
3648 + output_asm_insn ("sbcb\t%5", xoperands); | |
3649 + output_asm_insn ("sbca\t%4", xoperands); | |
3650 + output_asm_insn ("st%7\t%3", xoperands); | |
3651 + } | |
3652 +} | |
3653 + | |
3654 + | |
3655 +#if 0 | |
3656 +/** Output the assembly code for a 32-bit shift. | |
3657 +Operands 0 and 1 must be the same rtx, forced by a matching | |
3658 +constraint. Operand 2 must be a CONST_INT. Operand 3 is | |
3659 +"d" in case a temporary reg is needed. */ | |
3660 +void | |
3661 +m6809_output_shiftsi3 (int rtx_code, rtx *operands) | |
3662 +{ | |
3663 + unsigned int count = INTVAL (operands[2]) % 32; | |
3664 + unsigned int size = 4; /* sizeof (SImode) */ | |
3665 + int s; | |
3666 + rtx xoperands[4]; | |
3667 + int op; | |
3668 + int start, end, step; | |
3669 + | |
3670 + /* Initialize */ | |
3671 + if (rtx_code == ASHIFT) | |
3672 + { | |
3673 + start = size-1; | |
3674 + end = -1; | |
3675 + step = -1; | |
3676 + } | |
3677 + else | |
3678 + { | |
3679 + start = 0; | |
3680 + end = size; | |
3681 + step = 1; | |
3682 + } | |
3683 + | |
3684 + xoperands[2] = operands[2]; | |
3685 + xoperands[3] = operands[3]; | |
3686 + | |
3687 + if (count <= 0) | |
3688 + abort (); | |
3689 + if (rtx_code == ROTATE || rtx_code == ROTATERT) | |
3690 + abort (); | |
3691 + | |
3692 + /* Extract bit shifts over 16 bits by HImode moves. */ | |
3693 + if (count >= 16) | |
3694 + { | |
3695 + } | |
3696 + | |
3697 + /* Extract bit shifts over 8 bits by QImode moves. */ | |
3698 + if (count >= 8) | |
3699 + { | |
3700 + } | |
3701 + | |
3702 + /* Iterate over the number of bits to be shifted. */ | |
3703 + while (count > 0) | |
3704 + { | |
3705 + /* Each bit to be shifted requires 1 proper bit shift | |
3706 + and 3 rotates. */ | |
3707 + | |
3708 + /* First, do the arithmetic/logical shift. Left shifts | |
3709 + start from the LSB; right shifts start from the MSB. */ | |
3710 + xoperands[0] = adjust_address (operands[0], QImode, start); | |
3711 + switch (rtx_code) | |
3712 + { | |
3713 + case ASHIFT: | |
3714 + output_asm_insn ("asl\t%0", xoperands); | |
3715 + start--; | |
3716 + break; | |
3717 + case ASHIFTRT: | |
3718 + output_asm_insn ("asr\t%0", xoperands); | |
3719 + start++; | |
3720 + break; | |
3721 + case LSHIFTRT: | |
3722 + output_asm_insn ("lsr\t%0", xoperands); | |
3723 + start++; | |
3724 + break; | |
3725 + } | |
3726 + | |
3727 + /* Next, rotate the other bytes */ | |
3728 + for (s = start; s != end; s += step) | |
3729 + { | |
3730 + xoperands[0] = adjust_address (operands[0], QImode, s); | |
3731 + switch (rtx_code) | |
3732 + { | |
3733 + case ASHIFT: | |
3734 + output_asm_insn ("rol\t%0", xoperands); | |
3735 + break; | |
3736 + case ASHIFTRT: | |
3737 + case LSHIFTRT: | |
3738 + output_asm_insn ("ror\t%0", xoperands); | |
3739 + break; | |
3740 + } | |
3741 + } | |
3742 + count--; | |
3743 + } | |
3744 +} | |
3745 +#endif | |
3746 + | |
3747 +int | |
3748 +power_of_two_p (unsigned int n) | |
3749 +{ | |
3750 + return (n & (n-1)) == 0; | |
3751 +} | |
3752 + | |
3753 + | |
3754 +int | |
3755 +m6809_can_eliminate (int from, int to) | |
3756 +{ | |
3757 + if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) | |
3758 + return !frame_pointer_needed; | |
3759 + return 1; | |
3760 +} | |
3761 + | |
3762 + | |
3763 +int | |
3764 +m6809_initial_elimination_offset (int from, int to) | |
3765 +{ | |
3766 + switch (from) | |
3767 + { | |
3768 + case ARG_POINTER_REGNUM: | |
3769 + return get_frame_size () + m6809_get_regs_size (m6809_get_live_regs ()); | |
3770 + case FRAME_POINTER_REGNUM: | |
3771 + return get_frame_size (); | |
3772 + default: | |
3773 + gcc_unreachable (); | |
3774 + } | |
3775 +} | |
3776 + | |
3777 + | |
3778 +bool | |
3779 +m6809_frame_pointer_required (void) | |
3780 +{ | |
3781 + return false; | |
3782 +} | |
3783 + | |
3784 + | |
3785 +/* Defines the target-specific hooks structure. */ | |
3786 +struct gcc_target targetm = TARGET_INITIALIZER; | |
3787 diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.h gcc-4.6.1/gcc/config/m6809/m6809.h | |
3788 --- gcc-4.6.1-orig/gcc/config/m6809/m6809.h 1969-12-31 17:00:00.000000000 -0700 | |
3789 +++ gcc-4.6.1/gcc/config/m6809/m6809.h 2011-09-18 19:47:50.207654849 -0600 | |
3790 @@ -0,0 +1,1352 @@ | |
3791 +/* Definitions of target machine for GNU compiler. MC6809 version. | |
3792 + | |
3793 + MC6809 Version by Tom Jones (jones@sal.wisc.edu) | |
3794 + Space Astronomy Laboratory | |
3795 + University of Wisconsin at Madison | |
3796 + | |
3797 + minor changes to adapt it to gcc-2.5.8 by Matthias Doerfel | |
3798 + ( msdoerfe@informatik.uni-erlangen.de ) | |
3799 + also added #pragma interrupt (inspired by gcc-6811) | |
3800 + | |
3801 + minor changes to adapt it to gcc-2.8.0 by Eric Botcazou | |
3802 + (ebotcazou@multimania.com) | |
3803 + | |
3804 + minor changes to adapt it to egcs-1.1.2 by Eric Botcazou | |
3805 + (ebotcazou@multimania.com) | |
3806 + | |
3807 + minor changes to adapt it to gcc-2.95.3 by Eric Botcazou | |
3808 + (ebotcazou@multimania.com) | |
3809 + | |
3810 + changes for gcc-3.1.1 by ??? | |
3811 + | |
3812 + further changes for gcc-3.1.1 and beyond by Brian Dominy | |
3813 + (brian@oddchange.com) | |
3814 + | |
3815 + even more changes for gcc-4.6.1 by William Astle (lost@l-w.ca) | |
3816 + | |
3817 +This file is part of GCC. | |
3818 + | |
3819 +GCC is free software; you can redistribute it and/or modify | |
3820 +it under the terms of the GNU General Public License as published by | |
3821 +the Free Software Foundation; either version 3, or (at your option) | |
3822 +any later version. | |
3823 + | |
3824 +GCC is distributed in the hope that it will be useful, | |
3825 +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
3826 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
3827 +GNU General Public License for more details. | |
3828 + | |
3829 +You should have received a copy of the GNU General Public License | |
3830 +along with GCC; see the file COPYING3. If not see | |
3831 +<http://www.gnu.org/licenses/>. */ | |
3832 + | |
3833 + | |
3834 +/* Helper macros for creating strings with macros */ | |
3835 +#define C_STRING(x) C_STR(x) | |
3836 +#define C_STR(x) #x | |
3837 + | |
3838 +/* Certain parts of GCC include host-side includes, which is bad. | |
3839 + * Some things that get pulled in need to be undone. | |
3840 + */ | |
3841 +#undef HAVE_GAS_HIDDEN | |
3842 + | |
3843 +/* Names to predefine in the preprocessor for this target machine. */ | |
3844 +/*#define TARGET_CPU_CPP_BUILTINS() m6809_cpu_cpp_builtins () */ | |
3845 +#define TARGET_CPU_CPP_BUILTINS() do \ | |
3846 + { \ | |
3847 + if (TARGET_6309) \ | |
3848 + { \ | |
3849 + builtin_define_std ("__M6309__"); \ | |
3850 + builtin_define_std ("__m6309__"); \ | |
3851 + } \ | |
3852 + else \ | |
3853 + { \ | |
3854 + builtin_define_std ("__M6809__"); \ | |
3855 + builtin_define_std ("__m6809__"); \ | |
3856 + } \ | |
3857 + \ | |
3858 + if (TARGET_BYTE_INT) \ | |
3859 + builtin_define_std ("__int8__"); \ | |
3860 + else \ | |
3861 + builtin_define_std ("__int16__"); \ | |
3862 + \ | |
3863 + switch (m6809_abi_version) \ | |
3864 + { \ | |
3865 + case M6809_ABI_VERSION_STACK: \ | |
3866 + builtin_define_std ("__regargs__"); \ | |
3867 + builtin_define_std ("__ABI_STACK__"); \ | |
3868 + break; \ | |
3869 + case M6809_ABI_VERSION_REGS: \ | |
3870 + builtin_define_std ("__ABI_REGS__"); \ | |
3871 + break; \ | |
3872 + case M6809_ABI_VERSION_BX: \ | |
3873 + builtin_define_std ("__ABI_BX__"); \ | |
3874 + break; \ | |
3875 + default: \ | |
3876 + break; \ | |
3877 + } \ | |
3878 + \ | |
3879 + if (TARGET_WPC) \ | |
3880 + builtin_define_std ("__WPC__"); \ | |
3881 + \ | |
3882 + if (TARGET_DRET) \ | |
3883 + builtin_define_std ("__DRET__"); \ | |
3884 + } while (0) | |
3885 + | |
3886 +/* As an embedded target, we have no libc. */ | |
3887 +#ifndef inhibit_libc | |
3888 +#define inhibit_libc | |
3889 +#endif | |
3890 + | |
3891 +/* Print subsidiary information on the compiler version in use. */ | |
3892 +#define TARGET_VERSION fprintf (stderr, " (MC6809)"); | |
3893 + | |
3894 +/* Run-time compilation parameters selecting different hardware subsets. */ | |
3895 +/*extern int target_flags; */ | |
3896 +extern short *reg_renumber; /* def in local_alloc.c */ | |
3897 + | |
3898 +/* Runtime current values of section names */ | |
3899 +extern int section_changed; | |
3900 +extern char code_section_op[], data_section_op[], bss_section_op[]; | |
3901 + | |
3902 +#define WARNING_OPT 0, | |
3903 +/*extern const char *m6809_abi_version_ptr; */ | |
3904 +extern unsigned int m6809_soft_regs; | |
3905 +extern unsigned int m6809_abi_version; | |
3906 + | |
3907 +/* ABI versions */ | |
3908 + | |
3909 +#define M6809_ABI_VERSION_STACK 0 | |
3910 +#define M6809_ABI_VERSION_REGS 1 | |
3911 +#define M6809_ABI_VERSION_BX 2 | |
3912 +#define M6809_ABI_VERSION_LATEST (M6809_ABI_VERSION_BX) | |
3913 + | |
3914 +/* Allow $ in identifiers */ | |
3915 +#define DOLLARS_IN_IDENTIFIERS 1 | |
3916 + | |
3917 +/*-------------------------------------------------------------- | |
3918 + Target machine storage layout | |
3919 +--------------------------------------------------------------*/ | |
3920 + | |
3921 +/* Define this if most significant bit is lowest numbered | |
3922 + in instructions that operate on numbered bit-fields. */ | |
3923 +#define BITS_BIG_ENDIAN 0 | |
3924 + | |
3925 +/* Define to 1 if most significant byte of a word is the lowest numbered. */ | |
3926 +#define BYTES_BIG_ENDIAN 1 | |
3927 + | |
3928 +/* Define to 1 if most significant word of a multiword value is the lowest numbered. */ | |
3929 +#define WORDS_BIG_ENDIAN 1 | |
3930 + | |
3931 +/* Number of bits in an addressible storage unit */ | |
3932 +#define BITS_PER_UNIT 8 | |
3933 + | |
3934 +/* Width in bits of a "word", or the contents of a machine register. | |
3935 + * Although the 6809 has a few byte registers, define this to 16-bits | |
3936 + * since this is the natural size of most registers. */ | |
3937 +#define BITS_PER_WORD 16 | |
3938 + | |
3939 +/* Width of a word, in units (bytes). */ | |
3940 +#define UNITS_PER_WORD (BITS_PER_WORD/8) | |
3941 + | |
3942 +/* Width in bits of a pointer. See also the macro `Pmode' defined below. */ | |
3943 +#define POINTER_SIZE 16 | |
3944 + | |
3945 +/* Allocation boundary (bits) for storing pointers in memory. */ | |
3946 +#define POINTER_BOUNDARY 8 | |
3947 + | |
3948 +/* Allocation boundary (bits) for storing arguments in argument list. */ | |
3949 +/* PARM_BOUNDARY is divided by BITS_PER_WORD in expr.c -- tej */ | |
3950 +#define PARM_BOUNDARY 8 | |
3951 + | |
3952 +/* Boundary (bits) on which stack pointer should be aligned. */ | |
3953 +#define STACK_BOUNDARY 8 | |
3954 + | |
3955 +/* Allocation boundary (bits) for the code of a function. */ | |
3956 +#define FUNCTION_BOUNDARY 8 | |
3957 + | |
3958 +/* Alignment of field after `int : 0' in a structure. */ | |
3959 +#define EMPTY_FIELD_BOUNDARY 8 | |
3960 + | |
3961 +/* Every structure's size must be a multiple of this. */ | |
3962 +#define STRUCTURE_SIZE_BOUNDARY 8 | |
3963 + | |
3964 +/* Largest mode size to use when putting an object, including | |
3965 + * a structure, into a register. By limiting this to 16, no | |
3966 + * 32-bit objects will ever be allocated to a pair of hard | |
3967 + * registers. This is a good thing, since there aren't that | |
3968 + * many of them. 32-bit objects are only needed for floats | |
3969 + * and "long long"s. Larger values have been tried and did not | |
3970 + * work. */ | |
3971 +#define MAX_FIXED_MODE_SIZE 16 | |
3972 + | |
3973 +/* No data type wants to be aligned rounder than this. */ | |
3974 +#define BIGGEST_ALIGNMENT 8 | |
3975 + | |
3976 +/* Define this if move instructions will actually fail to work | |
3977 + when given unaligned data. */ | |
3978 +#define STRICT_ALIGNMENT 0 | |
3979 + | |
3980 +/*-------------------------------------------------------------- | |
3981 + Standard register usage. | |
3982 +--------------------------------------------------------------*/ | |
3983 + | |
3984 +/* Register values as bitmasks. | |
3985 + * TODO : merge D_REGBIT and B_REGBIT, and treat this as the same | |
3986 + * register. */ | |
3987 +#define RSVD1_REGBIT (1 << HARD_RSVD1_REGNUM) | |
3988 +#define D_REGBIT (1 << HARD_D_REGNUM) | |
3989 +#define X_REGBIT (1 << HARD_X_REGNUM) | |
3990 +#define Y_REGBIT (1 << HARD_Y_REGNUM) | |
3991 +#define U_REGBIT (1 << HARD_U_REGNUM) | |
3992 +#define S_REGBIT (1 << HARD_S_REGNUM) | |
3993 +#define PC_REGBIT (1 << HARD_PC_REGNUM) | |
3994 +#define Z_REGBIT (1 << HARD_Z_REGNUM) | |
3995 +#define A_REGBIT (1 << HARD_A_REGNUM) | |
3996 +#define B_REGBIT (1 << HARD_B_REGNUM) | |
3997 +#define CC_REGBIT (1 << HARD_CC_REGNUM) | |
3998 +#define DP_REGBIT (1 << HARD_DP_REGNUM) | |
3999 +#define SOFT_FP_REGBIT (1 << SOFT_FP_REGNUM) | |
4000 +#define SOFT_AP_REGBIT (1 << SOFT_AP_REGNUM) | |
4001 +#define M_REGBIT(n) (1 << (SOFT_M0_REGNUM + n)) | |
4002 + | |
4003 +/* Macros for dealing with set of registers. | |
4004 + * A register set is just a bitwise-OR of all the register | |
4005 + * bitmask values. */ | |
4006 + | |
4007 +/* Which registers can hold 8-bits */ | |
4008 +#define BYTE_REGSET \ | |
4009 + (Z_REGBIT | A_REGBIT | D_REGBIT | CC_REGBIT | DP_REGBIT | SOFT_M_REGBITS) | |
4010 + | |
4011 +/* Which registers can hold 16-bits. | |
4012 + * Note: D_REGBIT is defined as both an 8-bit and 16-bit register */ | |
4013 +#define WORD_REGSET \ | |
4014 + (D_REGBIT | X_REGBIT | Y_REGBIT | U_REGBIT | S_REGBIT | PC_REGBIT | SOFT_FP_REGBIT | SOFT_AP_REGBIT | RSVD1_REGBIT) | |
4015 + | |
4016 +/* Returns nonzero if a given REGNO is in the REGSET. */ | |
4017 +#define REGSET_CONTAINS_P(regno, regset) (((1 << (regno)) & (regset)) != 0) | |
4018 + | |
4019 +/* Defines related to the number of soft registers supported. | |
4020 + * The actual number used may be less depending on -msoft-reg-count. | |
4021 + * If you change one of these, you should change them all. */ | |
4022 +#define NUM_M_REGS 8 | |
4023 +#define M_REGS_FIXED 1, 1, 1, 1, 1, 1, 1, 1 | |
4024 +#define M_REGS_CALL_USED 1, 1, 1, 1, 1, 1, 1, 1 | |
4025 +#define HARD_M_REGNUMS \ | |
4026 + SOFT_M0_REGNUM+0, SOFT_M0_REGNUM+1, SOFT_M0_REGNUM+2, SOFT_M0_REGNUM+3, \ | |
4027 + SOFT_M0_REGNUM+4, SOFT_M0_REGNUM+5, SOFT_M0_REGNUM+6, SOFT_M0_REGNUM+7 | |
4028 + | |
4029 +#define SOFT_M_REGBITS (((1UL << NUM_M_REGS) - 1) << (SOFT_M0_REGNUM)) | |
4030 + | |
4031 +/* Number of actual hardware registers. | |
4032 + The hardware registers are assigned numbers for the compiler | |
4033 + from 0 to just below FIRST_PSEUDO_REGISTER. | |
4034 + All registers that the compiler knows about must be given numbers, | |
4035 + even those that are not normally considered general registers. | |
4036 + Make sure the constant below matches the value of SOFT_M0_REGNUM; | |
4037 + for some reason, GCC won't compile if that name is used here directly. */ | |
4038 +#ifdef SOFT_M0_REGNUM | |
4039 +#if (SOFT_M0_REGNUM != 14) | |
4040 +#error "bad register numbering" | |
4041 +#endif | |
4042 +#endif | |
4043 +#define FIRST_PSEUDO_REGISTER (14 + NUM_M_REGS) | |
4044 + | |
4045 +/* 1 for registers that have pervasive standard uses | |
4046 + and are not available for the register allocator. | |
4047 + The psuedoregisters (M_REGS) are declared fixed here, but | |
4048 + will be unfixed if -msoft-reg-count is seen later. */ | |
4049 +#define FIXED_REGISTERS \ | |
4050 + {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, M_REGS_FIXED, } | |
4051 + /* -, X, Y, U, S, PC,D, Z, A, B, C, DP,FP,AP,M... */ | |
4052 + | |
4053 +/* 1 for registers not available across function calls. | |
4054 + These must include the FIXED_REGISTERS and also any | |
4055 + registers that can be used without being saved. | |
4056 + The latter must include the registers where values are returned | |
4057 + and the register where structure-value addresses are passed. | |
4058 + Aside from that, you can include as many other registers as you like. */ | |
4059 +#define CALL_USED_REGISTERS \ | |
4060 + {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, M_REGS_CALL_USED, } | |
4061 + /* -, X, Y, U, S, PC,D, Z, A, B, C, DP,FP,AP,M... */ | |
4062 + | |
4063 +/* Return number of consecutive hard regs needed starting at reg REGNO | |
4064 + to hold something of mode MODE. | |
4065 + For the 6809, we distinguish between word-length and byte-length | |
4066 + registers. */ | |
4067 +#define HARD_REGNO_NREGS(REGNO, MODE) \ | |
4068 + (REGSET_CONTAINS_P (REGNO, WORD_REGSET) ? \ | |
4069 + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) : \ | |
4070 + (GET_MODE_SIZE (MODE))) | |
4071 + | |
4072 + | |
4073 +/* Value is 1 if hard register REGNO can hold a value | |
4074 +of machine-mode MODE. */ | |
4075 +#define HARD_REGNO_MODE_OK(REGNO, MODE) m6809_hard_regno_mode_ok (REGNO, MODE) | |
4076 + | |
4077 +/* Value is 1 if it is a good idea to tie two pseudo registers | |
4078 + when one has mode MODE1 and one has mode MODE2. | |
4079 + If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, | |
4080 + for any hard reg, then this must be 0 for correct output. */ | |
4081 +#define MODES_TIEABLE_P(MODE1, MODE2) 0 | |
4082 + | |
4083 +/* Specify the registers used for certain standard purposes. | |
4084 + The values of these macros are register numbers. */ | |
4085 + | |
4086 +/* program counter if referenced as a register */ | |
4087 +#define PC_REGNUM HARD_PC_REGNUM | |
4088 + | |
4089 +/* Register to use for pushing function arguments. */ | |
4090 +#define STACK_POINTER_REGNUM HARD_S_REGNUM | |
4091 + | |
4092 +/* Base register for access to local variables of the function. | |
4093 + * Before reload, FRAME_POINTER_REGNUM will be used. Later, | |
4094 + * the elimination pass will convert these to STACK_POINTER_REGNUM | |
4095 + * if possible, or else HARD_FRAME_POINTER_REGNUM. The idea is to | |
4096 + * avoid tying up a hard register (U) for the frame pointer if | |
4097 + * it can be eliminated entirely, making it available for use as | |
4098 + * a general register. */ | |
4099 +#define FRAME_POINTER_REGNUM SOFT_FP_REGNUM | |
4100 +#define HARD_FRAME_POINTER_REGNUM HARD_U_REGNUM | |
4101 + | |
4102 +/* Define a table of possible eliminations. | |
4103 + * The idea is to try to avoid using hard registers for the argument | |
4104 + * and frame pointers if they can be derived from the stack pointer | |
4105 + * instead, which already has a hard register reserved for it. | |
4106 + * | |
4107 + * The order of entries in this table will try to convert | |
4108 + * ARG_POINTER_REGNUM and FRAME_POINTER_REGNUM into stack pointer | |
4109 + * references first, but if that fails, they will be converted to use | |
4110 + * HARD_FRAME_POINTER_REGNUM. | |
4111 + */ | |
4112 +#define ELIMINABLE_REGS \ | |
4113 +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ | |
4114 + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \ | |
4115 + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ | |
4116 + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }} | |
4117 + | |
4118 +/* #define CAN_ELIMINATE(FROM, TO) m6809_can_eliminate (FROM, TO) */ | |
4119 + | |
4120 +/* Define how to offset the frame or argument pointer to turn it | |
4121 + * into a stack pointer reference. This is based on the way that | |
4122 + * the frame is constructed in the function prologue. */ | |
4123 +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ | |
4124 + (OFFSET) = m6809_initial_elimination_offset (FROM, TO) | |
4125 + | |
4126 +/* Base register for access to arguments of the function. | |
4127 + * This is only used prior to reload; no instructions will ever | |
4128 + * be output referring to this register. */ | |
4129 +#define ARG_POINTER_REGNUM SOFT_AP_REGNUM | |
4130 + | |
4131 +/* Register in which static-chain is passed to a function. */ | |
4132 +#define STATIC_CHAIN_REGNUM HARD_Y_REGNUM | |
4133 + | |
4134 +/* #define CONDITIONAL_REGISTER_USAGE (m6809_conditional_register_usage ()) */ | |
4135 + | |
4136 +/* Order in which hard registers are allocated to pseudos. | |
4137 + * | |
4138 + * Since the D register is the only valid reg for 8-bit values | |
4139 + * now, avoid using it for 16-bit values by putting it after all | |
4140 + * other 16-bits. | |
4141 + * | |
4142 + * Prefer X first since the first 16-bit function argument goes | |
4143 + * there. We may be able to pass in to a subroutine without | |
4144 + * a copy. | |
4145 + * | |
4146 + * Prefer U over Y since instructions using Y take one extra | |
4147 + * byte, and thus one extra cycle to execute. | |
4148 + */ | |
4149 +#define REG_ALLOC_ORDER \ | |
4150 + { HARD_X_REGNUM, HARD_U_REGNUM, HARD_Y_REGNUM, HARD_D_REGNUM, \ | |
4151 + HARD_M_REGNUMS, HARD_S_REGNUM, HARD_PC_REGNUM, \ | |
4152 + HARD_B_REGNUM, HARD_A_REGNUM, HARD_CC_REGNUM, \ | |
4153 + HARD_DP_REGNUM, SOFT_FP_REGNUM, SOFT_AP_REGNUM, \ | |
4154 + 6, HARD_Z_REGNUM } | |
4155 + | |
4156 +/*-------------------------------------------------------------- | |
4157 + classes of registers | |
4158 +--------------------------------------------------------------*/ | |
4159 + | |
4160 +/* Define the classes of registers for register constraints in the | |
4161 + machine description. Also define ranges of constants. | |
4162 + | |
4163 + One of the classes must always be named ALL_REGS and include all hard regs. | |
4164 + If there is more than one class, another class must be named NO_REGS | |
4165 + and contain no registers. | |
4166 + | |
4167 + The name GENERAL_REGS must be the name of a class (or an alias for | |
4168 + another name such as ALL_REGS). This is the class of registers | |
4169 + that is allowed by "g" or "r" in a register constraint. | |
4170 + Also, registers outside this class are allocated only when | |
4171 + instructions express preferences for them. | |
4172 + | |
4173 + The classes must be numbered in nondecreasing order; that is, | |
4174 + a larger-numbered class must never be contained completely | |
4175 + in a smaller-numbered class. | |
4176 + | |
4177 + For any two classes, it is very desirable that there be another | |
4178 + class that represents their union. */ | |
4179 + | |
4180 +enum reg_class { | |
4181 + NO_REGS, /* The trivial class with no registers in it */ | |
4182 + D_REGS, /* 16-bit (word (HI)) data (D) */ | |
4183 + ACC_A_REGS, /* The A register */ | |
4184 + ACC_B_REGS, /* The B register */ | |
4185 + X_REGS, /* The X register */ | |
4186 + Z_REGS, /* The Z (zero-bit) register */ | |
4187 + Q_REGS, /* 8-bit (byte (QI)) data (A,B) */ | |
4188 + M_REGS, /* 8-bit (byte (QI)) soft registers */ | |
4189 + CC_REGS, /* 8-bit condition code register */ | |
4190 + I_REGS, /* An index register (A,B,D) */ | |
4191 + T_REGS, /* 16-bit addresses, not including stack or PC (X,Y,U) */ | |
4192 + A_REGS, /* 16-bit addresses (X,Y,U,S,PC) */ | |
4193 + S_REGS, /* 16-bit soft registers (FP, AP) */ | |
4194 + P_REGS, /* 16-bit pushable registers (D,X,Y,U); omit PC and S */ | |
4195 + G_REGS, /* 16-bit data and address (D,X,Y,U,S,PC) */ | |
4196 + ALL_REGS, /* All registers */ | |
4197 + LIM_REG_CLASSES | |
4198 +}; | |
4199 + | |
4200 +#define N_REG_CLASSES (int) LIM_REG_CLASSES | |
4201 + | |
4202 +/* Since GENERAL_REGS is a smaller class than ALL_REGS, | |
4203 + it is not an alias to ALL_REGS, but to G_REGS. */ | |
4204 +#define GENERAL_REGS G_REGS | |
4205 + | |
4206 +/* Give names of register classes as strings for dump file. */ | |
4207 +#define REG_CLASS_NAMES \ | |
4208 + { "NO_REGS", "D_REGS", "ACC_A_REGS", "ACC_B_REGS", "X_REGS", "Z_REGS", "Q_REGS", "M_REGS", \ | |
4209 + "CC_REGS", "I_REGS", "T_REGS", "A_REGS", "S_REGS", "P_REGS", "G_REGS", \ | |
4210 + "ALL_REGS" } | |
4211 + | |
4212 +/* Define which registers fit in which classes. | |
4213 + This is an initializer for a vector of HARD_REG_SET | |
4214 + of length N_REG_CLASSES. */ | |
4215 + | |
4216 +#define D_REGSET (D_REGBIT) | |
4217 +#define ACC_A_REGSET (A_REGBIT) | |
4218 +#define ACC_B_REGSET (D_REGBIT) | |
4219 +#define X_REGSET (X_REGBIT) | |
4220 +#define Z_REGSET (Z_REGBIT) | |
4221 +#define Q_REGSET (D_REGBIT | A_REGBIT) | |
4222 +#define M_REGSET (SOFT_M_REGBITS) | |
4223 +#define CC_REGSET (CC_REGBIT) | |
4224 +#define I_REGSET (A_REGBIT | B_REGBIT | D_REGBIT) | |
4225 +#define T_REGSET (X_REGBIT | Y_REGBIT | U_REGBIT) | |
4226 +#define A_REGSET (X_REGBIT | Y_REGBIT | U_REGBIT | S_REGBIT | PC_REGBIT) | |
4227 +#define S_REGSET (SOFT_FP_REGBIT | SOFT_AP_REGBIT) | |
4228 +#define P_REGSET (D_REGBIT | X_REGBIT | Y_REGBIT | U_REGBIT) | |
4229 +#define G_REGSET \ | |
4230 + (D_REGSET | Q_REGSET | I_REGSET | A_REGSET | M_REGSET | S_REGSET) | |
4231 +#define ALL_REGSET (G_REGSET) | |
4232 + | |
4233 +#define REG_CLASS_CONTENTS { \ | |
4234 + {0}, \ | |
4235 + {D_REGSET}, \ | |
4236 + {ACC_A_REGSET}, \ | |
4237 + {ACC_B_REGSET}, \ | |
4238 + {X_REGSET}, \ | |
4239 + {Z_REGSET}, \ | |
4240 + {Q_REGSET}, \ | |
4241 + {M_REGSET}, \ | |
4242 + {CC_REGSET}, \ | |
4243 + {I_REGSET}, \ | |
4244 + {T_REGSET}, \ | |
4245 + {A_REGSET}, \ | |
4246 + {S_REGSET}, \ | |
4247 + {P_REGSET}, \ | |
4248 + {G_REGSET}, \ | |
4249 + {ALL_REGSET}, \ | |
4250 +} | |
4251 + | |
4252 +/* The same information, inverted. | |
4253 + * This is defined to use the REG_CLASS_CONTENTS defines above, so that | |
4254 + * these two sets of definitions are always consistent. */ | |
4255 + | |
4256 +#define REGNO_REG_CLASS(REGNO) \ | |
4257 + (D_REGNO_P (REGNO) ? D_REGS : \ | |
4258 + (Z_REGNO_P (REGNO) ? Z_REGS : \ | |
4259 + (ACC_A_REGNO_P (REGNO) ? ACC_A_REGS : \ | |
4260 + (ACC_B_REGNO_P (REGNO) ? ACC_B_REGS : \ | |
4261 + (X_REGNO_P (REGNO) ? X_REGS : \ | |
4262 + (Q_REGNO_P (REGNO) ? Q_REGS : \ | |
4263 + (M_REGNO_P (REGNO) ? M_REGS : \ | |
4264 + (CC_REGNO_P (REGNO) ? CC_REGS : \ | |
4265 + (I_REGNO_P (REGNO) ? I_REGS : \ | |
4266 + (T_REGNO_P (REGNO) ? T_REGS : \ | |
4267 + (A_REGNO_P (REGNO) ? A_REGS : \ | |
4268 + (S_REGNO_P (REGNO) ? S_REGS : \ | |
4269 + (P_REGNO_P (REGNO) ? P_REGS : \ | |
4270 + (G_REGNO_P (REGNO) ? G_REGS : ALL_REGS)))))))))))))) | |
4271 + | |
4272 +#define D_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, D_REGSET)) | |
4273 +#define ACC_A_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, ACC_A_REGSET)) | |
4274 +#define ACC_B_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, ACC_B_REGSET)) | |
4275 +#define X_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, X_REGSET)) | |
4276 +#define Z_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, Z_REGSET)) | |
4277 +#define Q_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, Q_REGSET)) | |
4278 +#define M_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, M_REGSET)) | |
4279 +#define CC_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, CC_REGSET)) | |
4280 +#define I_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, I_REGSET)) | |
4281 +#define T_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, T_REGSET)) | |
4282 +#define A_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, A_REGSET)) | |
4283 +#define S_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, S_REGSET)) | |
4284 +#define P_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, P_REGSET)) | |
4285 +#define G_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, G_REGSET)) | |
4286 + | |
4287 +/* Macros that test an rtx 'X' to see if it's in a particular | |
4288 + * register class. 'X' need not be a REG necessarily. */ | |
4289 + | |
4290 +#define D_REG_P(X) (REG_P (X) && D_REGNO_P (REGNO (X))) | |
4291 +#define ACC_A_REG_P(X) (REG_P (X) && ACC_A_REGNO_P (REGNO (X))) | |
4292 +#define ACC_B_REG_P(X) (REG_P (X) && ACC_B_REGNO_P (REGNO (X))) | |
4293 +#define X_REG_P(X) (REG_P (X) && X_REGNO_P (REGNO (X))) | |
4294 +#define Z_REG_P(X) (REG_P (X) && Z_REGNO_P (REGNO (X))) | |
4295 +#define I_REG_P(X) (REG_P (X) && I_REGNO_P (REGNO (X))) | |
4296 +#define T_REG_P(X) (REG_P (X) && T_REGNO_P (REGNO (X))) | |
4297 +#define A_REG_P(X) (REG_P (X) && A_REGNO_P (REGNO (X))) | |
4298 +#define S_REG_P(X) (REG_P (X) && S_REGNO_P (REGNO (X))) | |
4299 +#define P_REG_P(X) (REG_P (X) && P_REGNO_P (REGNO (X))) | |
4300 +#define Q_REG_P(X) (REG_P (X) && Q_REGNO_P (REGNO (X))) | |
4301 +#define M_REG_P(X) (REG_P (X) && M_REGNO_P (REGNO (X))) | |
4302 +#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X))) | |
4303 + | |
4304 +/* Redefine this in terms of BYTE_REGSET */ | |
4305 +#define BYTE_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, BYTE_REGSET)) | |
4306 + | |
4307 +/* The class value for index registers, and the one for base regs. */ | |
4308 +#define INDEX_REG_CLASS I_REGS | |
4309 +#define BASE_REG_CLASS A_REGS | |
4310 + | |
4311 +/* Get reg_class from a letter in the machine description. */ | |
4312 +#define REG_CLASS_FROM_LETTER(C) \ | |
4313 + (((C) == 'a' ? A_REGS : \ | |
4314 + ((C) == 'd' ? D_REGS : \ | |
4315 + ((C) == 'x' ? I_REGS : \ | |
4316 + ((C) == 't' ? M_REGS : \ | |
4317 + ((C) == 'c' ? CC_REGS : \ | |
4318 + ((C) == 'A' ? ACC_A_REGS : \ | |
4319 + ((C) == 'B' ? ACC_B_REGS : \ | |
4320 + ((C) == 'v' ? X_REGS : \ | |
4321 + ((C) == 'u' ? S_REGS : \ | |
4322 + ((C) == 'U' ? P_REGS : \ | |
4323 + ((C) == 'T' ? T_REGS : \ | |
4324 + ((C) == 'z' ? Z_REGS : \ | |
4325 + ((C) == 'q' ? Q_REGS : NO_REGS)))))))))))))) | |
4326 + | |
4327 +/*-------------------------------------------------------------- | |
4328 + The letters I through O in a register constraint string | |
4329 + can be used to stand for particular ranges of immediate operands. | |
4330 + This macro defines what the ranges are. | |
4331 + C is the letter, and VALUE is a constant value. | |
4332 + Return 1 if VALUE is in the range specified by C. | |
4333 + | |
4334 + For the 6809, J, K, L are used for indexed addressing. | |
4335 + `I' is used for the constant 1. | |
4336 + `J' is used for the 5-bit offsets. | |
4337 + `K' is used for the 8-bit offsets. | |
4338 + `L' is used for the range of signed numbers that fit in 16 bits. | |
4339 + `M' is used for the exact value '8'. | |
4340 + `N' is used for the constant -1. | |
4341 + `O' is used for the constant 0. | |
4342 +--------------------------------------------------------------*/ | |
4343 + | |
4344 +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ | |
4345 + ((C) == 'I' ? ((VALUE) == 1) : \ | |
4346 + (C) == 'J' ? ((VALUE) >= -16 && (VALUE) <= 15) : \ | |
4347 + (C) == 'K' ? ((VALUE) >= -128 && (VALUE) <= 127) : \ | |
4348 + (C) == 'L' ? ((VALUE) >= -32768 && (VALUE) <= 32767) : \ | |
4349 + (C) == 'M' ? ((VALUE) == 8) : \ | |
4350 + (C) == 'N' ? ((VALUE) == -1) : \ | |
4351 + (C) == 'O' ? ((VALUE) == 0) : 0) | |
4352 + | |
4353 +/* Similar, but for floating constants, and defining letters G and H. | |
4354 + No floating-point constants are valid on MC6809. */ | |
4355 +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ | |
4356 + ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ | |
4357 + && VALUE == CONST0_RTX (GET_MODE (VALUE))) : 0) | |
4358 + | |
4359 +/* Given an rtx X being reloaded into a reg required to be | |
4360 + in class CLASS, return the class of reg to actually use. | |
4361 + In general this is just CLASS; but on some machines | |
4362 + in some cases it is preferable to use a more restrictive class. */ | |
4363 +#define PREFERRED_RELOAD_CLASS(X,CLASS) m6809_preferred_reload_class(X,CLASS) | |
4364 + | |
4365 +#define SMALL_REGISTER_CLASSES 1 | |
4366 + | |
4367 +/* Return the maximum number of consecutive registers | |
4368 + needed to represent mode MODE in a register of class CLASS. */ | |
4369 +#define CLASS_MAX_NREGS(CLASS, MODE) \ | |
4370 + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) | |
4371 + | |
4372 +/*-------------------------------------------------------------- | |
4373 + Stack layout; function entry, exit and calling. | |
4374 +--------------------------------------------------------------*/ | |
4375 + | |
4376 +/* Define this if pushing a word on the stack | |
4377 + makes the stack pointer a smaller address. */ | |
4378 +#define STACK_GROWS_DOWNWARD | |
4379 + | |
4380 + | |
4381 +/* Define this if the nominal address of the stack frame | |
4382 + is at the high-address end of the local variables; | |
4383 + that is, each additional local variable allocated | |
4384 + goes at a more negative offset in the frame. */ | |
4385 +#define FRAME_GROWS_DOWNWARD 1 | |
4386 + | |
4387 + | |
4388 +/* Offset within stack frame to start allocating local variables at. | |
4389 + If FRAME_GROWS_DOWNWARD, this is the offset to the END of the | |
4390 + first local allocated. Otherwise, it is the offset to the BEGINNING | |
4391 + of the first local allocated. */ | |
4392 +#define STARTING_FRAME_OFFSET 0 | |
4393 + | |
4394 + | |
4395 +/* Always push stack arguments for now. Accumulation is not yet working. */ | |
4396 +#define PUSH_ROUNDING(BYTES) (BYTES) | |
4397 + | |
4398 + | |
4399 +/* Offset of first parameter from the argument pointer register value. | |
4400 + * ARG_POINTER_REGNUM is defined to point to the return address pushed | |
4401 + * onto the stack, so we must offset by 2 bytes to get to the arguments. */ | |
4402 +#define FIRST_PARM_OFFSET(FNDECL) 2 | |
4403 + | |
4404 +/* Value is 1 if returning from a function call automatically | |
4405 + pops the arguments described by the number-of-args field in the call. | |
4406 + FUNTYPE is the data type of the function (as a tree), | |
4407 + or for a library call it is an identifier node for the subroutine name. */ | |
4408 +/* #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 */ | |
4409 + | |
4410 +/* Define how to find the value returned by a function. | |
4411 + VALTYPE is the data type of the value (as a tree). | |
4412 + If the precise function being called is known, FUNC is its FUNCTION_DECL; | |
4413 + otherwise, FUNC is 0. */ | |
4414 +#define FUNCTION_VALUE(VALTYPE, FUNC) m6809_function_value (VALTYPE, FUNC) | |
4415 + | |
4416 +/* Define how to find the value returned by a library function | |
4417 + assuming the value has mode MODE. */ | |
4418 + | |
4419 +/* All return values are in the X-register. */ | |
4420 +#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, HARD_X_REGNUM) | |
4421 + | |
4422 +/* Define this if using the nonreentrant convention for returning | |
4423 + structure and union values. No; it is inefficient and buggy. */ | |
4424 +#undef PCC_STATIC_STRUCT_RETURN | |
4425 + | |
4426 +/* 1 if N is a possible register number for a function value. */ | |
4427 +#define FUNCTION_VALUE_REGNO_P(N) m6809_function_value_regno_p (N) | |
4428 + | |
4429 +/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for | |
4430 + more than one register. */ | |
4431 +#define NEEDS_UNTYPED_CALL 1 | |
4432 + | |
4433 +/* 1 if N is a possible register number for function argument passing. */ | |
4434 +#define FUNCTION_ARG_REGNO_P(N) \ | |
4435 + ((m6809_abi_version != M6809_ABI_VERSION_STACK) ? \ | |
4436 + (((N) == HARD_D_REGNUM) || ((N) == HARD_X_REGNUM)) : \ | |
4437 + 0) | |
4438 + | |
4439 +/*-------------------------------------------------------------- | |
4440 + Argument Lists | |
4441 +--------------------------------------------------------------*/ | |
4442 + | |
4443 +/* Cumulative arguments are tracked in a single integer, | |
4444 + * which is the number of bytes of arguments scanned so far, | |
4445 + * plus which registers have already been used. The register | |
4446 + * info is kept in some of the upper bits */ | |
4447 +#define CUMULATIVE_ARGS unsigned int | |
4448 + | |
4449 +#define CUM_STACK_ONLY 0x80000000 | |
4450 +#define CUM_X_MASK 0x40000000 | |
4451 +#define CUM_B_MASK 0x20000000 | |
4452 +#define CUM_STACK_INVALID 0x10000000 | |
4453 +#define CUM_STACK_MASK 0xFFFFFFF | |
4454 + | |
4455 +#define CUM_ADVANCE_8BIT(cum) \ | |
4456 + (((cum) & CUM_B_MASK) ? (cum)++ : ((cum) |= CUM_B_MASK)) | |
4457 + | |
4458 +#define CUM_ADVANCE_16BIT(cum) \ | |
4459 + (((cum) & CUM_X_MASK) ? (cum) += 2 : ((cum) |= CUM_X_MASK)) | |
4460 + | |
4461 +/* Initialize a variable CUM of type CUMULATIVE_ARGS | |
4462 + for a call to a function whose data type is FNTYPE. | |
4463 + For a library call, FNTYPE is 0. | |
4464 + N_NAMED was added in gcc 3.4 and is not used currently. */ | |
4465 +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT,N_NAMED) \ | |
4466 + ((CUM) = m6809_init_cumulative_args (CUM, FNTYPE, LIBNAME)) | |
4467 + | |
4468 +#define FUNCTION_ARG_SIZE(MODE, TYPE) \ | |
4469 + ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) \ | |
4470 + : (unsigned) int_size_in_bytes (TYPE)) | |
4471 + | |
4472 +/* Update the data in CUM to advance over an argument | |
4473 + of mode MODE and data type TYPE. | |
4474 + (TYPE is null for libcalls where that information may not be available.) */ | |
4475 +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ | |
4476 + (((MODE == QImode) && !((CUM) & CUM_STACK_ONLY)) ? \ | |
4477 + CUM_ADVANCE_8BIT (CUM) : \ | |
4478 + ((MODE == HImode) && !((CUM) & CUM_STACK_ONLY)) ? \ | |
4479 + CUM_ADVANCE_16BIT (CUM) : \ | |
4480 + ((CUM) = ((CUM) + (TYPE ? int_size_in_bytes (TYPE) : 2)))) | |
4481 + | |
4482 +/* Define where to put the arguments to a function. | |
4483 + Value is zero to push the argument on the stack, | |
4484 + or a hard register rtx in which to store the argument. | |
4485 + This macro is used _before_ FUNCTION_ARG_ADVANCE. | |
4486 + | |
4487 + For the 6809, the first 8-bit function argument can be placed into B, | |
4488 + and the first 16-bit arg can go into X. All other arguments | |
4489 + will be pushed onto the stack. | |
4490 + | |
4491 + Command-line options can adjust this behavior somewhat. | |
4492 + */ | |
4493 +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ | |
4494 + ((MODE == VOIDmode) ? NULL_RTX : \ | |
4495 + ((MODE == BLKmode) || (GET_MODE_SIZE (MODE) > 2)) ? NULL_RTX : \ | |
4496 + ((MODE == QImode) && !((CUM) & (CUM_STACK_ONLY | CUM_B_MASK))) ? \ | |
4497 + gen_rtx_REG (QImode, HARD_D_REGNUM) : \ | |
4498 + ((MODE == HImode) && !((CUM) & (CUM_STACK_ONLY | CUM_X_MASK))) ? \ | |
4499 + gen_rtx_REG (HImode, HARD_X_REGNUM) : m6809_function_arg_on_stack (&CUM)) | |
4500 + | |
4501 +/* Output assembler code to FILE to increment profiler label # LABELNO | |
4502 + for profiling a function entry. */ | |
4503 +#define FUNCTION_PROFILER(FILE, LABELNO) \ | |
4504 + fprintf (FILE, "\tldd\t#LP%u\n\tjsr\tmcount\n", (LABELNO)); | |
4505 + | |
4506 +/* Stack pointer must be correct on function exit */ | |
4507 +#define EXIT_IGNORE_STACK 0 | |
4508 + | |
4509 +/***************************************************************************** | |
4510 +** | |
4511 +** Trampolines for Nested Functions | |
4512 +** | |
4513 +*****************************************************************************/ | |
4514 + | |
4515 +/* Length in units of the trampoline for entering a nested function. */ | |
4516 +#define TRAMPOLINE_SIZE 7 | |
4517 + | |
4518 +/*-------------------------------------------------------------- | |
4519 + Addressing modes, | |
4520 + and classification of registers for them. | |
4521 +--------------------------------------------------------------*/ | |
4522 + | |
4523 +/* 6809 has postincrement and predecrement addressing modes */ | |
4524 +#define HAVE_POST_INCREMENT 1 | |
4525 +#define HAVE_PRE_DECREMENT 1 | |
4526 + | |
4527 +/* Whether or not to use index registers is configurable. | |
4528 + * Experiments show that things work better when this is off, so | |
4529 + * that's the way it is for now. */ | |
4530 +#undef USE_INDEX_REGISTERS | |
4531 + | |
4532 + | |
4533 +/* Macros to check register numbers against specific register classes. */ | |
4534 +#define REG_VALID_FOR_BASE_P(REGNO) \ | |
4535 + (((REGNO) < FIRST_PSEUDO_REGISTER) && A_REGNO_P (REGNO)) | |
4536 + | |
4537 +/* MC6809 index registers do not allow scaling, */ | |
4538 +/* but there is "accumulator-offset" mode. */ | |
4539 +#ifdef USE_INDEX_REGISTERS | |
4540 +#define REG_VALID_FOR_INDEX_P(REGNO) \ | |
4541 + (((REGNO) < FIRST_PSEUDO_REGISTER) && I_REGNO_P (REGNO)) | |
4542 +#else | |
4543 +#define REG_VALID_FOR_INDEX_P(REGNO) 0 | |
4544 +#endif | |
4545 + | |
4546 +/* Internal macro, the nonstrict definition for REGNO_OK_FOR_BASE_P */ | |
4547 +#define REGNO_OK_FOR_BASE_NONSTRICT_P(REGNO) \ | |
4548 + ((REGNO) >= FIRST_PSEUDO_REGISTER \ | |
4549 + || REG_VALID_FOR_BASE_P (REGNO) \ | |
4550 + || (REGNO) == FRAME_POINTER_REGNUM \ | |
4551 + || (REGNO) == HARD_FRAME_POINTER_REGNUM \ | |
4552 + || (REGNO) == ARG_POINTER_REGNUM \ | |
4553 + || (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO]))) | |
4554 + | |
4555 +/* Internal macro, the nonstrict definition for REGNO_OK_FOR_INDEX_P */ | |
4556 +#define REGNO_OK_FOR_INDEX_NONSTRICT_P(REGNO) \ | |
4557 + ((REGNO) >= FIRST_PSEUDO_REGISTER \ | |
4558 + || REG_VALID_FOR_INDEX_P (REGNO) \ | |
4559 + || (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO]))) | |
4560 + | |
4561 + | |
4562 +/* Internal macro, the strict definition for REGNO_OK_FOR_BASE_P */ | |
4563 +#define REGNO_OK_FOR_BASE_STRICT_P(REGNO) \ | |
4564 + ((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_BASE_P (REGNO) \ | |
4565 + : (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO]))) | |
4566 + | |
4567 + | |
4568 +/* Internal macro, the strict definition for REGNO_OK_FOR_INDEX_P */ | |
4569 +#define REGNO_OK_FOR_INDEX_STRICT_P(REGNO) \ | |
4570 + ((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_INDEX_P (REGNO) \ | |
4571 + : (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO]))) | |
4572 + | |
4573 + | |
4574 +#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_BASE_STRICT_P (REGNO) | |
4575 + | |
4576 +#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_INDEX_STRICT_P (REGNO) | |
4577 + | |
4578 +#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_STRICT_P (REGNO (X)) | |
4579 +#define REG_OK_FOR_BASE_NONSTRICT_P(X) REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (X)) | |
4580 +#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_STRICT_P (REGNO (X)) | |
4581 +#define REG_OK_FOR_INDEX_NONSTRICT_P(X) REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (X)) | |
4582 + | |
4583 +#ifndef REG_OK_STRICT | |
4584 +#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X) | |
4585 +#ifdef USE_INDEX_REGISTERS | |
4586 +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X) | |
4587 +#else | |
4588 +#define REG_OK_FOR_INDEX_P(X) 0 | |
4589 +#endif | |
4590 +#else | |
4591 +#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X) | |
4592 +#ifdef USE_INDEX_REGISTERS | |
4593 +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P (X) | |
4594 +#else | |
4595 +#define REG_OK_FOR_INDEX_P(X) 0 | |
4596 +#endif | |
4597 +#endif | |
4598 + | |
4599 +/* Maximum number of registers that can appear in a valid memory address */ | |
4600 +#ifdef USE_INDEX_REGISTERS | |
4601 +#define MAX_REGS_PER_ADDRESS 2 | |
4602 +#else | |
4603 +#define MAX_REGS_PER_ADDRESS 1 | |
4604 +#endif | |
4605 + | |
4606 +/* 1 if X is an rtx for a constant that is a valid address. | |
4607 + * We allow any constant, plus the sum of any two constants (this allows | |
4608 + * offsetting a symbol ref) */ | |
4609 +#define CONSTANT_ADDRESS_P(X) \ | |
4610 + ((CONSTANT_P (X)) \ | |
4611 + || ((GET_CODE (X) == PLUS) \ | |
4612 + && (CONSTANT_P (XEXP (X, 0))) && (CONSTANT_P (XEXP (X, 1))))) | |
4613 + | |
4614 +/* Nonzero if the constant value X is a legitimate general operand. | |
4615 + It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ | |
4616 +/* Any single-word constant is ok; the only contexts | |
4617 + allowing general_operand of mode DI or DF are movdi and movdf. */ | |
4618 +#define LEGITIMATE_CONSTANT_P(X) (GET_CODE (X) != CONST_DOUBLE) | |
4619 + | |
4620 +/* Nonzero if the X is a legitimate immediate operand in PIC mode. */ | |
4621 +#define LEGITIMATE_PIC_OPERAND_P(X) !symbolic_operand (X, VOIDmode) | |
4622 + | |
4623 +/*-------------------------------------------------------------- | |
4624 + Test for valid memory addresses | |
4625 +--------------------------------------------------------------*/ | |
4626 +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression | |
4627 + that is a valid memory address for an instruction. | |
4628 + The MODE argument is the machine mode for the MEM expression | |
4629 + that wants to use this address. */ | |
4630 + | |
4631 +/*-------------------------------------------------------------- | |
4632 + Valid addresses are either direct or indirect (MEM) versions | |
4633 + of the following forms. | |
4634 + constant N | |
4635 + register ,X | |
4636 + constant indexed N,X | |
4637 + accumulator indexed D,X | |
4638 + auto_increment ,X++ | |
4639 + auto_decrement ,--X | |
4640 +--------------------------------------------------------------*/ | |
4641 + | |
4642 +#define REGISTER_ADDRESS_P(X) \ | |
4643 + (REG_P (X) && REG_OK_FOR_BASE_P (X)) | |
4644 + | |
4645 +#define EXTENDED_ADDRESS_P(X) \ | |
4646 + CONSTANT_ADDRESS_P (X) \ | |
4647 + | |
4648 +#define LEGITIMATE_BASE_P(X) \ | |
4649 + ((REG_P (X) && REG_OK_FOR_BASE_P (X)) \ | |
4650 + || (GET_CODE (X) == SIGN_EXTEND \ | |
4651 + && GET_CODE (XEXP (X, 0)) == REG \ | |
4652 + && GET_MODE (XEXP (X, 0)) == HImode \ | |
4653 + && REG_OK_FOR_BASE_P (XEXP (X, 0)))) | |
4654 + | |
4655 +#define LEGITIMATE_OFFSET_P(X) \ | |
4656 + (CONSTANT_ADDRESS_P (X) || (REG_P (X) && REG_OK_FOR_INDEX_P (X))) | |
4657 + | |
4658 +/* 1 if X is the sum of a base register and an offset. */ | |
4659 +#define INDEXED_ADDRESS(X) \ | |
4660 + ((GET_CODE (X) == PLUS \ | |
4661 + && LEGITIMATE_BASE_P (XEXP (X, 0)) \ | |
4662 + && LEGITIMATE_OFFSET_P (XEXP (X, 1))) \ | |
4663 + || (GET_CODE (X) == PLUS \ | |
4664 + && LEGITIMATE_BASE_P (XEXP (X, 1)) \ | |
4665 + && LEGITIMATE_OFFSET_P (XEXP (X, 0)))) | |
4666 + | |
4667 +#define STACK_REG_P(X) (REG_P(X) && REGNO(X) == HARD_S_REGNUM) | |
4668 + | |
4669 +#define STACK_PUSH_P(X) \ | |
4670 + (MEM_P (X) && GET_CODE (XEXP (X, 0)) == PRE_DEC && STACK_REG_P (XEXP (XEXP (X, 0), 0))) | |
4671 + | |
4672 +#define STACK_POP_P(X) \ | |
4673 + (MEM_P (X) && GET_CODE (XEXP (X, 0)) == POST_INC && STACK_REG_P (XEXP (XEXP (X, 0), 0))) | |
4674 + | |
4675 +#define PUSH_POP_ADDRESS_P(X) \ | |
4676 + (((GET_CODE (X) == PRE_DEC) || (GET_CODE (X) == POST_INC)) \ | |
4677 + && (LEGITIMATE_BASE_P (XEXP (X, 0)))) | |
4678 + | |
4679 +/* Go to ADDR if X is a valid address. */ | |
4680 +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ | |
4681 +{ \ | |
4682 + if (REGISTER_ADDRESS_P(X)) goto ADDR; \ | |
4683 + if (PUSH_POP_ADDRESS_P (X)) goto ADDR; \ | |
4684 + if (EXTENDED_ADDRESS_P (X)) goto ADDR; \ | |
4685 + if (INDEXED_ADDRESS (X)) goto ADDR; \ | |
4686 + if (MEM_P (X) && REGISTER_ADDRESS_P(XEXP (X, 0))) goto ADDR; \ | |
4687 + if (MEM_P (X) && PUSH_POP_ADDRESS_P (XEXP (X, 0))) goto ADDR; \ | |
4688 + if (MEM_P (X) && EXTENDED_ADDRESS_P (XEXP (X, 0))) goto ADDR; \ | |
4689 + if (MEM_P (X) && INDEXED_ADDRESS (XEXP (X, 0))) goto ADDR; \ | |
4690 +} | |
4691 + | |
4692 +/*-------------------------------------------------------------- | |
4693 + Address Fix-up | |
4694 +--------------------------------------------------------------*/ | |
4695 +/* Go to LABEL if ADDR (a legitimate address expression) | |
4696 + has an effect that depends on the machine mode it is used for. | |
4697 + In the latest GCC, this case is already handled by the core code | |
4698 + so no action is required here. */ | |
4699 +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {} | |
4700 + | |
4701 + | |
4702 +/*-------------------------------------------------------------- | |
4703 + Miscellaneous Parameters | |
4704 +--------------------------------------------------------------*/ | |
4705 +/* Specify the machine mode that this machine uses | |
4706 + for the index in the tablejump instruction. */ | |
4707 +#define CASE_VECTOR_MODE Pmode | |
4708 + | |
4709 +/* Define this as 1 if `char' should by default be signed; else as 0. */ | |
4710 +#define DEFAULT_SIGNED_CHAR 0 | |
4711 + | |
4712 +/* This flag, if defined, says the same insns that convert to a signed fixnum | |
4713 + also convert validly to an unsigned one. */ | |
4714 +#define FIXUNS_TRUNC_LIKE_FIX_TRUNC | |
4715 + | |
4716 +/* Max number of bytes we can move from memory to memory/register | |
4717 + in one reasonably fast instruction. */ | |
4718 +#define MOVE_MAX 2 | |
4719 + | |
4720 +/* Int can be 8 or 16 bits (default is 16) */ | |
4721 +#define INT_TYPE_SIZE (TARGET_BYTE_INT ? 8 : 16) | |
4722 + | |
4723 +/* Short is always 16 bits */ | |
4724 +#define SHORT_TYPE_SIZE (TARGET_BYTE_INT ? 8 : 16) | |
4725 + | |
4726 +/* Size (bits) of the type "long" on target machine */ | |
4727 +#define LONG_TYPE_SIZE (TARGET_BYTE_INT ? 16 : 32) | |
4728 + | |
4729 +/* Size (bits) of the type "long long" on target machine */ | |
4730 +#define LONG_LONG_TYPE_SIZE 32 | |
4731 + | |
4732 +/* Size (bits) of the type "char" on target machine */ | |
4733 +#define CHAR_TYPE_SIZE 8 | |
4734 + | |
4735 +/* Size (bits) of the type "float" on target machine */ | |
4736 +#define FLOAT_TYPE_SIZE 32 | |
4737 + | |
4738 +/* Size (bits) of the type "double" on target machine. | |
4739 + * Note that the C standard does not require that doubles | |
4740 + * hold any more bits than float. Since the 6809 has so few | |
4741 + * registers, we cannot really support more than 32-bits. */ | |
4742 +#define DOUBLE_TYPE_SIZE 32 | |
4743 + | |
4744 +/* Size (bits) of the type "long double" on target machine */ | |
4745 +#define LONG_DOUBLE_TYPE_SIZE 32 | |
4746 + | |
4747 +/* Define the type used for "size_t". With a 64KB address space, | |
4748 + * only a 16-bit value here makes sense. */ | |
4749 +#define SIZE_TYPE (TARGET_BYTE_INT ? "long unsigned int" : "unsigned int") | |
4750 + | |
4751 +/* Likewise, the difference between two pointers is also a 16-bit | |
4752 + * signed value. */ | |
4753 +#define PTRDIFF_TYPE (TARGET_BYTE_INT ? "long int" : "int") | |
4754 + | |
4755 +/* Nonzero if access to memory by bytes is slow and undesirable. */ | |
4756 +#define SLOW_BYTE_ACCESS 0 | |
4757 + | |
4758 +/* Define if shifts truncate the shift count | |
4759 + which implies one can omit a sign-extension or zero-extension | |
4760 + of a shift count. */ | |
4761 +#define SHIFT_COUNT_TRUNCATED 0 | |
4762 + | |
4763 +/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits | |
4764 + is done just by pretending it is already truncated. */ | |
4765 +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 | |
4766 + | |
4767 +/* It is as good to call a constant function address as to | |
4768 + call an address kept in a register. */ | |
4769 +#define NO_FUNCTION_CSE | |
4770 + | |
4771 +/* Specify the machine mode that pointers have. | |
4772 + After generation of rtl, the compiler makes no further distinction | |
4773 + between pointers and any other objects of this machine mode. */ | |
4774 +#define Pmode HImode | |
4775 + | |
4776 +/* A function address in a call instruction | |
4777 + is a byte address (for indexing purposes) | |
4778 + so give the MEM rtx a byte's mode. */ | |
4779 +#define FUNCTION_MODE HImode | |
4780 + | |
4781 +/* Define the cost of moving a value from a register in CLASS1 | |
4782 + * to CLASS2, of a given MODE. | |
4783 + * | |
4784 + * On the 6809, hard register transfers are all basically equivalent. | |
4785 + * But soft register moves are treated more like memory moves. */ | |
4786 +#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \ | |
4787 + (((CLASS1 == M_REGS) || (CLASS2 == M_REGS)) ? 4 : 7) | |
4788 + | |
4789 +/* Define the cost of moving a value between a register and memory. */ | |
4790 +#define MEMORY_MOVE_COST(MODE, CLASS, IN) 5 | |
4791 + | |
4792 +/* Check a `double' value for validity for a particular machine mode. */ | |
4793 + | |
4794 +#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \ | |
4795 + ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW)) | |
4796 + | |
4797 + | |
4798 +/*-------------------------------------------------------------- | |
4799 + machine-dependent | |
4800 +--------------------------------------------------------------*/ | |
4801 +/* Tell final.c how to eliminate redundant test instructions. */ | |
4802 + | |
4803 +/* Here we define machine-dependent flags and fields in cc_status | |
4804 + (see `conditions.h'). */ | |
4805 + | |
4806 +/* Store in cc_status the expressions | |
4807 + that the condition codes will describe | |
4808 + after execution of an instruction whose pattern is EXP. | |
4809 + Do not alter them if the instruction would not alter the cc's. */ | |
4810 + | |
4811 +/* On the 6809, most of the insns to store in an address register | |
4812 + fail to set the cc's. However, in some cases these instructions | |
4813 + can make it possibly invalid to use the saved cc's. In those | |
4814 + cases we clear out some or all of the saved cc's so they won't be used. */ | |
4815 + | |
4816 +#define NOTICE_UPDATE_CC(EXP, INSN) \ | |
4817 + notice_update_cc((EXP), (INSN)) | |
4818 + | |
4819 +/***************************************************************************** | |
4820 +** | |
4821 +** pragma support | |
4822 +** | |
4823 +*****************************************************************************/ | |
4824 + | |
4825 +#if 0 | |
4826 +#define REGISTER_TARGET_PRAGMAS() \ | |
4827 +do { \ | |
4828 + extern void pragma_section PARAMS ((cpp_reader *)); \ | |
4829 + c_register_pragma (0, "section", pragma_section); \ | |
4830 +} while (0) | |
4831 + | |
4832 +#endif | |
4833 + | |
4834 +/*-------------------------------------------------------------- | |
4835 + ASSEMBLER FORMAT | |
4836 +--------------------------------------------------------------*/ | |
4837 + | |
4838 +#define FMT_HOST_WIDE_INT "%ld" | |
4839 + | |
4840 +/* Output to assembler file text saying following lines | |
4841 + may contain character constants, extra white space, comments, etc. */ | |
4842 +#define ASM_APP_ON ";----- asm -----\n" | |
4843 + | |
4844 +/* Output to assembler file text saying following lines | |
4845 + no longer contain unusual constructs. */ | |
4846 +#define ASM_APP_OFF ";--- end asm ---\n" | |
4847 + | |
4848 +/* Use a semicolon to begin a comment. */ | |
4849 +#define ASM_COMMENT_START "; " | |
4850 + | |
4851 +/* Output assembly directives to switch to section 'name' */ | |
4852 +#undef TARGET_ASM_NAMED_SECTION | |
4853 +#define TARGET_ASM_NAMED_SECTION m6809_asm_named_section | |
4854 + | |
4855 +#undef TARGET_HAVE_NAMED_SECTION | |
4856 +#define TARGET_HAVE_NAMED_SECTION m6809_have_named_section | |
4857 + | |
4858 +/* Output before read-only data. */ | |
4859 +#define TEXT_SECTION_ASM_OP (code_section_op) | |
4860 + | |
4861 +/* Output before writable data. */ | |
4862 +#define DATA_SECTION_ASM_OP (data_section_op) | |
4863 + | |
4864 +/* Output before uninitialized data. */ | |
4865 +#define BSS_SECTION_ASM_OP (bss_section_op) | |
4866 + | |
4867 +/* Support the ctors and dtors sections for g++. */ | |
4868 + | |
4869 +#undef CTORS_SECTION_ASM_OP | |
4870 +#define CTORS_SECTION_ASM_OP "\t.area .ctors" | |
4871 +#undef DTORS_SECTION_ASM_OP | |
4872 +#define DTORS_SECTION_ASM_OP "\t.area .dtors" | |
4873 + | |
4874 + | |
4875 +#undef DO_GLOBAL_CTORS_BODY | |
4876 +#undef DO_GLOBAL_DTORS_BODY | |
4877 + | |
4878 +#define HAS_INIT_SECTION | |
4879 + | |
4880 +/* This is how to output an assembler line | |
4881 + that says to advance the location counter | |
4882 + to a multiple of 2**LOG bytes. */ | |
4883 + | |
4884 +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ | |
4885 + if ((LOG) > 1) \ | |
4886 + fprintf (FILE, "\t.bndry %u\n", 1 << (LOG)) | |
4887 + | |
4888 +/* The .set foo,bar construct doesn't work by default */ | |
4889 +#undef SET_ASM_OP | |
4890 +#define ASM_OUTPUT_DEF(FILE, LABEL1, LABEL2) \ | |
4891 + do \ | |
4892 + { \ | |
4893 + fputc ('\t', FILE); \ | |
4894 + assemble_name (FILE, LABEL1); \ | |
4895 + fputs (" = ", FILE); \ | |
4896 + assemble_name (FILE, LABEL2); \ | |
4897 + fputc ('\n', FILE); \ | |
4898 + } \ | |
4899 + while (0) | |
4900 + | |
4901 +/* How to refer to registers in assembler output. | |
4902 + This sequence is indexed by compiler's hard-register-number (see above). */ | |
4903 +#define MNAME(x) [SOFT_M0_REGNUM+(x)] = "*m" C_STRING(x) , | |
4904 + | |
4905 +#define REGISTER_NAMES { \ | |
4906 + [HARD_D_REGNUM]= "d", \ | |
4907 + [HARD_X_REGNUM]= "x", \ | |
4908 + [HARD_Y_REGNUM]= "y", \ | |
4909 + [HARD_U_REGNUM]= "u", \ | |
4910 + [HARD_S_REGNUM]= "s", \ | |
4911 + [HARD_PC_REGNUM]= "pc", \ | |
4912 + [HARD_A_REGNUM]= "a", \ | |
4913 + [HARD_B_REGNUM]= "b", \ | |
4914 + [HARD_CC_REGNUM]= "cc",\ | |
4915 + [HARD_DP_REGNUM]= "dp", \ | |
4916 + [SOFT_FP_REGNUM]= "soft_fp", \ | |
4917 + [SOFT_AP_REGNUM]= "soft_ap", \ | |
4918 + MNAME(0) MNAME(1) MNAME(2) MNAME(3) \ | |
4919 + MNAME(4) MNAME(5) MNAME(6) MNAME(7) \ | |
4920 + [HARD_RSVD1_REGNUM] = "-", \ | |
4921 + [HARD_Z_REGNUM] = "z" /* bit 2 of CC */ } | |
4922 + | |
4923 +/***************************************************************************** | |
4924 +** | |
4925 +** Debug Support | |
4926 +** | |
4927 +*****************************************************************************/ | |
4928 + | |
4929 +/* Default to DBX-style debugging */ | |
4930 +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG | |
4931 + | |
4932 +#define DBX_DEBUGGING_INFO | |
4933 + | |
4934 +#define DEFAULT_GDB_EXTENSIONS 0 | |
4935 + | |
4936 +#define ASM_STABS_OP ";\t.stabs\t" | |
4937 +#define ASM_STABD_OP ";\t.stabd\t" | |
4938 +#define ASM_STABN_OP ";\t.stabn\t" | |
4939 + | |
4940 +#define DBX_CONTIN_LENGTH 54 | |
4941 + | |
4942 +#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(ASMFILE, FILENAME) \ | |
4943 +do { \ | |
4944 + const char *p = FILENAME; \ | |
4945 + while ((p = strchr (p, '/')) != NULL) { \ | |
4946 + p = FILENAME = p+1; \ | |
4947 + } \ | |
4948 + fprintf (ASMFILE, "%s", ASM_STABS_OP); \ | |
4949 + output_quoted_string (ASMFILE, FILENAME); \ | |
4950 + fprintf (ASMFILE, ",%d,0,0,", N_SO); \ | |
4951 + assemble_name (ASMFILE, ltext_label_name); \ | |
4952 + fputc ('\n', ASMFILE); \ | |
4953 + switch_to_section (text_section); \ | |
4954 + (*targetm.asm_out.internal_label) (ASMFILE, "Ltext", 0); \ | |
4955 +} while (0) | |
4956 + | |
4957 +/* With -g, GCC sometimes outputs string literals that are longer than | |
4958 + * the assembler can handle. Without actual debug support, these are | |
4959 + * not really required. Redefine the function to output strings to | |
4960 + * output as much as possible. */ | |
4961 +#define OUTPUT_QUOTED_STRING(FILE, STR) m6809_output_quoted_string (FILE, STR) | |
4962 + | |
4963 +/***************************************************************************** | |
4964 +** | |
4965 +** Output and Generation of Labels | |
4966 +** | |
4967 +*****************************************************************************/ | |
4968 + | |
4969 +/* Prefixes for various assembly-time objects */ | |
4970 + | |
4971 +#define REGISTER_PREFIX "" | |
4972 + | |
4973 +#define LOCAL_LABEL_PREFIX "" | |
4974 + | |
4975 +#define USER_LABEL_PREFIX "_" | |
4976 + | |
4977 +#define IMMEDIATE_PREFIX "#" | |
4978 + | |
4979 +/* This is how to output the definition of a user-level label named NAME, | |
4980 + such as the label on a static function or variable NAME. */ | |
4981 + | |
4982 +#define ASM_OUTPUT_LABEL(FILE,NAME) \ | |
4983 +do { \ | |
4984 + if (section_changed) { \ | |
4985 + fprintf (FILE, "\n%s\n\n", code_section_op); \ | |
4986 + section_changed = 0; \ | |
4987 + } \ | |
4988 + assemble_name (FILE, NAME); \ | |
4989 + fputs (":\n", FILE); \ | |
4990 +} while (0) | |
4991 + | |
4992 +/* This is how to output the label for a function definition. It | |
4993 + invokes ASM_OUTPUT_LABEL, but may examine the DECL tree node for | |
4994 + other properties. */ | |
4995 +#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \ | |
4996 + m6809_declare_function_name (FILE,NAME,DECL) | |
4997 + | |
4998 +/* This is how to output a command to make the user-level label | |
4999 + named NAME defined for reference from other files. */ | |
5000 + | |
5001 +#define GLOBAL_ASM_OP "\t.globl " | |
5002 + | |
5003 +/* This is how to output a reference to a user label named NAME. */ | |
5004 +#define ASM_OUTPUT_LABELREF(FILE,NAME) \ | |
5005 + fprintf (FILE, "_%s", NAME) | |
5006 + | |
5007 +/* This is how to output a reference to a symbol ref | |
5008 + * Check to see if the symbol is in the direct page */ | |
5009 +#define ASM_OUTPUT_SYMBOL_REF(FILE,sym) \ | |
5010 +{ \ | |
5011 + print_direct_prefix (FILE, sym); \ | |
5012 + assemble_name (FILE, XSTR (sym, 0)); \ | |
5013 +} | |
5014 + | |
5015 +/* External references aren't necessary, so don't emit anything */ | |
5016 +#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) | |
5017 + | |
5018 +/* This is how to store into the string LABEL | |
5019 + the symbol_ref name of an internal numbered label where | |
5020 + PREFIX is the class of label and NUM is the number within the class. | |
5021 + This is suitable for output with `assemble_name'. */ | |
5022 +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ | |
5023 + sprintf (LABEL, "*%s%lu", PREFIX, (unsigned long int)NUM) | |
5024 + | |
5025 +/* This is how to output an assembler line defining an `int' constant. */ | |
5026 +#define ASM_OUTPUT_INT(FILE,VALUE) \ | |
5027 +( fprintf (FILE, "\t.word "), \ | |
5028 + output_addr_const (FILE, (VALUE)), \ | |
5029 + fprintf (FILE, "\n")) | |
5030 + | |
5031 +/* Likewise for `char' and `short' constants. */ | |
5032 +#define ASM_OUTPUT_SHORT(FILE,VALUE) \ | |
5033 +( fprintf (FILE, "\t.word "), \ | |
5034 + output_addr_const (FILE, (VALUE)), \ | |
5035 + fprintf (FILE, "\n")) | |
5036 + | |
5037 +/* This is how to output a string. */ | |
5038 +#define ASM_OUTPUT_ASCII(FILE,STR,SIZE) m6809_output_ascii (FILE, STR, SIZE) | |
5039 + | |
5040 +/* This is how to output an insn to push a register on the stack. | |
5041 + It need not be very fast code. */ | |
5042 + | |
5043 +#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ | |
5044 + fprintf (FILE, "\tpshs\t%s\n", reg_names[REGNO]) | |
5045 + | |
5046 +/* This is how to output an insn to pop a register from the stack. | |
5047 + It need not be very fast code. */ | |
5048 + | |
5049 +#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ | |
5050 + fprintf (FILE, "\tpuls\t%s\n", reg_names[REGNO]) | |
5051 + | |
5052 +/* This is how to output an element of a case-vector that is absolute. */ | |
5053 + | |
5054 +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ | |
5055 + fprintf (FILE, "\t.word L%u\n", VALUE) | |
5056 + | |
5057 +/* This is how to output an element of a case-vector that is relative. */ | |
5058 + | |
5059 +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ | |
5060 + fprintf (FILE, "\t.word L%u-L%u\n", VALUE, REL) | |
5061 + | |
5062 + | |
5063 +/***************************************************************************** | |
5064 +** | |
5065 +** Assembler Commands for Alignment | |
5066 +** | |
5067 +*****************************************************************************/ | |
5068 + | |
5069 +/* ASM_OUTPUT_SKIP is supposed to zero initialize the data. | |
5070 + * So use the .byte and .word directives instead of .blkb */ | |
5071 +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ | |
5072 + do { \ | |
5073 + int __size = SIZE; \ | |
5074 + while (__size > 0) { \ | |
5075 + if (__size >= 2) \ | |
5076 + { \ | |
5077 + fprintf (FILE, "\t.word\t0\t;skip space %d\n", __size); \ | |
5078 + __size -= 2; \ | |
5079 + } \ | |
5080 + else \ | |
5081 + { \ | |
5082 + fprintf (FILE, "\t.byte\t0\t;skip space\n"); \ | |
5083 + __size--; \ | |
5084 + } \ | |
5085 + } \ | |
5086 + } while (0) | |
5087 + | |
5088 +/* This says how to output an assembler line | |
5089 + to define a global common symbol. */ | |
5090 + | |
5091 +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ | |
5092 + do { \ | |
5093 + switch_to_section (bss_section); \ | |
5094 + fputs ("\t.globl\t", FILE); \ | |
5095 + assemble_name ((FILE), (NAME)); \ | |
5096 + fputs ("\n", FILE); \ | |
5097 + assemble_name ((FILE), (NAME)); \ | |
5098 + fprintf ((FILE), ":\t.blkb\t" FMT_HOST_WIDE_INT "\n", (ROUNDED));} while(0) | |
5099 + | |
5100 +/* This says how to output an assembler line | |
5101 + to define a local common symbol. */ | |
5102 + | |
5103 +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ | |
5104 +do { \ | |
5105 + switch_to_section (bss_section); \ | |
5106 + assemble_name ((FILE), (NAME)); \ | |
5107 + fprintf ((FILE), ":\t.blkb\t" FMT_HOST_WIDE_INT "\n", (ROUNDED));} while(0) | |
5108 + | |
5109 +/* Store in OUTPUT a string (made with alloca) containing | |
5110 + an assembler-name for a local static variable named NAME. | |
5111 + LABELNO is an integer which is different for each call. */ | |
5112 + | |
5113 +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ | |
5114 +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ | |
5115 + sprintf ((OUTPUT), "%s.%lu", (NAME), (unsigned long int)(LABELNO))) | |
5116 + | |
5117 +/* Print an instruction operand X on file FILE. | |
5118 + CODE is the code from the %-spec for printing this operand. | |
5119 + If `%z3' was used to print operand 3, then CODE is 'z'. */ | |
5120 +#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE) | |
5121 + | |
5122 +/* Print a memory operand whose address is X, on file FILE. */ | |
5123 +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) | |
5124 + | |
5125 +/* Don't let stack pushes build up too much. */ | |
5126 +#define MAX_PENDING_STACK 8 | |
5127 + | |
5128 +/* Define values for builtin operations */ | |
5129 +enum m6809_builtins | |
5130 +{ | |
5131 + M6809_SWI, | |
5132 + M6809_SWI2, | |
5133 + M6809_SWI3, | |
5134 + M6809_CWAI, | |
5135 + M6809_SYNC, | |
5136 + M6809_ADD_CARRY, | |
5137 + M6809_SUB_CARRY, | |
5138 + M6809_ADD_DECIMAL, | |
5139 + M6809_NOP, | |
5140 + M6809_BLOCKAGE | |
5141 +}; | |
5142 + | |
5143 diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.md gcc-4.6.1/gcc/config/m6809/m6809.md | |
5144 --- gcc-4.6.1-orig/gcc/config/m6809/m6809.md 1969-12-31 17:00:00.000000000 -0700 | |
5145 +++ gcc-4.6.1/gcc/config/m6809/m6809.md 2011-09-21 20:40:01.287068005 -0600 | |
5146 @@ -0,0 +1,2359 @@ | |
5147 +;; GCC machine description for Motorola 6809 | |
5148 +;; Copyright (C) 1989, 2005, 2006, 2007, 2008, | |
5149 +;; 2009 Free Software Foundation, Inc. | |
5150 +;; | |
5151 +;; Mostly by Brian Dominy (brian@oddchange.com) with substantial renovations | |
5152 +;; by William Astle (lost@l-w.ca). | |
5153 +;; | |
5154 +;; Based on earlier work by Tom Jones (jones@sal.wisc.edu) and | |
5155 +;; Matthias Doerfel (msdoerfe@informatik.uni-erlangen.de) | |
5156 +;; | |
5157 +;; This file is part of GCC. | |
5158 +;; | |
5159 +;; GCC is free software; you can redistribute it and/or modify | |
5160 +;; it under the terms of the GNU General Public License as published by | |
5161 +;; the Free Software Foundation; either version 3, or (at your option) | |
5162 +;; any later version. | |
5163 +;; | |
5164 +;; GCC is distributed in the hope that it will be useful, | |
5165 +;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
5166 +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
5167 +;; GNU General Public License for more details. | |
5168 +;; | |
5169 +;; You should have received a copy of the GNU General Public License | |
5170 +;; along with GCC; see the file COPYING3. If not see | |
5171 +;; <http://www.gnu.org/licenses/>. | |
5172 +;; | |
5173 +;; General information: | |
5174 +;; -------------------- | |
5175 +;; * This backend is mostly a rewrite from earlier (3.1.1 and before) | |
5176 +;; versions. | |
5177 +;; | |
5178 +;; * The 'A' and 'B' registers are treated as a single register by the | |
5179 +;; register allocator; hence, the instruction templates assume that | |
5180 +;; both can be modified if either one is available for use. No | |
5181 +;; attempt is made to split instructions to refer to a particular half | |
5182 +;; of the register. It is always referred to as the 'D' register, even | |
5183 +;; in QImode (when it will be displayed as 'B'). | |
5184 +;; | |
5185 +;; * There is full support for proper branch instruction generation, | |
5186 +;; based on instruction lengths. However, many instruction patterns | |
5187 +;; are still overloaded to emit lots of real instructions, which can | |
5188 +;; make the length calculation difficult; in those cases, I've tried | |
5189 +;; to be pessimistic and assume the worst-case. | |
5190 +;; | |
5191 +;; * The instruction type attributes are only defined for branch | |
5192 +;; vs. non branch instructions for now, since there is seemingly no | |
5193 +;; reason to define these for other types anyway. | |
5194 +;; | |
5195 +;; * The limited number of total registers presents the greatest | |
5196 +;; challenge. There are 'soft registers' -- memory locations | |
5197 +;; used to simulate real regs -- which can be helpful. | |
5198 +;; | |
5199 +;; * Position-independent code (PIC) is supported and has been tested | |
5200 +;; but not to the extent of absolute code generation. | |
5201 +;; | |
5202 +;; * All of the 6809 special opcodes, e.g. SWI and SYNC, are defined | |
5203 +;; as UNSPEC instructions, and can be accessed from C code using | |
5204 +;; __builtin_xxxx() style functions. | |
5205 +;; | |
5206 +;; What still needs to be done: | |
5207 +;; ---------------------------- | |
5208 +;; * Replace remaining instances of (define_peephole) with | |
5209 +;; (define_peephole2), or remove them completely if they are not | |
5210 +;; matching anyway. Add more peepholes for things actually encountered. | |
5211 +;; | |
5212 +;; * Indexing addressing can lead to crashes in complex functions when | |
5213 +;; register pressure is high. Only the 'D' register can actually be | |
5214 +;; used as an index register, and its demand by other instructions | |
5215 +;; can sometimes mean that it is impossible to satisfy constraints. | |
5216 +;; Currently, indexing is completely disabled to avoid these types | |
5217 +;; of problems, although code is slightly more inefficient in some | |
5218 +;; working cases. | |
5219 +;; | |
5220 +;; * 32-bit math is terribly inefficient. | |
5221 +;; | |
5222 + | |
5223 + | |
5224 +;;-------------------------------------------------------------------- | |
5225 +;;- Constants | |
5226 +;;-------------------------------------------------------------------- | |
5227 + | |
5228 +; | |
5229 +; Define constants for hard register numbers. | |
5230 +; | |
5231 +(define_constants [ | |
5232 + (HARD_RSVD1_REGNUM 0) | |
5233 + (HARD_X_REGNUM 1) (HARD_Y_REGNUM 2) (HARD_U_REGNUM 3) | |
5234 + (HARD_S_REGNUM 4) (HARD_PC_REGNUM 5) (HARD_D_REGNUM 6) | |
5235 + (HARD_Z_REGNUM 7) | |
5236 + (HARD_A_REGNUM 8) (HARD_B_REGNUM 9) | |
5237 + (HARD_CC_REGNUM 10) (HARD_DP_REGNUM 11) | |
5238 + (SOFT_FP_REGNUM 12) (SOFT_AP_REGNUM 13) | |
5239 + (SOFT_M0_REGNUM 14) (SOFT_M1_REGNUM 15) | |
5240 + (SOFT_M2_REGNUM 16) (SOFT_M3_REGNUM 17) | |
5241 +]) | |
5242 + | |
5243 + | |
5244 +; | |
5245 +; The range in which a short branch insn can be used. | |
5246 +; | |
5247 +(define_constants [ | |
5248 + (MIN_SHORT_BRANCH_OFFSET -127) | |
5249 + (MAX_SHORT_BRANCH_OFFSET 128) | |
5250 +]) | |
5251 + | |
5252 + | |
5253 +; | |
5254 +; The lengths of various types of real 6809 instructions. | |
5255 +; | |
5256 +; By default, ordinary insns are 4 bytes long. This is often not | |
5257 +; right, and the insn patterns below will redefine this to the | |
5258 +; correct value. | |
5259 +; | |
5260 +; Branch instruction lengths (conditional and unconditionals) are | |
5261 +; well known and declared here. The short insns are used when the | |
5262 +; offset is within the range declared above (between MIN_SHORT | |
5263 +; and MAX_SHORT) ; otherwise the long form is used. | |
5264 +; | |
5265 +(define_constants [ | |
5266 + (DEFAULT_INSN_LENGTH 4) | |
5267 + (SHORT_CBRANCH_LENGTH 2) | |
5268 + (LONG_CBRANCH_LENGTH 4) | |
5269 + (SHORT_BRANCH_LENGTH 2) | |
5270 + (LONG_BRANCH_LENGTH 3) | |
5271 +]) | |
5272 + | |
5273 + | |
5274 +; | |
5275 +; Constants for insn cycle counts. | |
5276 +; Note that these counts all assume 1-byte opcodes. 2-byte | |
5277 +; opcodes require 1 extra cycles for fetching the extra byte. | |
5278 +; | |
5279 +(define_constants [ | |
5280 + ;; The default insn length, when it cannot be calculated. | |
5281 + ;; Take a conservative approach and estimate high. | |
5282 + (DEFAULT_INSN_CYCLES 10) | |
5283 + | |
5284 + ;; Cycle counts for ALU and load operations. | |
5285 + (ALU_INHERENT_CYCLES 2) | |
5286 + (ALU_IMMED_CYCLES 2) | |
5287 + (ALU_DIRECT_CYCLES 4) | |
5288 + (ALU_INDEXED_BASE_CYCLES 4) | |
5289 + (ALU_EXTENDED_CYCLES 5) | |
5290 + | |
5291 + ;; If an ALU operation is on a 16-bit register (D), then | |
5292 + ;; add this number of cycles to the total count. | |
5293 + (ALU_16BIT_CYCLES 2) | |
5294 + | |
5295 + ;; A load of a 16-bit register incurs this extra amount. | |
5296 + (LOAD_16BIT_CYCLES 1) | |
5297 + | |
5298 + ;; Cycle counts for memory-only operations (bit shifts, clear, test) | |
5299 + (MEM_DIRECT_CYCLES 6) | |
5300 + (MEM_INDEXED_BASE_CYCLES 6) | |
5301 + (MEM_EXTENDED_CYCLES 7) | |
5302 + | |
5303 + ;; Cycle count for any reg-reg transfer (regardless of size) | |
5304 + (EXG_CYCLES 8) | |
5305 + (TFR_CYCLES 6) | |
5306 + | |
5307 + ;; Cycle count for a condition code update (andcc/orcc) | |
5308 + (CC_CYCLES 3) | |
5309 + | |
5310 + (JMP_DIRECT_CYCLES 3) | |
5311 + (JMP_INDEXED_BASE_CYCLES 3) | |
5312 + (JMP_EXTENDED_CYCLES 4) | |
5313 + | |
5314 + (JSR_DIRECT_CYCLES 7) | |
5315 + (JSR_INDEXED_BASE_CYCLES 7) | |
5316 + (JSR_EXTENDED_CYCLES 8) | |
5317 + | |
5318 + (LEA_BASE_CYCLES 4) | |
5319 + | |
5320 + ;; Cycle count for a psh/pul operations. Add to this the | |
5321 + ;; total number of bytes moved for the correct count. | |
5322 + (PSH_PUL_CYCLES 5) | |
5323 + | |
5324 + ;; Miscellaneous cycle counts | |
5325 + (CWAI_CYCLES 20) | |
5326 + (MUL_CYCLES 11) | |
5327 + (NOP_CYCLES 2) | |
5328 + (RTI_CYCLES 15) | |
5329 + (RTS_CYCLES 5) | |
5330 + (SWI_CYCLES 20) | |
5331 + (SYNC_CYCLES 4) | |
5332 +]) | |
5333 + | |
5334 + | |
5335 +; | |
5336 +; An enumeration of values for each "unspec"; i.e. unspecified | |
5337 +; instruction. These represent insns that are meaningful on the | |
5338 +; 6809 but which have no intrinsic meaning to GCC itself. | |
5339 +; These insns can be generated explicitly using the __builtin_xxx | |
5340 +; syntax; they are also implicitly generated by the backend | |
5341 +; as needed to implement other insns. | |
5342 +; | |
5343 +(define_constants [ | |
5344 + (UNSPEC_BLOCKAGE 0) | |
5345 + (UNSPEC_PUSH_RS 1) | |
5346 + (UNSPEC_POP_RS 2) | |
5347 + (UNSPEC_SWI 3) | |
5348 + (UNSPEC_CWAI 4) | |
5349 + (UNSPEC_ADD_CARRY 5) | |
5350 + (UNSPEC_SUB_CARRY 6) | |
5351 + (UNSPEC_SYNC 7) | |
5352 + (UNSPEC_ADD_DECIMAL 8) | |
5353 +]) | |
5354 + | |
5355 + | |
5356 +;;-------------------------------------------------------------------- | |
5357 +;;- Predicates | |
5358 +;;-------------------------------------------------------------------- | |
5359 + | |
5360 +(include "predicates.md") | |
5361 + | |
5362 +;;-------------------------------------------------------------------- | |
5363 +;;- Attributes | |
5364 +;;-------------------------------------------------------------------- | |
5365 + | |
5366 +;; | |
5367 +;; The type attribute is used to distinguish between different | |
5368 +;; types of branch instructions, so that their lengths can be | |
5369 +;; calculated correctly. | |
5370 +;; | |
5371 +(define_attr "type" "branch,cbranch,unknown" (const_string "unknown")) | |
5372 + | |
5373 +;; | |
5374 +;; The length of a branch instruction is calculated based on how | |
5375 +;; far away the branch target is. Lengths of other insns default | |
5376 +;; to 4. set_attr is used in instruction templates to specify | |
5377 +;; the length when it is known exactly. When not sure, err on | |
5378 +;; the high side to avoid compile errors. | |
5379 +;; | |
5380 +(define_attr "length" "" | |
5381 + (cond [ | |
5382 + (eq_attr "type" "branch") | |
5383 + (if_then_else (lt (minus (match_dup 0) (pc)) | |
5384 + (const_int MIN_SHORT_BRANCH_OFFSET)) | |
5385 + (const_int LONG_BRANCH_LENGTH) | |
5386 + (if_then_else (gt (minus (match_dup 0) (pc)) | |
5387 + (const_int MAX_SHORT_BRANCH_OFFSET)) | |
5388 + (const_int LONG_BRANCH_LENGTH) | |
5389 + (const_int SHORT_BRANCH_LENGTH))) | |
5390 + (eq_attr "type" "cbranch") | |
5391 + (if_then_else (lt (minus (match_dup 0) (pc)) | |
5392 + (const_int MIN_SHORT_BRANCH_OFFSET)) | |
5393 + (const_int LONG_CBRANCH_LENGTH) | |
5394 + (if_then_else (gt (minus (match_dup 0) (pc)) | |
5395 + (const_int MAX_SHORT_BRANCH_OFFSET)) | |
5396 + (const_int LONG_CBRANCH_LENGTH) | |
5397 + (const_int SHORT_CBRANCH_LENGTH))) | |
5398 + ] (const_int DEFAULT_INSN_LENGTH))) | |
5399 + | |
5400 + | |
5401 +;; | |
5402 +;; The default attributes for 'asm' statements. | |
5403 +;; The default length is the longest possible single 6809 instruction, | |
5404 +;; which is 5 bytes. GCC will automatically multiply this by the | |
5405 +;; number of real insns contained in an asm statement. | |
5406 +;; | |
5407 +(define_asm_attributes | |
5408 + [(set_attr "length" "5") | |
5409 + (set_attr "type" "unknown")]) | |
5410 + | |
5411 +;; | |
5412 +;; An attribute for the number of cycles that it takes an instruction | |
5413 +;; to execute. | |
5414 +;; | |
5415 +(define_attr "cycles" "" (const_int DEFAULT_INSN_CYCLES)) | |
5416 + | |
5417 + | |
5418 +;;-------------------------------------------------------------------- | |
5419 +;;- Instruction patterns. When multiple patterns apply, | |
5420 +;;- the first one in the file is chosen. | |
5421 +;;- | |
5422 +;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
5423 +;;- | |
5424 +;;- Note: NOTICE_UPDATE_CC in m6809.h handles condition code updates | |
5425 +;;- for most instructions. | |
5426 +;;-------------------------------------------------------------------- | |
5427 + | |
5428 +;;-------------------------------------------------------------------- | |
5429 +;;- Test | |
5430 +;;-------------------------------------------------------------------- | |
5431 + | |
5432 +;; cmpx is 3 bytes, not 4 | |
5433 +(define_insn "*tsthi_x" | |
5434 + [(set (cc0) (match_operand:HI 0 "register_operand_x" "v"))] | |
5435 + "" | |
5436 + "cmpx\t#0" | |
5437 + [(set_attr "length" "3")]) | |
5438 + | |
5439 +;; subd #0 is 3 bytes, better than cmpd #0 which is 4 bytes | |
5440 +(define_insn "*tsthi_d" | |
5441 + [(set (cc0) (match_operand:HI 0 "register_operand_d" "d"))] | |
5442 + "" | |
5443 + "subd\t#0" | |
5444 + [(set_attr "length" "3")]) | |
5445 + | |
5446 +(define_insn "*tsthi" | |
5447 + [(set (cc0) (match_operand:HI 0 "register_operand" "a"))] | |
5448 + "" | |
5449 + "cmp%0\t#0" | |
5450 + [(set_attr "length" "4")]) | |
5451 + | |
5452 +(define_insn "*bitqi3" | |
5453 + [(set (cc0) | |
5454 + (and:QI (match_operand:QI 0 "register_operand" "%q") | |
5455 + (match_operand:QI 1 "general_operand" "mi")))] | |
5456 + "" | |
5457 + "bit%0\t%1" | |
5458 + [(set_attr "length" "3")]) | |
5459 + | |
5460 + | |
5461 +(define_insn "tstqi" | |
5462 + [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" "q,mt"))] | |
5463 + "" | |
5464 + "@ | |
5465 + tst%0 | |
5466 + tst\t%0" | |
5467 + [(set_attr "length" "1,3")]) | |
5468 + | |
5469 +;;-------------------------------------------------------------------- | |
5470 +;;- Compare instructions | |
5471 +;;-------------------------------------------------------------------- | |
5472 + | |
5473 +;; - cmphi for register to memory or register compares | |
5474 +(define_insn "cmphi" | |
5475 + [(set (cc0) | |
5476 + (compare | |
5477 + (match_operand:HI 0 "general_operand" "da, mi, ??Ud") | |
5478 + (match_operand:HI 1 "general_operand" "mi, da, dU")))] | |
5479 + "" | |
5480 +{ | |
5481 + if ((REG_P (operands[0])) && (REG_P (operands[1]))) { | |
5482 + output_asm_insn ("pshs\t%1\t;cmphi: R:%1 with R:%0", operands); | |
5483 + return "cmp%0\t,s++\t;cmphi:"; | |
5484 + } | |
5485 + if (GET_CODE (operands[0]) == REG) | |
5486 + return "cmp%0\t%1\t;cmphi:"; | |
5487 + else { | |
5488 + cc_status.flags |= CC_REVERSED; | |
5489 + return "cmp%1\t%0\t;cmphi:(R)"; | |
5490 + } | |
5491 +} | |
5492 + [(set_attr "length" "5,5,7")]) | |
5493 + | |
5494 + | |
5495 +(define_insn "cmpqi" | |
5496 + [(set (cc0) | |
5497 + (compare (match_operand:QI 0 "whole_general_operand" "q,q, q,O,mt,K") | |
5498 + (match_operand:QI 1 "whole_general_operand" "O,mt,K,q,q, q")))] | |
5499 + "" | |
5500 +{ | |
5501 + if (REG_P (operands[0]) && !M_REG_P (operands[0])) | |
5502 + { | |
5503 + if (operands[1] == const0_rtx) | |
5504 + return "tst%0\t;cmpqi:(ZERO)"; | |
5505 + else | |
5506 + return "cmp%0\t%1\t;cmpqi:"; | |
5507 + } | |
5508 + else | |
5509 + { | |
5510 + cc_status.flags |= CC_REVERSED; | |
5511 + | |
5512 + if (operands[0] == const0_rtx) | |
5513 + return "tst%1\t;cmpqi:(RZERO)"; | |
5514 + else | |
5515 + return "cmp%1\t%0\t;cmpqi:(R)"; | |
5516 + } | |
5517 +} | |
5518 + [(set_attr "length" "1,3,2,1,3,2")]) | |
5519 + | |
5520 + | |
5521 +;;-------------------------------------------------------------------- | |
5522 +;;- Compare/branch pattern | |
5523 +;;-------------------------------------------------------------------- | |
5524 + | |
5525 +(define_expand "cbranchhi4" | |
5526 + [(set (cc0) | |
5527 + (compare | |
5528 + (match_operand:HI 1 "general_operand" "da, mi, ??Ud") | |
5529 + (match_operand:HI 2 "general_operand" "mi, da, dU"))) | |
5530 + (set (pc) | |
5531 + (if_then_else | |
5532 + (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) | |
5533 + (label_ref (match_operand 3 "" "")) | |
5534 + (pc)))] | |
5535 + "" | |
5536 + "" | |
5537 +) | |
5538 + | |
5539 +(define_expand "cbranchqi4" | |
5540 + [(set (cc0) | |
5541 + (compare | |
5542 + (match_operand:QI 1 "whole_general_operand" "q,q, q,O,mt,K") | |
5543 + (match_operand:QI 2 "whole_general_operand" "O,mt,K,q,q, q"))) | |
5544 + (set (pc) | |
5545 + (if_then_else | |
5546 + (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)]) | |
5547 + (label_ref (match_operand 3 "" "")) | |
5548 + (pc)))] | |
5549 + "" | |
5550 + "" | |
5551 +) | |
5552 + | |
5553 +;;-------------------------------------------------------------------- | |
5554 +;;- Move | |
5555 +;;-------------------------------------------------------------------- | |
5556 + | |
5557 +; this looks good (obviously not finished) but I still see 'movsi' | |
5558 +; places in udivsi3 where it's broken | |
5559 +; (define_insn "pushsi1" | |
5560 +; [(set (mem:SI (pre_dec (reg:HI HARD_S_REGNUM))) | |
5561 +; (match_operand:SI 0 "general_operand" "o")) | |
5562 +; (set (reg:HI HARD_S_REGNUM) | |
5563 +; (plus:HI (reg:HI HARD_S_REGNUM) (const_int -4))) ] | |
5564 +; "" | |
5565 +; "; pushsi %0" | |
5566 +; [(set_attr "length" "12")]) | |
5567 +; | |
5568 +; (define_insn "popsi1" | |
5569 +; [(set (match_operand:SI 0 "general_operand" "=o") | |
5570 +; (mem:SI (post_inc (reg:HI HARD_S_REGNUM)))) | |
5571 +; (set (reg:HI HARD_S_REGNUM) | |
5572 +; (plus:HI (reg:HI HARD_S_REGNUM) (const_int 4))) ] | |
5573 +; "" | |
5574 +; "; popsi %0" | |
5575 +; [(set_attr "length" "12")]) | |
5576 + | |
5577 +; (define_insn "movsi" | |
5578 +; [(set (match_operand:SI 0 "nonimmediate_operand" "=o") | |
5579 +; (match_operand:SI 1 "general_operand" " oi"))] | |
5580 +; "" | |
5581 +; "; movsi %0 <- %1" | |
5582 +; [(set_attr "length" "1")]) | |
5583 + | |
5584 +; this doesn't work | |
5585 +; (define_expand "movsi" | |
5586 +; [(parallel [ | |
5587 +; (set (match_operand:SI 0 "nonimmediate_operand" "") | |
5588 +; (match_operand:SI 1 "general_operand" "")) | |
5589 +; (clobber (match_scratch:HI 2 ""))])] | |
5590 +; "" | |
5591 +; { | |
5592 +; rtx insn; | |
5593 +; if (STACK_PUSH_P (operands[0]) || STACK_POP_P (operands[1])) | |
5594 +; { | |
5595 +; REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, stack_pointer_rtx, REG_NOTES (insn)); | |
5596 +; } | |
5597 +; insn = emit_move_multi_word (SImode, operands[0], operands[1]); | |
5598 +; DONE; | |
5599 +; }) | |
5600 + | |
5601 + | |
5602 +(define_expand "movhi" | |
5603 + [(set (match_operand:HI 0 "nonimmediate_operand" "") | |
5604 + (match_operand:HI 1 "general_operand" ""))] | |
5605 + "" | |
5606 +{ | |
5607 + /* One of the ops has to be in a register prior to reload */ | |
5608 + if (!register_operand (operand0, HImode) && | |
5609 + !register_operand (operand1, HImode)) | |
5610 + operands[1] = copy_to_mode_reg (HImode, operand1); | |
5611 +}) | |
5612 + | |
5613 +;;; Try a splitter to handle failure cases where we try to move | |
5614 +;;; an immediate constant (zero usually) directly to memory. | |
5615 +;;; This absolutely requires an intermediate register. | |
5616 +(define_split | |
5617 + [(set (match_operand:HI 0 "memory_operand" "") | |
5618 + (match_operand:HI 1 "immediate_operand" "")) | |
5619 + (clobber (match_operand:HI 2 "register_operand" ""))] | |
5620 + "" | |
5621 + [(set (match_dup 2) (match_dup 1)) | |
5622 + (set (match_dup 0) (match_dup 2))] | |
5623 + "") | |
5624 + | |
5625 + | |
5626 +;;; This would be a nice method for loading from a word array, | |
5627 +;;; but it is never generated because the combiner cannot merge | |
5628 +;;; more than 3 instructions (there are four here). This is | |
5629 +;;; perhaps better done via a peephole. | |
5630 +(define_insn "*movhi_array_load" | |
5631 + [(set (match_operand:HI 0 "nonimmediate_operand" "=da") | |
5632 + (mem:HI (plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%B")) (const_int 1)) | |
5633 + (match_operand:HI 2 "immediate_operand" "i")))) | |
5634 + (clobber (match_scratch:HI 3 "=X"))] | |
5635 + "" | |
5636 + "ldx\t%2\;abx\;abx\;ld%0\t,x" | |
5637 + [(set_attr "length" "7")]) | |
5638 + | |
5639 + | |
5640 +;;; Optimize the move of a byte to the stack using the pshs instruction | |
5641 +;;; instead of a store with pre-increment. | |
5642 +(define_insn "movhi_push" | |
5643 + [(set (match_operand:HI 0 "push_operand" "=m") | |
5644 + (match_operand:HI 1 "register_operand" "U"))] | |
5645 + "" | |
5646 + "pshs\t%1" | |
5647 + [(set_attr "length" "2")]) | |
5648 + | |
5649 + | |
5650 +(define_insn "*movhi_pic_symbolref" | |
5651 + [(set (match_operand:HI 0 "register_operand" "=a") | |
5652 + (match_operand:HI 1 "symbolic_operand" ""))] | |
5653 + "flag_pic" | |
5654 + "lea%0\t%c1,pcr" | |
5655 + [(set_attr "length" "4")]) | |
5656 + | |
5657 + | |
5658 +(define_insn "*movhi_1" | |
5659 + [(set (match_operand:HI 0 "nonimmediate_operand" "=a,d,a,ad,tmu") | |
5660 + (match_operand:HI 1 "general_operand" " a,a,d,tmiu,ad"))] | |
5661 + "" | |
5662 + "@ | |
5663 + lea%0\t,%1 | |
5664 + tfr\t%1,%0 | |
5665 + tfr\t%1,%0 | |
5666 + ld%0\t%1 | |
5667 + st%1\t%0" | |
5668 + [(set_attr "length" "2,2,2,*,*")]) | |
5669 + | |
5670 + | |
5671 +;;; Generated by the combiner to merge an address calculation with | |
5672 +;;; a byte load. We can use the 'abx' instruction here. | |
5673 +(define_insn "*movqi_array_load" | |
5674 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q") | |
5675 + (mem:QI (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%B")) | |
5676 + (match_operand:HI 2 "immediate_operand" "i")))) | |
5677 + (clobber (match_scratch:HI 3 "=X"))] | |
5678 + "" | |
5679 + "ldx\t%2\;abx\;ld%0\t,x" | |
5680 + [(set_attr "length" "6")]) | |
5681 + | |
5682 + | |
5683 +;;; Optimize the move of a byte to the stack using the pshs instruction | |
5684 +;;; instead of a store with pre-increment. | |
5685 +(define_insn "movqi_push" | |
5686 + [(set (match_operand:QI 0 "push_operand" "=m") | |
5687 + (match_operand:QI 1 "register_operand" " q"))] | |
5688 + "" | |
5689 + "pshs\t%1" | |
5690 + [(set_attr "length" "2")]) | |
5691 + | |
5692 + | |
5693 +;;; Optimize the move of a byte from the stack using the puls instruction | |
5694 +;;; instead of a store with post-decrement. | |
5695 +(define_insn "movqi_pop" | |
5696 + [(set (match_operand:QI 0 "register_operand" "=q") | |
5697 + (match_operand:QI 1 "pop_operand" "m"))] | |
5698 + "" | |
5699 + "puls\t%0" | |
5700 + [(set_attr "length" "2")]) | |
5701 + | |
5702 + | |
5703 +;;- load low byte of 16-bit data into 8-bit register/memory | |
5704 +(define_insn "*mov_lsb" | |
5705 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q,q,m,!q") | |
5706 + (subreg:QI (match_operand:HI 1 "general_operand" "d,m,a,d, U") 1))] | |
5707 + "" | |
5708 + "@ | |
5709 + \t;movlsbqihi: D->B | |
5710 + ld%0\t%L1\t;movlsbqihi: msb:%1 -> R:%0 | |
5711 + tfr\t%1,d\t;movlsbqihi: R:%1 -> R:%0 | |
5712 + stb\t%0\t;movlsbqihi: R:%1 -> %0 | |
5713 + pshs\t%1\t;movlsbqihi: R:%1 -> R:%0\;leas\t1,s\;puls\t%0" | |
5714 + [(set_attr "length" "0,*,2,*,6")]) | |
5715 + | |
5716 + | |
5717 +;;- load high byte of 16-bit data into 8-bit register/memory | |
5718 +(define_insn "*mov_msb" | |
5719 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q,q,q,m,!q") | |
5720 + (subreg:QI (match_operand:HI 1 "general_operand" "d,O,a,m,d, U") 0))] | |
5721 + "" | |
5722 + "@ | |
5723 + tfr\ta,b\t;movmsbqihi: D->B | |
5724 + clr%0\t\t;movmsbqihi: ZERO -> R:%0 | |
5725 + tfr\t%1,d\t;movmsbqihi: R:%1 -> R:%0\;tfr\ta,b | |
5726 + ld%0\t%L1\t;movmsbqihi: lsb:%1 -> R:%0 | |
5727 + sta\t%0\t;movmsbqihi: R:%1 -> %0 | |
5728 + pshs\t%1\t;movmsbqihi: R:%1 -> R:%0\;puls\t%0\;leas\t1,s" | |
5729 + [(set_attr "length" "2,1,4,*,*,6")]) | |
5730 + | |
5731 + | |
5732 +(define_insn "*movqi_boolean" | |
5733 + [(set (reg:QI HARD_Z_REGNUM) | |
5734 + (match_operand:QI 0 "general_operand" "q,O,i,m"))] | |
5735 + "" | |
5736 + "@ | |
5737 + tst%0 | |
5738 + andcc\t#~4 | |
5739 + orcc\t#4 | |
5740 + tst\t%0") | |
5741 + | |
5742 + | |
5743 +(define_insn "movqi" | |
5744 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q,tm,q,tm,q,z") | |
5745 + (match_operand:QI 1 "general_operand" " q,O,O,tmi,q,z,q"))] | |
5746 + "" | |
5747 + "@ | |
5748 + tfr\t%1,%0 | |
5749 + clr%0 | |
5750 + clr\t%0 | |
5751 + ld%0\t%1 | |
5752 + st%1\t%0 | |
5753 + tfr\tcc,%0\;and%0\t#4 | |
5754 + tst%0" | |
5755 + [(set_attr "length" "2,1,3,*,*,4,1")]) | |
5756 + | |
5757 + | |
5758 +;;-------------------------------------------------------------------- | |
5759 +;;- Swap registers | |
5760 +;;-------------------------------------------------------------------- | |
5761 + | |
5762 +; Note: 8-bit swap is never needed so it is not defined. | |
5763 + | |
5764 +(define_insn "swaphi" | |
5765 + [(set (match_operand:HI 0 "register_operand" "+r") | |
5766 + (match_operand:HI 1 "register_operand" "+r")) | |
5767 + (set (match_dup 1) (match_dup 0))] | |
5768 + "" | |
5769 + "exg\t%1,%0" | |
5770 + [(set_attr "length" "2") | |
5771 + (set (attr "cycles") (const_int EXG_CYCLES))]) | |
5772 + | |
5773 + | |
5774 +(define_insn "bswaphi2" | |
5775 + [(set (match_operand:HI 0 "register_operand" "=d") | |
5776 + (bswap:HI (match_operand:HI 1 "register_operand" "0")))] | |
5777 + "" | |
5778 + "exg\ta,b" | |
5779 + [(set_attr "length" "2")]) | |
5780 + | |
5781 + | |
5782 +;;-------------------------------------------------------------------- | |
5783 +;;- Extension and truncation insns. | |
5784 +;;-------------------------------------------------------------------- | |
5785 + | |
5786 +(define_insn "extendqihi2" | |
5787 + [(set (match_operand:HI 0 "register_operand" "=d") | |
5788 + (sign_extend:HI (match_operand:QI 1 "general_operand" "B")))] | |
5789 + "" | |
5790 + "sex\t\t;extendqihi2: R:%1 -> R:%0" | |
5791 + [(set_attr "length" "1")]) | |
5792 + | |
5793 + | |
5794 +(define_insn "zero_extendqihi2" | |
5795 + [(set (match_operand:HI 0 "register_operand" "=d") | |
5796 + (zero_extend:HI (match_operand:QI 1 "general_operand" "B")))] | |
5797 + "" | |
5798 + "clra\t\t;zero_extendqihi: R:%1 -> R:%0" | |
5799 + [(set_attr "length" "1")]) | |
5800 + | |
5801 + | |
5802 +;;-------------------------------------------------------------------- | |
5803 +;;- All kinds of add instructions. | |
5804 +;;-------------------------------------------------------------------- | |
5805 + | |
5806 + | |
5807 +;; | |
5808 +;; gcc's automatic version of addsi3 doesn't know about adcb,adca | |
5809 +;; so it is MUCH less efficient. Define this one ourselves. | |
5810 +;; | |
5811 +;; TODO - can't always get 'd' for the clobber... allow other registers | |
5812 +;; as well and use exg d,R ... exg R,d around the code sequence to | |
5813 +;; use others, at a price. Also consider libcall for this when | |
5814 +;; optimizing for size. | |
5815 +;; | |
5816 +(define_insn "addsi3" | |
5817 + [(set (match_operand:SI 0 "nonimmediate_operand" "=o") | |
5818 + (plus:SI (match_operand:SI 1 "general_operand" "%o") | |
5819 + (match_operand:SI 2 "general_operand" " oi"))) | |
5820 + (clobber (match_scratch:HI 3 "=d"))] | |
5821 + "" | |
5822 +{ | |
5823 + m6809_output_addsi3 (PLUS, operands); | |
5824 + return ""; | |
5825 +} | |
5826 + [(set_attr "length" "21")]) | |
5827 + | |
5828 + | |
5829 +; Increment of a 16-bit MEM by 1 can be done without a register. | |
5830 +(define_insn "*addhi_mem_1" | |
5831 + [(set (match_operand:HI 0 "memory_operand" "=m") | |
5832 + (plus:HI (match_operand:HI 1 "memory_operand" "0") (const_int 1)))] | |
5833 + "GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF" | |
5834 +{ | |
5835 + rtx xoperands[2]; | |
5836 + | |
5837 + xoperands[0] = operands[0]; | |
5838 + xoperands[1] = adjust_address (operands[0], QImode, 1); | |
5839 + | |
5840 + output_asm_insn ("inc\t%1", xoperands); | |
5841 + output_asm_insn ("bne\t__IL%=", xoperands); | |
5842 + output_asm_insn ("inc\t%0\;__IL%=:", xoperands); | |
5843 + return ""; | |
5844 +} | |
5845 + [(set_attr "length" "7")]) | |
5846 + | |
5847 + | |
5848 +; Decrement of a 16-bit MEM by 1 can be done without a register. | |
5849 +(define_insn "*addhi_mem_minus1" | |
5850 + [(set (match_operand:HI 0 "memory_operand" "=m") | |
5851 + (plus:HI (match_operand:HI 1 "memory_operand" "0") (const_int -1)))] | |
5852 + "GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF" | |
5853 +{ | |
5854 + rtx xoperands[2]; | |
5855 + | |
5856 + xoperands[0] = operands[0]; | |
5857 + xoperands[1] = adjust_address (operands[0], QImode, 1); | |
5858 + | |
5859 + output_asm_insn ("tst\t%1", xoperands); | |
5860 + output_asm_insn ("bne\t__IL%=", xoperands); | |
5861 + output_asm_insn ("dec\t%0", xoperands); | |
5862 + output_asm_insn ("__IL%=:", xoperands); | |
5863 + output_asm_insn ("dec\t%1", xoperands); | |
5864 + return ""; | |
5865 +} | |
5866 + [(set_attr "length" "7")]) | |
5867 + | |
5868 + | |
5869 +; Allow the addition of an 8-bit quantity to a 16-bit quantity | |
5870 +; using the LEAX B,Y addressing mode, where X and Y are both | |
5871 +; index registers. This will only get generated via the peephole | |
5872 +; which removes a sign extension. | |
5873 +(define_insn "*addhi_b" | |
5874 + [(set (match_operand:HI 0 "index_register_operand" "=a") | |
5875 + (plus:HI(match_operand:HI 1 "index_register_operand" "%a") | |
5876 + (match_operand:QI 2 "register_operand" "q") | |
5877 + ))] | |
5878 + "" | |
5879 + "lea%0\t%2,%1\t;addhi_b: R:%0 = R:%2 + R:%1" | |
5880 + [(set_attr "length" "*")]) | |
5881 + | |
5882 + | |
5883 +; Splitter for addhi pattern #5 below | |
5884 +(define_split | |
5885 + [(set (match_operand:HI 0 "index_register_operand" "") | |
5886 + (plus:HI (match_dup 0) (match_operand:HI 1 "memory_operand" "")))] | |
5887 + "reload_completed" | |
5888 + [ | |
5889 + (parallel [(set (match_dup 0) (reg:HI HARD_D_REGNUM)) | |
5890 + (set (reg:HI HARD_D_REGNUM) (match_dup 0))]) | |
5891 + (set (reg:HI HARD_D_REGNUM) | |
5892 + (plus:HI (reg:HI HARD_D_REGNUM) (match_dup 1))) | |
5893 + (parallel [(set (match_dup 0) (reg:HI HARD_D_REGNUM)) | |
5894 + (set (reg:HI HARD_D_REGNUM) (match_dup 0))]) | |
5895 + ] | |
5896 +{ | |
5897 +}) | |
5898 + | |
5899 + | |
5900 +; Splitter for addhi pattern #7 below | |
5901 +(define_split | |
5902 + [(set (match_operand:HI 0 "index_register_operand" "") | |
5903 + (plus:HI (match_dup 0) (match_operand:HI 1 "index_register_operand" "")))] | |
5904 + "reload_completed" | |
5905 + [ | |
5906 + (parallel [(set (match_dup 1) (reg:HI HARD_D_REGNUM)) | |
5907 + (set (reg:HI HARD_D_REGNUM) (match_dup 1))]) | |
5908 + (set (match_dup 0) | |
5909 + (plus:HI (reg:HI HARD_D_REGNUM) (match_dup 0))) | |
5910 + (parallel [(set (match_dup 1) (reg:HI HARD_D_REGNUM)) | |
5911 + (set (reg:HI HARD_D_REGNUM) (match_dup 1))]) | |
5912 + ] | |
5913 +{ | |
5914 +}) | |
5915 + | |
5916 + | |
5917 +; TODO - this is ugly. During RTL generation, we don't know what registers | |
5918 +; are available, so the multiple-insn sequences can only be solved | |
5919 +; via 'define_split's during matching. See andhi3 for an example. | |
5920 +; Keep the constraints with ? modifiers to help reload pick the right | |
5921 +; registers. | |
5922 +; | |
5923 +; The forms are: | |
5924 +; 1. D += D, expand this into a shift instead. (rtx costs should be corrected | |
5925 +; to avoid this even happening...) | |
5926 +; 2. D += U, require U to be pushed to memory. (Lots of patterns do this | |
5927 +; now, is this a better way?) | |
5928 +; 3. Best choice: 'addd' | |
5929 +; 4. Next best choice: 'lea' | |
5930 +; 5. Hybrid of 3 and 4 | |
5931 +; 6. Same as 4, not bad | |
5932 +; 7. BAD, no D register at all | |
5933 +; 8. 'lea', as good as 4. | |
5934 +(define_insn "addhi3" | |
5935 + [(set (match_operand:HI 0 "nonimmediate_operand" "=d, d, d, a,?a, a,???T,a") | |
5936 + (plus:HI(match_operand:HI 1 "add_general_operand" "%0, 0, 0, d, 0, a, 0, a") | |
5937 + (match_operand:HI 2 "general_operand" " 0, !U, mi, a, m, d, T, i") | |
5938 + ))] | |
5939 + "" | |
5940 + "@ | |
5941 + lslb\t\t;addhi: R:%0 += R:%2\;rola\t\t;also R:%0 *= 2 | |
5942 + pshs\t%2\t;addhi: R:%0 += R:%2\;add%0\t,s++ | |
5943 + add%0\t%2 | |
5944 + lea%0\t%1,%2 | |
5945 + # | |
5946 + lea%0\t%2,%1 | |
5947 + # | |
5948 + lea%0\t%a2,%1" | |
5949 + [(set_attr "length" "2,6,*,*,7,*,7,*")]) | |
5950 + | |
5951 + | |
5952 +(define_insn "addqi3_carry" | |
5953 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q") | |
5954 + (unspec:QI [ | |
5955 + (match_operand:QI 1 "whole_general_operand" "%0") | |
5956 + (match_operand:QI 2 "whole_general_operand" "tmi")] UNSPEC_ADD_CARRY))] | |
5957 + "" | |
5958 + "adc%0\t%2\t;addqi_carry: R:%0 += %2" | |
5959 + [(set_attr "length" "*")]) | |
5960 + | |
5961 + | |
5962 +; TODO: specifying 'A' for the first constraint, to force into the A register | |
5963 +; is not working because of the way registers are currently set up. This will | |
5964 +; take some work to get right. Thus the second alternative as a backup. | |
5965 +(define_insn "addqi3_decimal" | |
5966 + [(set (match_operand:QI 0 "nonimmediate_operand" "=A,?q") | |
5967 + (unspec:QI [ | |
5968 + (match_operand:QI 1 "general_operand" "%0,0") | |
5969 + (match_operand:QI 2 "general_operand" "tmi,tmi")] UNSPEC_ADD_DECIMAL))] | |
5970 + "" | |
5971 + "@ | |
5972 + adda\t%2\;daa | |
5973 + tfr\t%0,a\;adda\t%2\;daa\;tfr\ta,%0" | |
5974 + [(set_attr "length" "5,9")]) | |
5975 + | |
5976 + | |
5977 +(define_insn "addqi3" | |
5978 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q,q,tm,tm,q") | |
5979 + (plus:QI (match_operand:QI 1 "whole_general_operand" "%0,0,0,0,0,0") | |
5980 + (match_operand:QI 2 "whole_general_operand" " 0,I,N,I,N,tmi")))] | |
5981 + "" | |
5982 + "@ | |
5983 + asl%0\t\t;addqi: R:%0 = R:%0 + R:%0 | |
5984 + inc%0 | |
5985 + dec%0 | |
5986 + inc\t%0 | |
5987 + dec\t%0 | |
5988 + add%0\t%2" | |
5989 + [(set_attr "length" "1,1,1,3,3,*")]) | |
5990 + | |
5991 + | |
5992 +;;-------------------------------------------------------------------- | |
5993 +;;- Subtract instructions. | |
5994 +;;-------------------------------------------------------------------- | |
5995 + | |
5996 +(define_insn "subsi3" | |
5997 + [(set (match_operand:SI 0 "nonimmediate_operand" "=o") | |
5998 + (minus:SI (match_operand:SI 1 "general_operand" " o") | |
5999 + (match_operand:SI 2 "general_operand" " oi"))) | |
6000 + (clobber (match_scratch:HI 3 "=d"))] | |
6001 + "" | |
6002 +{ | |
6003 + m6809_output_addsi3 (MINUS, operands); | |
6004 + return ""; | |
6005 +} | |
6006 + [(set_attr "length" "21")]) | |
6007 + | |
6008 + | |
6009 +(define_insn "subhi3" | |
6010 + [(set (match_operand:HI 0 "register_operand" "=d, d, a") | |
6011 + (minus:HI (match_operand:HI 1 "register_operand" "0, 0, 0") | |
6012 + (match_operand:HI 2 "general_operand" "mi, ?U,n")))] | |
6013 + "" | |
6014 + "@ | |
6015 + sub%0\t%2\t;subhi: R:%0 -= %2 | |
6016 + pshs\t%2\t;subhi: R:%0 -= R:%2\;sub%0\t,s++ | |
6017 + lea%0\t%n2,%1\t;subhi: R:%0 = R:%1 + %n2" | |
6018 + [(set_attr "length" "*,5,3")]) | |
6019 + | |
6020 + | |
6021 +(define_insn "subqi3_carry" | |
6022 + [(set (match_operand:QI 0 "register_operand" "=q") | |
6023 + (unspec:QI [ | |
6024 + (match_operand:QI 1 "whole_general_operand" "%0") | |
6025 + (match_operand:QI 2 "whole_general_operand" "tmi")] UNSPEC_SUB_CARRY))] | |
6026 + "" | |
6027 + "sbc%0\t%2\t;subqi_carry: R:%0 += %2" | |
6028 + [(set_attr "length" "*")]) | |
6029 + | |
6030 + | |
6031 +(define_insn "subqi3" | |
6032 + [(set (match_operand:QI 0 "register_operand" "=q, q, !q, !q, q") | |
6033 + (minus:QI (match_operand:QI 1 "whole_register_operand" "0, 0, I, tmn, 0") | |
6034 + (match_operand:QI 2 "whole_general_operand" "I, mi, 0, 0, t")))] | |
6035 + "" | |
6036 + "@ | |
6037 + dec%0 | |
6038 + sub%0\t%2 | |
6039 + dec%0\;neg%0 | |
6040 + sub%0\t%1\;neg%0 | |
6041 + sub%0\t%2" | |
6042 + [(set_attr "length" "1,3,2,4,3")]) | |
6043 + | |
6044 + | |
6045 +;;-------------------------------------------------------------------- | |
6046 +;;- Multiply instructions. | |
6047 +;;-------------------------------------------------------------------- | |
6048 + | |
6049 +; TODO - merge these two instructions, using 'extend_operator' to match | |
6050 +; either signed or zero extension. Everything else is the same. | |
6051 +(define_insn "mulqihi3" | |
6052 + [(set (match_operand:HI 0 "register_operand" "=d") | |
6053 + (mult:HI (sign_extend:HI (match_operand:QI 1 "general_operand" "%q")) | |
6054 + (match_operand:QI 2 "general_operand" "tmK")))] | |
6055 + "" | |
6056 + "lda\t%2\t;mulqihi3\;mul" | |
6057 + [(set_attr "length" "3")]) | |
6058 + | |
6059 + | |
6060 +(define_insn "umulqihi3" | |
6061 + [(set (match_operand:HI 0 "register_operand" "=d") | |
6062 + (mult:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "%q")) | |
6063 + (match_operand:QI 2 "general_operand" "tmK")))] | |
6064 + "" | |
6065 + "lda\t%2\t;umulqihi3\;mul" | |
6066 + [(set_attr "length" "3")]) | |
6067 + | |
6068 + | |
6069 +; Expand a 16x16 multiplication into either a libcall or a shift. | |
6070 +; If the second operand is a small constant, use the above form. | |
6071 +; Otherwise, do a libcall. | |
6072 +(define_expand "mulhi3" | |
6073 + [(set (match_operand:HI 0 "nonimmediate_operand" "") | |
6074 + (mult:HI (match_operand:HI 1 "general_operand" "") | |
6075 + (match_operand:HI 2 "nonmemory_operand" "")))] | |
6076 + "" | |
6077 +{ | |
6078 + emit_libcall_insns (HImode, "mulhi3", operands, 2); | |
6079 + DONE; | |
6080 +}) | |
6081 + | |
6082 + | |
6083 +;;-------------------------------------------------------------------- | |
6084 +;;- Divide instructions. | |
6085 +;;-------------------------------------------------------------------- | |
6086 + | |
6087 +(define_expand "divhi3" | |
6088 + [(set (match_operand:HI 0 "register_operand" "") | |
6089 + (div:HI (match_operand:HI 1 "register_operand" "") | |
6090 + (match_operand:HI 2 "register_operand" "")))] | |
6091 + "" | |
6092 +{ | |
6093 + emit_libcall_insns (HImode, "divhi3", operands, 2); | |
6094 + DONE; | |
6095 +}) | |
6096 + | |
6097 + | |
6098 +(define_expand "divqi3" | |
6099 + [(set (match_operand:QI 0 "register_operand" "") | |
6100 + (div:QI (match_operand:QI 1 "register_operand" "") | |
6101 + (match_operand:QI 2 "register_operand" "")))] | |
6102 + "" | |
6103 +{ | |
6104 + emit_libcall_insns (QImode, "divqi3", operands, 2); | |
6105 + DONE; | |
6106 +}) | |
6107 + | |
6108 + | |
6109 +(define_expand "udivhi3" | |
6110 + [(set (match_operand:HI 0 "register_operand" "") | |
6111 + (udiv:HI (match_operand:HI 1 "register_operand" "") | |
6112 + (match_operand:HI 2 "register_operand" "")))] | |
6113 + "" | |
6114 +{ | |
6115 + emit_libcall_insns (HImode, "udivhi3", operands, 2); | |
6116 + DONE; | |
6117 +}) | |
6118 + | |
6119 + | |
6120 +;;-------------------------------------------------------------------- | |
6121 +;;- mod | |
6122 +;;-------------------------------------------------------------------- | |
6123 + | |
6124 +(define_expand "modhi3" | |
6125 + [(set (match_operand:HI 0 "register_operand" "") | |
6126 + (mod:HI (match_operand:HI 1 "register_operand" "") | |
6127 + (match_operand:HI 2 "register_operand" "")))] | |
6128 + "" | |
6129 +{ | |
6130 + emit_libcall_insns (HImode, "modhi3", operands, 2); | |
6131 + DONE; | |
6132 +}) | |
6133 + | |
6134 + | |
6135 +(define_expand "modqi3" | |
6136 + [(set (match_operand:QI 0 "register_operand" "") | |
6137 + (mod:QI (match_operand:QI 1 "register_operand" "") | |
6138 + (match_operand:QI 2 "register_operand" "")))] | |
6139 + "" | |
6140 +{ | |
6141 + emit_libcall_insns (QImode, "modqi3", operands, 2); | |
6142 + DONE; | |
6143 +}) | |
6144 + | |
6145 + | |
6146 +(define_expand "umodhi3" | |
6147 + [(set (match_operand:HI 0 "register_operand" "") | |
6148 + (umod:HI (match_operand:HI 1 "register_operand" "") | |
6149 + (match_operand:HI 2 "register_operand" "")))] | |
6150 + "" | |
6151 +{ | |
6152 + emit_libcall_insns (HImode, "umodhi3", operands, 2); | |
6153 + DONE; | |
6154 +}) | |
6155 + | |
6156 + | |
6157 + | |
6158 +;;-------------------------------------------------------------------- | |
6159 +;;- and, or, xor common patterns | |
6160 +;;-------------------------------------------------------------------- | |
6161 + | |
6162 +; Split a bitwise HImode into two QImode instructions, with one of | |
6163 +; the sources in a pushable register. The register is pushed onto | |
6164 +; the stack and memory pop operands (,s+) are used in the QI forms. | |
6165 +(define_split | |
6166 + [(set (match_operand:HI 0 "register_operand" "") | |
6167 + (match_operator:HI 3 "logical_bit_operator" | |
6168 + [(match_operand:HI 1 "register_operand" "") | |
6169 + (match_operand:HI 2 "register_operand" "")]))] | |
6170 + "reload_completed" | |
6171 + [(set (mem:HI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (match_dup 2)) | |
6172 + (set (reg:QI HARD_A_REGNUM) (match_op_dup:QI 3 | |
6173 + [(reg:QI HARD_A_REGNUM) | |
6174 + (mem:QI (post_inc:QI (reg:HI HARD_S_REGNUM)))])) | |
6175 + (set (reg:QI HARD_D_REGNUM) (match_op_dup:QI 3 | |
6176 + [(reg:QI HARD_D_REGNUM) | |
6177 + (mem:QI (post_inc:QI (reg:HI HARD_S_REGNUM)))])) | |
6178 + (use (reg:QI HARD_A_REGNUM))] | |
6179 +{ | |
6180 +}) | |
6181 + | |
6182 +; Split a bitwise HImode into two QImode instructions, with one | |
6183 +; of the sources being a (MEM (MEM (...)); i.e. an indirect memory | |
6184 +; reference. This requires dereferencing the pointer into a | |
6185 +; temporary register (X), which must be saved/restored around the | |
6186 +; compute instructions. | |
6187 +(define_split | |
6188 + [(set (match_operand:HI 0 "register_operand" "") | |
6189 + (match_operator:HI 3 "logical_bit_operator" | |
6190 + [(match_operand:HI 1 "register_operand" "") | |
6191 + (mem:HI (match_operand:HI 2 "memory_operand" ""))]))] | |
6192 + "reload_completed" | |
6193 + [ | |
6194 + (set (mem:HI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (match_dup 4)) | |
6195 + (set (match_dup 4) (match_dup 2)) | |
6196 + (set (match_dup 4) (mem:HI (match_dup 4))) | |
6197 + (set (reg:QI HARD_A_REGNUM) (match_op_dup:QI 3 | |
6198 + [(reg:QI HARD_A_REGNUM) | |
6199 + (mem:QI (post_inc:QI (match_dup 4)))])) | |
6200 + (set (reg:QI HARD_D_REGNUM) (match_op_dup:QI 3 | |
6201 + [(reg:QI HARD_D_REGNUM) | |
6202 + (mem:QI (post_inc:QI (match_dup 4)))])) | |
6203 + (use (reg:QI HARD_A_REGNUM)) | |
6204 + (set (match_dup 4) (mem:HI (post_inc:HI (reg:HI HARD_S_REGNUM)))) | |
6205 + ] | |
6206 +{ | |
6207 + /* Use X for a temporary index register */ | |
6208 + operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM); | |
6209 +}) | |
6210 + | |
6211 + | |
6212 +; Split a bitwise HImode into two QImode instructions. This is | |
6213 +; the common case. This handles splitting when neither of the | |
6214 +; above two cases applies. | |
6215 +(define_split | |
6216 + [(set (match_operand:HI 0 "register_operand" "") | |
6217 + (match_operator:HI 3 "logical_bit_operator" | |
6218 + [(match_operand:HI 1 "register_operand" "") | |
6219 + (match_operand:HI 2 "general_operand" "")]))] | |
6220 + "reload_completed" | |
6221 + [(set (reg:QI HARD_A_REGNUM) (match_op_dup:QI 3 | |
6222 + [(reg:QI HARD_A_REGNUM) (match_dup 4)])) | |
6223 + (set (reg:QI HARD_D_REGNUM) (match_op_dup:QI 3 | |
6224 + [(reg:QI HARD_D_REGNUM) (match_dup 5)])) | |
6225 + (use (reg:QI HARD_A_REGNUM))] | |
6226 +{ | |
6227 + if (GET_CODE (operands[2]) == CONST_INT) | |
6228 + { | |
6229 + operands[4] = gen_rtx_const_high (operands[2]); | |
6230 + operands[5] = gen_rtx_const_low (operands[2]); | |
6231 + } | |
6232 + else if ((GET_CODE (operands[2]) == MEM) | |
6233 + && (GET_CODE (XEXP (operands[2], 0)) == MEM)) | |
6234 + { | |
6235 + FAIL; | |
6236 + } | |
6237 + else | |
6238 + { | |
6239 + operands[4] = gen_highpart (QImode, operands[2]); | |
6240 + operands[5] = gen_lowpart (QImode, operands[2]); | |
6241 + } | |
6242 +}) | |
6243 + | |
6244 +; Below are the specific cases for each of the operators. | |
6245 +; The QImode versions are the simplest and can be implemented | |
6246 +; directly on the hardware. The HImode cases are all output | |
6247 +; using one of the above splitting techniques. | |
6248 + | |
6249 +;;-------------------------------------------------------------------- | |
6250 +;;- and | |
6251 +;;-------------------------------------------------------------------- | |
6252 + | |
6253 +(define_insn "andhi3" | |
6254 + [(set (match_operand:HI 0 "register_operand" "=d") | |
6255 + (and:HI (match_operand:HI 1 "register_operand" "%0") | |
6256 + (match_operand:HI 2 "general_operand" "mnU")))] | |
6257 + "" | |
6258 + "#") | |
6259 + | |
6260 +;; it is not clear that this is correct | |
6261 +(define_insn "*andqi_2" | |
6262 + [(set | |
6263 + (match_operand:QI 0 "register_operand" "=q") | |
6264 + (and:QI (match_operand:QI 1 "register_operand" "q") | |
6265 + (match_operand 2 "const_int_operand" "i")))] | |
6266 + "" | |
6267 +{ | |
6268 + if (GET_CODE (operands[2]) == CONST_INT) | |
6269 + { | |
6270 + operands[3] = GEN_INT(INTVAL(operands[2]) & 0xff); | |
6271 + return "and%0 %3"; | |
6272 + } | |
6273 + | |
6274 + return "and%0 %2"; | |
6275 +} | |
6276 + [(set_attr "length" "2")]) | |
6277 + | |
6278 +(define_insn "andqi3" | |
6279 + [(set (match_operand:QI 0 "register_operand" "=q,q,q,qc") | |
6280 + (and:QI (match_operand:QI 1 "whole_register_operand" "%0,0,0,0") | |
6281 + (match_operand:QI 2 "whole_general_operand" " O,N,tm,i")))] | |
6282 + "" | |
6283 + "@ | |
6284 + clr%0\t;andqi(ZERO) | |
6285 + \t;andqi(-1) | |
6286 + and%0\t%2 | |
6287 + and%0\t%2" | |
6288 + [(set_attr "length" "1,0,3,2")]) | |
6289 + | |
6290 + | |
6291 +;;-------------------------------------------------------------------- | |
6292 +;;- or | |
6293 +;;-------------------------------------------------------------------- | |
6294 + | |
6295 +(define_insn "iorhi3" | |
6296 + [(set (match_operand:HI 0 "register_operand" "=d") | |
6297 + (ior:HI (match_operand:HI 1 "register_operand" "%0") | |
6298 + (match_operand:HI 2 "general_operand" "mnU")))] | |
6299 + "" | |
6300 + "#") | |
6301 + | |
6302 + | |
6303 +(define_insn "iorqi3" | |
6304 + [(set (match_operand:QI 0 "register_operand" "=q,q, qc") | |
6305 + (ior:QI (match_operand:QI 1 "whole_register_operand" "%0,0, 0") | |
6306 + (match_operand:QI 2 "whole_general_operand" " O,tm,i")))] | |
6307 + "" | |
6308 + "@ | |
6309 + \t;iorqi(ZERO) | |
6310 + or%0\t%2 | |
6311 + or%0\t%2" | |
6312 + [(set_attr "length" "0,3,2")]) | |
6313 + | |
6314 +;;-------------------------------------------------------------------- | |
6315 +;;- xor | |
6316 +;;-------------------------------------------------------------------- | |
6317 + | |
6318 +(define_insn "xorhi3" | |
6319 + [(set (match_operand:HI 0 "register_operand" "=d") | |
6320 + (xor:HI (match_operand:HI 1 "register_operand" "%0") | |
6321 + (match_operand:HI 2 "general_operand" "mnU")))] | |
6322 + "" | |
6323 + "#") | |
6324 + | |
6325 + | |
6326 +(define_insn "xorqi3" | |
6327 + [(set (match_operand:QI 0 "register_operand" "=q,q,q,q") | |
6328 + (xor:QI (match_operand:QI 1 "whole_register_operand" "%0,0,0,0") | |
6329 + (match_operand:QI 2 "whole_general_operand" " O,N,tm,i")))] | |
6330 + "" | |
6331 + "@ | |
6332 + \t;xorqi(ZERO) | |
6333 + com%0\t;xorqi(-1) | |
6334 + eor%0\t%2 | |
6335 + eor%0\t%2" | |
6336 + [(set_attr "length" "0,1,3,2")]) | |
6337 + | |
6338 +;;-------------------------------------------------------------------- | |
6339 +;;- Two's Complements | |
6340 +;;-------------------------------------------------------------------- | |
6341 + | |
6342 +(define_insn "neghi2" | |
6343 + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,!a") | |
6344 + (neg:HI (match_operand:HI 1 "general_operand" "0, 0")))] | |
6345 + "" | |
6346 + "@ | |
6347 + nega\;negb\;sbca\t#0 | |
6348 + exg\td,%0\;nega\;negb\;sbca\t#0\;exg\td,%0" | |
6349 + [(set_attr "length" "5,9")]) | |
6350 + | |
6351 + | |
6352 +(define_insn "negqi2" | |
6353 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,m") | |
6354 + (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))] | |
6355 + "" | |
6356 + "@ | |
6357 + neg%0 | |
6358 + neg\t%0" | |
6359 + [(set_attr "length" "1,3")]) | |
6360 + | |
6361 + | |
6362 +;;-------------------------------------------------------------------- | |
6363 +;;- One's Complements | |
6364 +;;-------------------------------------------------------------------- | |
6365 + | |
6366 +(define_insn "one_cmplhi2" | |
6367 + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,?tm,???a") | |
6368 + (not:HI (match_operand:HI 1 "general_operand" "0, 0, 0")))] | |
6369 + "" | |
6370 + "@ | |
6371 + coma\;comb | |
6372 + com\t%0\;com\t%L0 | |
6373 + exg\td,%0\;coma\;comb\;exg\td,%0" | |
6374 + [(set_attr "length" "2,6,6")]) | |
6375 + | |
6376 + | |
6377 +(define_insn "one_cmplqi2" | |
6378 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,tm") | |
6379 + (not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))] | |
6380 + "" | |
6381 + "@ | |
6382 + com%0 | |
6383 + com\t%0" | |
6384 + [(set_attr "length" "1,3")]) | |
6385 + | |
6386 +;;-------------------------------------------------------------------- | |
6387 +;;- Shifts/rotates | |
6388 +;;-------------------------------------------------------------------- | |
6389 + | |
6390 +(define_code_iterator bit_code [ashift ashiftrt lshiftrt]) | |
6391 +(define_code_attr bit_code_name [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr")]) | |
6392 + | |
6393 +(define_mode_iterator bit_mode [QI HI]) | |
6394 +(define_mode_attr bit_mode_name [(QI "qi3") (HI "hi3")]) | |
6395 + | |
6396 +;; Emit RTL for any shift (handles all 3 opcodes and 2 mode sizes) | |
6397 + | |
6398 +(define_expand "<bit_code:bit_code_name><bit_mode:bit_mode_name>" | |
6399 + [(set (match_operand:bit_mode 0 "nonimmediate_operand" "") | |
6400 + (bit_code:bit_mode (match_operand:bit_mode 1 "general_operand" "") | |
6401 + (match_operand:bit_mode 2 "nonmemory_operand" "")))] | |
6402 + "" | |
6403 +{ | |
6404 +}) | |
6405 + | |
6406 +; Individual instructions implemented in the CPU. | |
6407 + | |
6408 + | |
6409 +(define_insn "*ashift1" | |
6410 + [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q") | |
6411 + (ashift:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))] | |
6412 + "" | |
6413 + "@ | |
6414 + asl\t%0 | |
6415 + asl%0" | |
6416 + [(set_attr "length" "3,1")]) | |
6417 + | |
6418 +(define_insn "*lshiftrt1" | |
6419 + [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q") | |
6420 + (lshiftrt:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))] | |
6421 + "" | |
6422 + "@ | |
6423 + lsr\t%0 | |
6424 + lsr%0" | |
6425 + [(set_attr "length" "3,1")]) | |
6426 + | |
6427 +(define_insn "*ashiftrt1" | |
6428 + [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q") | |
6429 + (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))] | |
6430 + "" | |
6431 + "@ | |
6432 + asr\t%0 | |
6433 + asr%0" | |
6434 + [(set_attr "length" "3,1")]) | |
6435 + | |
6436 +(define_insn "*rotate1" | |
6437 + [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q") | |
6438 + (rotate:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))] | |
6439 + "" | |
6440 + "@ | |
6441 + rol\t%0 | |
6442 + rol%0" | |
6443 + [(set_attr "length" "3,1")]) | |
6444 + | |
6445 + | |
6446 +(define_insn "*rotatert1" | |
6447 + [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q") | |
6448 + (rotatert:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))] | |
6449 + "" | |
6450 + "@ | |
6451 + ror\t%0 | |
6452 + ror%0" | |
6453 + [(set_attr "length" "3,1")]) | |
6454 + | |
6455 + | |
6456 +; A shift by 8 for D reg can be optimized by just moving | |
6457 +; between the A/B halves, and then zero/sign extending or | |
6458 +; filling in zeroes. | |
6459 +; Because GCC does not understand that 'A' and 'D' refer to | |
6460 +; the same storage location, we must use 'USE' throughout | |
6461 +; to prevent deletion of 'unnecessary' instructions. | |
6462 +; Similar optimization for MEM would require a scratch register | |
6463 +; so is not done here. | |
6464 + | |
6465 +(define_split | |
6466 + [(set (reg:HI HARD_D_REGNUM) (ashift:HI (reg:HI HARD_D_REGNUM) (const_int 8)))] | |
6467 + "reload_completed" | |
6468 + [ | |
6469 + (use (reg:HI HARD_D_REGNUM)) | |
6470 + (set (reg:QI HARD_A_REGNUM) (reg:QI HARD_D_REGNUM)) | |
6471 + (use (reg:QI HARD_A_REGNUM)) | |
6472 + (set (reg:QI HARD_D_REGNUM) (const_int 0)) | |
6473 + ] | |
6474 + "") | |
6475 + | |
6476 +(define_split | |
6477 + [(set (reg:HI HARD_D_REGNUM) (lshiftrt:HI (reg:HI HARD_D_REGNUM) (const_int 8)))] | |
6478 + "reload_completed" | |
6479 + [ | |
6480 + (use (reg:HI HARD_D_REGNUM)) | |
6481 + (set (reg:QI HARD_D_REGNUM) (reg:QI HARD_A_REGNUM)) | |
6482 + (use (reg:QI HARD_D_REGNUM)) | |
6483 + (set (reg:HI HARD_D_REGNUM) (zero_extend:HI (reg:QI HARD_D_REGNUM))) | |
6484 + ] | |
6485 + "") | |
6486 + | |
6487 +(define_split | |
6488 + [(set (reg:HI HARD_D_REGNUM) (ashiftrt:HI (reg:HI HARD_D_REGNUM) (const_int 8)))] | |
6489 + "reload_completed" | |
6490 + [ | |
6491 + (use (reg:HI HARD_D_REGNUM)) | |
6492 + (set (reg:QI HARD_D_REGNUM) (reg:QI HARD_A_REGNUM)) | |
6493 + (use (reg:QI HARD_D_REGNUM)) | |
6494 + (set (reg:HI HARD_D_REGNUM) (sign_extend:HI (reg:QI HARD_D_REGNUM))) | |
6495 + ] | |
6496 + "") | |
6497 + | |
6498 + | |
6499 +; On the WPC hardware, there is a shift register that can be used | |
6500 +; to compute (1<<n) efficiently in two instructions. Note that this | |
6501 +; form only works when using -mint8 though, because C will promote | |
6502 +; to 'int' when doing this operation. TODO : we need a 16-bit form too. | |
6503 +(define_insn "ashlqi3_wpc" | |
6504 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q") | |
6505 + (ashift:QI (match_operand:QI 1 "immediate_operand" "I") | |
6506 + (match_operand:QI 2 "general_operand" "q")))] | |
6507 + "TARGET_WPC" | |
6508 + "st%2\t0x3FF7\;ld%0\t0x3FF7" | |
6509 + [(set_attr "length" "6")]) | |
6510 + | |
6511 + | |
6512 +; Internal instructions for shifting by a constant. | |
6513 +; Two forms are provided, one for QImode, one for HImode. | |
6514 +; These are always split into the above instructions | |
6515 +; (except for QImode forms that directly match one of the | |
6516 +; above instructions, in which the condition will not | |
6517 +; allow the splitter to match). | |
6518 + | |
6519 +(define_insn_and_split "<bit_code:bit_code_name>hi3_const" | |
6520 + [(set (match_operand:HI 0 "nonimmediate_operand" "=dm") | |
6521 + (bit_code:HI (match_operand:HI 1 "general_operand" "0") | |
6522 + (match_operand:HI 2 "immediate_operand" "n")))] | |
6523 + "" | |
6524 + "#" | |
6525 + "reload_completed" | |
6526 + [(const_int 0)] | |
6527 +{ | |
6528 + m6809_split_shift (<bit_code:CODE>, operands); | |
6529 + DONE; | |
6530 +}) | |
6531 + | |
6532 + | |
6533 +(define_insn_and_split "<bit_code:bit_code_name>qi3_const" | |
6534 + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") | |
6535 + (bit_code:QI (match_operand:QI 1 "general_operand" "0") | |
6536 + (match_operand:QI 2 "immediate_operand" "n")))] | |
6537 + "INTVAL (operands[2]) > 1" | |
6538 + "#" | |
6539 + "&& reload_completed" | |
6540 + [(const_int 0)] | |
6541 +{ | |
6542 + m6809_split_shift (<bit_code:CODE>, operands); | |
6543 + DONE; | |
6544 +}) | |
6545 + | |
6546 +; Internal instructions for shifting by a nonconstant. | |
6547 +; These expand into complex assembly. | |
6548 + | |
6549 +(define_insn "<bit_code:bit_code_name>hi3_reg" | |
6550 + [(set (match_operand:HI 0 "nonimmediate_operand" "=d") | |
6551 + (bit_code:HI (match_operand:HI 1 "general_operand" "0") | |
6552 + (match_operand:HI 2 "nonimmediate_operand" "v")))] | |
6553 + "" | |
6554 +{ | |
6555 + m6809_output_shift_insn (<bit_code:CODE>, operands); | |
6556 + return ""; | |
6557 +} | |
6558 + [(set_attr "length" "20")]) | |
6559 + | |
6560 + | |
6561 +(define_insn "<bit_code:bit_code_name>qi3_reg" | |
6562 + [(set (match_operand:QI 0 "nonimmediate_operand" "=q") | |
6563 + (bit_code:QI (match_operand:QI 1 "general_operand" "0") | |
6564 + (match_operand:QI 2 "nonimmediate_operand" "v")))] | |
6565 + "" | |
6566 +{ | |
6567 + m6809_output_shift_insn (<bit_code:CODE>, operands); | |
6568 + return ""; | |
6569 +} | |
6570 + [(set_attr "length" "16")]) | |
6571 + | |
6572 + | |
6573 + | |
6574 +;;-------------------------------------------------------------------- | |
6575 +;;- Jumps and transfers | |
6576 +;;-------------------------------------------------------------------- | |
6577 + | |
6578 +;;; The casesi pattern is normally *not* defined; see 'tablejump' instead. | |
6579 +(define_expand "casesi" | |
6580 + [(match_operand:HI 0 "register_operand" "") ; index to jump on | |
6581 + (match_operand:HI 1 "immediate_operand" "") ; lower bound | |
6582 + (match_operand:HI 2 "immediate_operand" "") ; total range | |
6583 + (match_operand 3 "" "") ; table label | |
6584 + (match_operand 4 "" "")] ; out of range label | |
6585 + "TARGET_BYTE_INT && TARGET_CASESI" | |
6586 +{ | |
6587 + m6809_do_casesi (operands[0], operands[1], operands[2], | |
6588 + operands[3], operands[4]); | |
6589 + DONE; | |
6590 +}) | |
6591 + | |
6592 +(define_insn "tablejump_short_offset" | |
6593 + [(set (pc) | |
6594 + (mem:HI (plus:HI (match_operand:HI 1 "register_operand" "U") | |
6595 + (zero_extend:HI (match_operand:QI 0 "register_operand" "q")))))] | |
6596 + "" | |
6597 + "jmp\t[b,x]\t;tablejump_short_offset" | |
6598 + [(set_attr "length" "3")]) | |
6599 + | |
6600 +(define_insn "tablejump_long_offset" | |
6601 + [(set (pc) | |
6602 + (mem:HI (plus:HI (match_operand:HI 1 "register_operand" "U") | |
6603 + (match_operand:HI 0 "register_operand" "d"))))] | |
6604 + "" | |
6605 + "jmp\t[d,x]\t;tablejump_long_offset" | |
6606 + [(set_attr "length" "3")]) | |
6607 + | |
6608 + | |
6609 + ;; A tablejump operation gives the address in operand 0, with the | |
6610 + ;; CODE_LABEL for the table in operand 1. The 'define_expand' | |
6611 + ;; shows the arguments as GCC presents them. For a register | |
6612 + ;; operand, the assembly code is straightforward. For a MEM, | |
6613 + ;; assumed to be a SYMBOL_REF, two forms are given, one normal | |
6614 + ;; and one for PIC mode. | |
6615 + (define_expand "tablejump" | |
6616 + [(parallel [ | |
6617 + (set (pc) (match_operand:HI 0 "" "")) | |
6618 + (use (label_ref (match_operand 1 "" ""))) | |
6619 + (clobber (match_scratch:HI 2 "")) | |
6620 + ])] | |
6621 + "" | |
6622 + { | |
6623 + }) | |
6624 + | |
6625 + | |
6626 +(define_insn "*tablejump_reg" | |
6627 + [(parallel [ | |
6628 + (set (pc) | |
6629 + (match_operand:HI 0 "register_operand" "a")) | |
6630 + (use (label_ref (match_operand 1 "" ""))) | |
6631 + (clobber (match_scratch:HI 2 "")) | |
6632 + ])] | |
6633 + "" | |
6634 + "jmp\t,%0" | |
6635 + [(set_attr "length" "3")]) | |
6636 + | |
6637 + | |
6638 +(define_insn "*tablejump_symbol" | |
6639 + [(parallel [ | |
6640 + (set (pc) | |
6641 + (mem:HI | |
6642 + (plus:HI (match_operand:HI 0 "register_operand" "a") | |
6643 + (label_ref (match_operand 1 "" ""))))) | |
6644 + (use (label_ref (match_dup 1))) | |
6645 + (clobber (match_scratch:HI 2 "")) | |
6646 + ])] | |
6647 + "!flag_pic" | |
6648 +{ | |
6649 + output_asm_insn ("jmp\t[%a1,%0]", operands); | |
6650 + return ""; | |
6651 +} | |
6652 + [(set_attr "length" "4")]) | |
6653 + | |
6654 + | |
6655 +(define_insn "*tablejump_symbol_pic" | |
6656 + [(parallel [ | |
6657 + (set (pc) | |
6658 + (mem:HI | |
6659 + (plus:HI (match_operand:HI 0 "register_operand" "d") | |
6660 + (label_ref (match_operand 1 "" ""))))) | |
6661 + (use (label_ref (match_dup 1))) | |
6662 + (clobber (match_scratch:HI 2 "=&a")) | |
6663 + ])] | |
6664 + "flag_pic" | |
6665 +{ | |
6666 + output_asm_insn ("lea%2\t%a1,pcr", operands); | |
6667 + output_asm_insn ("ld%0\t%0,%2", operands); | |
6668 + output_asm_insn ("jmp\t%0,%2", operands); | |
6669 + return ""; | |
6670 +} | |
6671 + [(set_attr "length" "8")]) | |
6672 + | |
6673 + | |
6674 +(define_insn "indirect_jump" | |
6675 + [(set (pc) | |
6676 + (match_operand:HI 0 "register_operand" "a"))] | |
6677 + "" | |
6678 + "jmp\t,%0" | |
6679 + [(set_attr "length" "3")]) | |
6680 + | |
6681 + | |
6682 +(define_insn "jump" | |
6683 + [(set (pc) (label_ref (match_operand 0 "" "")))] | |
6684 + "" | |
6685 +{ | |
6686 + return output_branch_insn ( LABEL_REF, operands, get_attr_length (insn)); | |
6687 +} | |
6688 + [(set (attr "type") (const_string "branch"))]) | |
6689 + | |
6690 +; Output assembly for a condition branch instruction. | |
6691 +(define_insn "*cond_branch" | |
6692 + [(set (pc) | |
6693 + (if_then_else | |
6694 + (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) | |
6695 + (label_ref (match_operand 0 "" "")) (pc)))] | |
6696 + "" | |
6697 +{ | |
6698 + return output_branch_insn ( GET_CODE(operands[1]), | |
6699 + operands, get_attr_length (insn)); | |
6700 +} | |
6701 + [(set (attr "type") (const_string "cbranch"))]) | |
6702 + | |
6703 + | |
6704 +; Similar to above, but for a condition branch instruction that | |
6705 +; had its operands reversed at some point. | |
6706 +(define_insn "*cond_branch_reverse" | |
6707 + [(set (pc) | |
6708 + (if_then_else | |
6709 + (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) | |
6710 + (pc) (label_ref (match_operand 0 "" ""))))] | |
6711 + "" | |
6712 +{ | |
6713 + return output_branch_insn ( reverse_condition (GET_CODE(operands[1])), | |
6714 + operands, get_attr_length (insn)); | |
6715 +} | |
6716 + [(set (attr "type") (const_string "cbranch"))]) | |
6717 + | |
6718 + | |
6719 + | |
6720 +;;-------------------------------------------------------------------- | |
6721 +;;- Calls | |
6722 +;;-------------------------------------------------------------------- | |
6723 + | |
6724 +;; Generate a call instruction for a function that does not | |
6725 +;; return a value. The expander is used during RTL generation. | |
6726 +;; The instructions below are used during matching; only one | |
6727 +;; of them will be used, depending on the type of function | |
6728 +;; being called. The different conditions are: | |
6729 +;; | |
6730 +;; 1) far_functionp - is this a far function? Those need | |
6731 +;; to be output as indirect calls through a far-function | |
6732 +;; handler. | |
6733 +;; | |
6734 +;; 2) noreturn_functionp - if the function does not return, | |
6735 +;; we can use a 'jmp' instead of a 'jsr' to call it. | |
6736 +;; | |
6737 +;; 3) is PIC mode enabled? If so, we'll always use | |
6738 +;; relative calls (lbsr or lbra). | |
6739 +;; | |
6740 +;; Note: not all combinations are fully supported, especially | |
6741 +;; relating to PIC. | |
6742 +;; | |
6743 +;; The 'bsr' instruction is never generated. | |
6744 + | |
6745 +(define_expand "call" | |
6746 + [(call (match_operand:HI 0 "memory_operand" "") | |
6747 + (match_operand:HI 1 "general_operand" ""))] | |
6748 + "" | |
6749 + "") | |
6750 + | |
6751 +(define_insn "*call_nopic_far" | |
6752 + [(call (match_operand:HI 0 "memory_operand" "m") | |
6753 + (match_operand:HI 1 "general_operand" "g"))] | |
6754 + "far_functionp (operands[0])" | |
6755 +{ | |
6756 + output_far_call_insn (operands, 0); | |
6757 + return ""; | |
6758 +} | |
6759 + [(set_attr "length" "6")]) | |
6760 + | |
6761 + | |
6762 +; PIC forms come first, and should only match | |
6763 +; (MEM (SYMBOL_REF)). Other MEM forms are treated as usual. | |
6764 +(define_insn "*call_pic" | |
6765 + [(call (mem:HI (match_operand:HI 0 "symbolic_operand" "")) | |
6766 + (match_operand:HI 1 "general_operand" "g"))] | |
6767 + "flag_pic && !noreturn_functionp (operands[0])" | |
6768 + "lbsr\t%C0" | |
6769 + [(set_attr "length" "4")]) | |
6770 + | |
6771 + | |
6772 +(define_insn "*call_nopic" | |
6773 + [(call (match_operand:HI 0 "memory_operand" "m") | |
6774 + (match_operand:HI 1 "general_operand" "g"))] | |
6775 + "!noreturn_functionp (operands[0])" | |
6776 + "jsr\t%0" | |
6777 + [(set_attr "length" "3") | |
6778 + (set (attr "cycles") (const_int JSR_EXTENDED_CYCLES))]) | |
6779 + | |
6780 + | |
6781 +(define_insn "*call_noreturn_pic" | |
6782 + [(call (mem:HI (match_operand:HI 0 "symbolic_operand" "")) | |
6783 + (match_operand:HI 1 "general_operand" "g"))] | |
6784 + "flag_pic && noreturn_functionp (operands[0])" | |
6785 + "lbra\t%C0" | |
6786 + [(set_attr "length" "4")]) | |
6787 + | |
6788 + | |
6789 +(define_insn "*call_noreturn_nopic" | |
6790 + [(call (match_operand:HI 0 "memory_operand" "m") | |
6791 + (match_operand:HI 1 "general_operand" "g"))] | |
6792 + "noreturn_functionp (operands[0])" | |
6793 + "jmp\t%0" | |
6794 + [(set_attr "length" "3")]) | |
6795 + | |
6796 + | |
6797 +;; | |
6798 +;; Same as above, but for functions that do return a value. | |
6799 +;; | |
6800 +(define_expand "call_value" | |
6801 + [(set (match_operand 0 "" "") | |
6802 + (call (match_operand:HI 1 "memory_operand" "") | |
6803 + (match_operand:HI 2 "general_operand" "")))] | |
6804 + "" | |
6805 + "") | |
6806 + | |
6807 + | |
6808 +(define_insn "*call_value_far" | |
6809 + [(set (match_operand 0 "" "=gz") | |
6810 + (call (match_operand:HI 1 "memory_operand" "m") | |
6811 + (match_operand:HI 2 "general_operand" "g")))] | |
6812 + "far_functionp (operands[1])" | |
6813 +{ | |
6814 + output_far_call_insn (operands, 1); | |
6815 + return ""; | |
6816 +} | |
6817 + [(set_attr "length" "6")]) | |
6818 + | |
6819 + | |
6820 +(define_insn "*call_value_pic" | |
6821 + [(set (match_operand 0 "" "=gz") | |
6822 + (call (mem:HI (match_operand:HI 1 "symbolic_operand" "")) | |
6823 + (match_operand:HI 2 "general_operand" "g")))] | |
6824 + "flag_pic" | |
6825 + "lbsr\t%C1" | |
6826 + [(set_attr "length" "4")]) | |
6827 + | |
6828 + | |
6829 +(define_insn "*call_value_nopic" | |
6830 + [(set (match_operand 0 "" "=gz") | |
6831 + (call (match_operand:HI 1 "memory_operand" "m") | |
6832 + (match_operand:HI 2 "general_operand" "g")))] | |
6833 + "" | |
6834 + "jsr\t%1" | |
6835 + [(set_attr "length" "3") | |
6836 + (set (attr "cycles") (const_int JSR_EXTENDED_CYCLES))]) | |
6837 + | |
6838 + | |
6839 + | |
6840 +;; | |
6841 +;; How to generate an untyped call. | |
6842 +;; | |
6843 +(define_expand "untyped_call" | |
6844 + [(parallel [(call (match_operand 0 "" "") | |
6845 + (const_int 0)) | |
6846 + (match_operand 1 "" "") | |
6847 + (match_operand 2 "" "")])] | |
6848 + "" | |
6849 +{ | |
6850 + int i; | |
6851 + | |
6852 + emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); | |
6853 + for (i=0; i < XVECLEN (operands[2], 0); i++) | |
6854 + { | |
6855 + rtx set = XVECEXP (operands[2], 0, i); | |
6856 + emit_move_insn (SET_DEST (set), SET_SRC (set)); | |
6857 + } | |
6858 + emit_insn (gen_blockage ()); | |
6859 + DONE; | |
6860 +}) | |
6861 + | |
6862 + | |
6863 +(define_expand "sibcall" | |
6864 + [(parallel | |
6865 + [(call (match_operand:HI 0 "memory_operand" "") | |
6866 + (match_operand:HI 1 "immediate_operand" "")) | |
6867 + (use (reg:HI HARD_PC_REGNUM))])] | |
6868 + "" | |
6869 + "") | |
6870 + | |
6871 +(define_insn "*sibcall_1" | |
6872 + [(parallel | |
6873 + [(call (match_operand:HI 0 "memory_operand" "m") | |
6874 + (match_operand:HI 1 "immediate_operand" "i")) | |
6875 + (use (reg:HI HARD_PC_REGNUM))])] | |
6876 + "SIBLING_CALL_P(insn)" | |
6877 + "jmp\t%0" | |
6878 + [(set_attr "length" "4")]) | |
6879 + | |
6880 + | |
6881 +(define_expand "sibcall_value" | |
6882 + [(parallel | |
6883 + [(set (match_operand 0 "" "") | |
6884 + (call (match_operand:HI 1 "memory_operand" "") | |
6885 + (match_operand:HI 2 "immediate_operand" ""))) | |
6886 + (use (reg:HI HARD_PC_REGNUM))])] | |
6887 + "" | |
6888 + "") | |
6889 + | |
6890 +(define_insn "*sibcall_value_1" | |
6891 + [(parallel | |
6892 + [(set (match_operand 0 "" "=gz") | |
6893 + (call (match_operand:HI 1 "memory_operand" "m") | |
6894 + (match_operand:HI 2 "immediate_operand" "i"))) | |
6895 + (use (reg:HI HARD_PC_REGNUM))])] | |
6896 + "SIBLING_CALL_P(insn)" | |
6897 + "jmp\t%1" | |
6898 + [(set_attr "length" "4")]) | |
6899 + | |
6900 + | |
6901 +;;-------------------------------------------------------------------- | |
6902 +;;- Function Entry and Exit | |
6903 +;;-------------------------------------------------------------------- | |
6904 + | |
6905 +;; On entry to a function, the stack frame looks as follows: | |
6906 +;; - return address (pushed by the caller) | |
6907 +;; - saved registers | |
6908 +;; - local variable storage | |
6909 +;; | |
6910 +;; If the function does not modify the stack after that, then | |
6911 +;; any of these can be accessed directly as an offset from | |
6912 +;; STACK_POINTER_REGNUM. Otherwise, a frame pointer is required. | |
6913 +;; In that case, the prologue must also initialize HARD_FRAME_POINTER_REGNUM | |
6914 +;; and all references to the stack frame will use that as a base instead. | |
6915 +;; | |
6916 +(define_expand "prologue" | |
6917 + [(const_int 0)] | |
6918 + "prologue_epilogue_required ()" | |
6919 +{ | |
6920 + emit_prologue_insns (); | |
6921 + DONE; | |
6922 +}) | |
6923 + | |
6924 + | |
6925 +;; The function epilogue does exactly the reverse of the prologue, | |
6926 +;; deallocating local variable space, restoring saved registers, | |
6927 +;; and returning. | |
6928 +;; | |
6929 +;; For the 6809, the return may be 'rti' if the function was | |
6930 +;; declared as an interrupt function, but is normally 'rts'. | |
6931 +;; | |
6932 +;; Also, as an optimization, the register restore and the 'rts' | |
6933 +;; can be combined into a single instruction, by adding 'PC' to the | |
6934 +;; list of registers to be restored. This is only done if there are | |
6935 +;; any saved registers, as 'rts' is more efficient by itself. | |
6936 +;; | |
6937 +(define_expand "epilogue" | |
6938 + [(const_int 0)] | |
6939 + "prologue_epilogue_required ()" | |
6940 +{ | |
6941 + emit_epilogue_insns (false); | |
6942 + DONE; | |
6943 +}) | |
6944 + | |
6945 + | |
6946 +(define_expand "sibcall_epilogue" | |
6947 + [(const_int 0)] | |
6948 + "prologue_epilogue_required ()" | |
6949 +{ | |
6950 + emit_epilogue_insns (true); | |
6951 + DONE; | |
6952 +}) | |
6953 + | |
6954 + | |
6955 +;; The RTS instruction | |
6956 +(define_insn "return_rts" | |
6957 + [(return) | |
6958 + (use (reg:HI HARD_PC_REGNUM))] | |
6959 + "!m6809_current_function_has_type_attr_p (\"interrupt\") | |
6960 + && m6809_get_live_regs () == 0" | |
6961 + "rts" | |
6962 + [(set_attr "length" "1") | |
6963 + (set (attr "cycles") (const_int RTS_CYCLES))]) | |
6964 + | |
6965 +(define_insn "return_puls_pc" | |
6966 + [(return) | |
6967 + (use (reg:HI HARD_PC_REGNUM))] | |
6968 + "!m6809_current_function_has_type_attr_p (\"interrupt\") | |
6969 + && m6809_get_live_regs () != 0" | |
6970 + "" | |
6971 + [(set_attr "length" "1") | |
6972 + (set (attr "cycles") (const_int RTS_CYCLES))]) | |
6973 + | |
6974 +;; The RTI instruction | |
6975 +(define_insn "return_rti" | |
6976 + [(return) | |
6977 + (use (reg:HI HARD_PC_REGNUM))] | |
6978 + "m6809_current_function_has_type_attr_p (\"interrupt\")" | |
6979 + "rti" | |
6980 + [(set_attr "length" "1") | |
6981 + (set (attr "cycles") (const_int RTI_CYCLES))]) | |
6982 + | |
6983 + | |
6984 +;;-------------------------------------------------------------------- | |
6985 +;;- Unspecified instructions | |
6986 +;;-------------------------------------------------------------------- | |
6987 + | |
6988 +;; An instruction that has the effect of an unspec_volatile, but | |
6989 +;; which doesn't require emitting any assembly code. | |
6990 +(define_insn "blockage" | |
6991 + [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)] | |
6992 + "" | |
6993 + "" | |
6994 + [(set_attr "length" "0") | |
6995 + (set (attr "cycles") (const_int 0))]) | |
6996 + | |
6997 + | |
6998 +;; Say how to push multiple registers onto the stack, using | |
6999 +;; the 6809 'pshs' instruction. The operand is a regset | |
7000 +;; specifying which registers to push. | |
7001 +;; | |
7002 +;; The operand mode is not given intentionally, so as to allow | |
7003 +;; any possible integer mode for the regset. | |
7004 +;; | |
7005 +;; See below for a peephole that can combine consecutive push | |
7006 +;; instructions that qualify for merging. | |
7007 +(define_insn "register_push" | |
7008 + [(use (reg:HI HARD_S_REGNUM)) | |
7009 + (unspec_volatile | |
7010 + [(match_operand 0 "immediate_operand" "")] UNSPEC_PUSH_RS) | |
7011 + (clobber (reg:HI HARD_S_REGNUM))] | |
7012 + "" | |
7013 + "pshs\t%R0" | |
7014 + [(set_attr "length" "2") | |
7015 + (set (attr "cycles") (const_int PSH_PUL_CYCLES))]) | |
7016 + | |
7017 + | |
7018 +;; Say how to pop multiple registers from the stack, using | |
7019 +;; the 6809 'puls' instruction. The operand is the register | |
7020 +;; bitset value. | |
7021 +(define_insn "register_pop" | |
7022 + [(use (reg:HI HARD_S_REGNUM)) | |
7023 + (unspec_volatile | |
7024 + [(match_operand 0 "immediate_operand" "")] UNSPEC_POP_RS) | |
7025 + (clobber (reg:HI HARD_S_REGNUM))] | |
7026 + "" | |
7027 + "puls\t%R0" | |
7028 + [(set_attr "length" "2") | |
7029 + (set (attr "cycles") (const_int PSH_PUL_CYCLES))]) | |
7030 + | |
7031 + | |
7032 +(define_insn "m6809_swi" | |
7033 + [(unspec_volatile | |
7034 + [(match_operand:QI 0 "immediate_operand" "I,n")] UNSPEC_SWI)] | |
7035 + "" | |
7036 + "@ | |
7037 + swi | |
7038 + swi%c0" | |
7039 + [(set_attr "length" "1,2") | |
7040 + (set (attr "cycles") (const_int SWI_CYCLES))]) | |
7041 + | |
7042 + | |
7043 +;; Generate the CWAI instruction | |
7044 +(define_insn "m6809_cwai" | |
7045 + [(unspec_volatile | |
7046 + [(match_operand:QI 0 "immediate_operand" "")] UNSPEC_CWAI)] | |
7047 + "" | |
7048 + "cwai\t%0" | |
7049 + [(set_attr "length" "2") | |
7050 + (set (attr "cycles") (const_int CWAI_CYCLES))]) | |
7051 + | |
7052 + | |
7053 +;; Generate the SYNC instruction | |
7054 +(define_insn "m6809_sync" | |
7055 + [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)] | |
7056 + "" | |
7057 + "sync" | |
7058 + [(set_attr "length" "1") | |
7059 + (set (attr "cycles") (const_int SYNC_CYCLES))]) | |
7060 + | |
7061 + | |
7062 +;; Generate the NOP instruction | |
7063 +(define_insn "nop" | |
7064 + [(const_int 0)] | |
7065 + "" | |
7066 + "nop" | |
7067 + [(set_attr "length" "1") | |
7068 + (set (attr "cycles") (const_int NOP_CYCLES))]) | |
7069 + | |
7070 + | |
7071 +;;-------------------------------------------------------------------- | |
7072 +;;- Peepholes | |
7073 +;;-------------------------------------------------------------------- | |
7074 + | |
7075 +;;; Each peephole has an ID that is used for debugging. | |
7076 +;;; Each peephole condition is bracketed by calls to | |
7077 +;;; m6809_match_peephole2() also for debugging. | |
7078 +(define_constants [ | |
7079 + (PEEP_END 0) | |
7080 + (PEEP_COND 1) | |
7081 + | |
7082 + (PEEP_STACK_STORE_INC 0) | |
7083 + (PEEP_STACK_CLEAR_INC 1) | |
7084 + (PEEP_LSRB_ADCB 2) | |
7085 + (PEEP_ABX 3) | |
7086 + (PEEP_ABX2 4) | |
7087 + (PEEP_INDEXED_INC 5) | |
7088 + (PEEP_MEM_DEC 6) | |
7089 + (PEEP_MEM_INC 7) | |
7090 + (PEEP_MEM_DEC_CMP 8) | |
7091 + (PEEP_PUSH2 9) | |
7092 + (PEEP_STORE_IMPLIES_CC 10) | |
7093 + (PEEP_DEC_IMPLIES_CC 11) | |
7094 + (PEEP_LEAB 12) | |
7095 + (PEEP_LDX_INDIRECT 13) | |
7096 + (PEEP_POP_JUNK 14) | |
7097 +]) | |
7098 + | |
7099 + | |
7100 +;;; Optimize 'leas -1,s' followed by 'stb ,s'. This can happen if the | |
7101 +;;; function prologue needs to allocate stack space and 'b' is placed | |
7102 +;;; into that local right away. Combine the stack allocation with the | |
7103 +;;; store using preincrement mode. | |
7104 +(define_peephole2 | |
7105 + [(set (reg:HI HARD_S_REGNUM) | |
7106 + (plus:HI (reg:HI HARD_S_REGNUM) (const_int -1))) | |
7107 + (set (mem:QI (reg:HI HARD_S_REGNUM)) | |
7108 + (match_operand:QI 0 "register_operand" ""))] | |
7109 + "m6809_match_peephole2 (PEEP_STACK_STORE_INC, PEEP_END)" | |
7110 + [(set (mem:QI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (match_dup 0))] | |
7111 + "") | |
7112 + | |
7113 + | |
7114 +;;; Same as above, but for a 'clr ,s' that follows the prologue. | |
7115 +(define_peephole2 | |
7116 + [(set (reg:HI HARD_S_REGNUM) (plus:HI (reg:HI HARD_S_REGNUM) (const_int -1))) | |
7117 + (set (mem:QI (reg:HI HARD_S_REGNUM)) (const_int 0))] | |
7118 + "m6809_match_peephole2 (PEEP_STACK_CLEAR_INC, PEEP_END)" | |
7119 + [(set (mem:QI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (const_int 0))] | |
7120 + "") | |
7121 + | |
7122 + | |
7123 +;;; Merge two consecutive push instructions into a single register_push. | |
7124 +(define_peephole2 | |
7125 + [(set (match_operand 0 "push_operand" "") | |
7126 + (match_operand 1 "register_operand" "")) | |
7127 + (set (match_operand 2 "push_operand" "") | |
7128 + (match_operand 3 "register_operand" ""))] | |
7129 + "m6809_match_peephole2 (PEEP_PUSH2, PEEP_COND) | |
7130 + && reload_completed | |
7131 + && GET_MODE (operands[1]) == GET_MODE (operands[3]) | |
7132 + && m6809_can_merge_pushpop_p (UNSPEC_PUSH_RS, 1 << REGNO (operands[1]), 1 << REGNO (operands[3])) | |
7133 + && m6809_match_peephole2 (PEEP_PUSH2, PEEP_END)" | |
7134 + [(parallel [ | |
7135 + (use (reg:HI HARD_S_REGNUM)) | |
7136 + (unspec_volatile [(match_dup 4)] UNSPEC_PUSH_RS) | |
7137 + (clobber (reg:HI HARD_S_REGNUM))]) | |
7138 + (use (match_dup 1)) | |
7139 + (use (match_dup 3))] | |
7140 +{ | |
7141 + operands[4] = gen_rtx_CONST_INT (QImode, | |
7142 + (1 << REGNO (operands[1])) | (1 << REGNO (operands[3]))); | |
7143 +}) | |
7144 + | |
7145 + | |
7146 +;;; Convert 'stX ,--s' into a push instruction. Use the regset | |
7147 +;;; notation, so that it may be combined with an adjacent regset. | |
7148 +;;; TBD - this doesn't compile some code cleanly. | |
7149 +;(define_peephole2 | |
7150 +; [(set (mem:HI (pre_dec:HI (reg:HI HARD_S_REGNUM))) | |
7151 +; (reg:HI HARD_X_REGNUM))] | |
7152 +; "reload_completed" | |
7153 +; [(parallel [ | |
7154 +; (use (reg:HI HARD_S_REGNUM)) | |
7155 +; (unspec_volatile [(match_dup 0)] UNSPEC_PUSH_RS) | |
7156 +; (clobber (reg:HI HARD_S_REGNUM))])] | |
7157 +;{ | |
7158 +; operands[0] = gen_rtx_CONST_INT (HImode, X_REGBIT); | |
7159 +;}) | |
7160 + | |
7161 + | |
7162 +;;; | |
7163 +;;; q = (q+1)/2 can be optimized as "lsrb; adcb". This also | |
7164 +;;; won't overflow when q=0xFF. | |
7165 +;;; TODO : this form isn't accounting for promotion when | |
7166 +;;; using 16-bit ints. | |
7167 +;;; | |
7168 +(define_peephole | |
7169 + [(set (reg:QI HARD_D_REGNUM) | |
7170 + (lshiftrt:QI (plus:HI (match_dup 0) (const_int 1)) (const_int 1)))] | |
7171 + "m6809_match_peephole2 (PEEP_LSRB_ADCB, PEEP_END)" | |
7172 + "lsrb\;adcb\t#0; peephole" | |
7173 + [(set_attr "length" "2")]) | |
7174 + | |
7175 + | |
7176 +;; | |
7177 +;; Optimize the case of following a register store with a test | |
7178 +;; of reg or mem just moved. | |
7179 +;; | |
7180 +(define_peephole | |
7181 + [(set (match_operand:HI 0 "memory_operand" "=m") | |
7182 + (match_operand:HI 1 "register_operand" "r")) | |
7183 + (set (cc0) (match_operand:HI 2 "general_operand" "g"))] | |
7184 + "m6809_match_peephole2 (PEEP_STORE_IMPLIES_CC, PEEP_COND) | |
7185 + && (operands[2] == operands[0] || operands[2] == operands[1]) | |
7186 + && m6809_match_peephole2 (PEEP_STORE_IMPLIES_CC, PEEP_END)" | |
7187 + "st%1\t%0\t;movhi: R:%1 -> %0 w/ implied test of %2" | |
7188 + [(set_attr "length" "4")]) | |
7189 + | |
7190 + | |
7191 +;; Optimize a pair of SET instructions in which the second insn | |
7192 +;; is the reverse of the first one. I.e. | |
7193 +;; | |
7194 +;; A = B | |
7195 +;; ----> A = B | |
7196 +;; B = A | |
7197 +;; | |
7198 +;; The second insn is redundant. Define two patterns, one for QI, one for HI. | |
7199 +;; But don't do this if either is a VOLATILE MEM. | |
7200 +(define_peephole2 | |
7201 + [(set (match_operand:HI 0 "nonimmediate_operand" "") | |
7202 + (match_operand:HI 1 "nonimmediate_operand" "")) | |
7203 + (set (match_dup 1) (match_dup 0))] | |
7204 + "!MEM_P (operands[0]) || !MEM_P (operands[1]) || (!MEM_VOLATILE_P (operands[0]) && !MEM_VOLATILE_P (operands[1]))" | |
7205 + [(set (match_dup 0) (match_dup 1))] | |
7206 + "") | |
7207 + | |
7208 +(define_peephole2 | |
7209 + [(set (match_operand:QI 0 "nonimmediate_operand" "") | |
7210 + (match_operand:QI 1 "nonimmediate_operand" "")) | |
7211 + (set (match_dup 1) (match_dup 0))] | |
7212 + "!MEM_P (operands[0]) || !MEM_P (operands[1]) || (!MEM_VOLATILE_P (operands[0]) && !MEM_VOLATILE_P (operands[1]))" | |
7213 + [(set (match_dup 0) (match_dup 1))] | |
7214 + "") | |
7215 + | |
7216 + | |
7217 +;; | |
7218 +;; Optimize the sum of an 8-bit and 16-bit using the 'abx' instruction | |
7219 +;; if B and X can be used. Two patterns are provided to catch both | |
7220 +;; X=X+D and X=D+X. | |
7221 +;; | |
7222 +(define_peephole | |
7223 + [(set (reg:HI HARD_D_REGNUM) | |
7224 + (zero_extend:HI (match_operand:QI 0 "general_operand" "q"))) | |
7225 + (set (reg:HI HARD_X_REGNUM) | |
7226 + (plus:HI (reg:HI HARD_D_REGNUM) (reg:HI HARD_X_REGNUM)))] | |
7227 + "m6809_match_peephole2 (PEEP_ABX, PEEP_END)" | |
7228 + "abx" | |
7229 + [(set_attr "length" "1")]) | |
7230 + | |
7231 +(define_peephole | |
7232 + [(set (reg:HI HARD_D_REGNUM) | |
7233 + (zero_extend:HI (match_operand:QI 0 "general_operand" "q"))) | |
7234 + (set (reg:HI HARD_X_REGNUM) | |
7235 + (plus:HI (reg:HI HARD_X_REGNUM) (reg:HI HARD_D_REGNUM)))] | |
7236 + "m6809_match_peephole2 (PEEP_ABX, PEEP_END)" | |
7237 + "abx" | |
7238 + [(set_attr "length" "1")]) | |
7239 + | |
7240 +;;; Likewise, handle when B is scaled by 2 prior to the add. | |
7241 +;;; Instead of shifting B in 4 cycles, just do the ABX a second | |
7242 +;;; time, in only 3 cycles. | |
7243 + | |
7244 +(define_peephole | |
7245 + [(set (reg:HI HARD_D_REGNUM) | |
7246 + (zero_extend:HI (match_operand:QI 0 "general_operand" "q"))) | |
7247 + (set (reg:HI HARD_D_REGNUM) | |
7248 + (ashift:HI (reg:HI HARD_D_REGNUM) (const_int 1))) | |
7249 + (set (reg:HI HARD_X_REGNUM) | |
7250 + (plus:HI (reg:HI HARD_D_REGNUM) (reg:HI HARD_X_REGNUM)))] | |
7251 + "m6809_match_peephole2 (PEEP_ABX2, PEEP_END)" | |
7252 + "abx\;abx" | |
7253 + [(set_attr "length" "2")]) | |
7254 + | |
7255 +(define_peephole | |
7256 + [(set (reg:HI HARD_D_REGNUM) | |
7257 + (zero_extend:HI (match_operand:QI 0 "general_operand" "q"))) | |
7258 + (set (reg:HI HARD_D_REGNUM) | |
7259 + (ashift:HI (reg:HI HARD_D_REGNUM) (const_int 1))) | |
7260 + (set (reg:HI HARD_X_REGNUM) | |
7261 + (plus:HI (reg:HI HARD_X_REGNUM) (reg:HI HARD_D_REGNUM)))] | |
7262 + "m6809_match_peephole2 (PEEP_ABX2, PEEP_END)" | |
7263 + "abx\;abx" | |
7264 + [(set_attr "length" "2")]) | |
7265 + | |
7266 + | |
7267 +;; | |
7268 +;; Work around a compiler bug that generates bad code when copying | |
7269 +;; between 32-bit memory addresses after a libcall. The problem seen is | |
7270 +;; that the source is MEM (REG X), but X is used as the reload register. | |
7271 +;; The second half of the copy therefore fails. | |
7272 +;; | |
7273 +;; The solution is to switch the reload register to D, since that is guaranteed | |
7274 +;; not to be in use right after a libcall. | |
7275 +;; | |
7276 +(define_peephole2 | |
7277 + [(set (reg:HI HARD_X_REGNUM) (mem:HI (reg:HI HARD_X_REGNUM))) | |
7278 + (set (match_operand:HI 0 "nonimmediate_operand" "") (reg:HI HARD_X_REGNUM)) | |
7279 + (set (reg:HI HARD_X_REGNUM) | |
7280 + (mem:HI (plus:HI (reg:HI HARD_X_REGNUM) (const_int 2)))) | |
7281 + (set (match_operand:HI 1 "nonimmediate_operand" "") (reg:HI HARD_X_REGNUM))] | |
7282 + "reload_completed" | |
7283 + [(set (reg:HI HARD_D_REGNUM) (mem:HI (reg:HI HARD_X_REGNUM))) | |
7284 + (set (match_dup 0) (reg:HI HARD_D_REGNUM)) | |
7285 + (set (reg:HI HARD_X_REGNUM) | |
7286 + (mem:HI (plus:HI (reg:HI HARD_X_REGNUM) (const_int 2)))) | |
7287 + (set (match_dup 1) (reg:HI HARD_X_REGNUM))] | |
7288 + "") | |
7289 + | |
7290 + | |
7291 +;; Turn "and then test" into a "bit test" operation. | |
7292 +;; Provide variants for immediate and memory sources | |
7293 +;; This is the most used peephople. | |
7294 +; (define_peephole | |
7295 +; [(set (match_operand:QI 0 "register_operand" "=q") | |
7296 +; (and:QI (match_operand:QI 1 "register_operand" "0") | |
7297 +; (match_operand:QI 2 "immediate_operand" "i"))) | |
7298 +; (set (cc0) (match_dup 0))] | |
7299 +; "" | |
7300 +; "bit%0\t%2" | |
7301 +; [(set_attr "length" "3")]) | |
7302 +; | |
7303 +; (define_peephole | |
7304 +; [(set (match_operand:QI 0 "register_operand" "=q") | |
7305 +; (and:QI (match_operand:QI 1 "register_operand" "0") | |
7306 +; (match_operand:QI 2 "memory_operand" "m"))) | |
7307 +; (set (cc0) (match_dup 0))] | |
7308 +; "" | |
7309 +; "bit%0\t%2" | |
7310 +; [(set_attr "length" "4")]) | |
7311 + | |
7312 + | |
7313 +;; Turn a "decrement, then test" sequence into just a "decrement". | |
7314 +;; The test can be omitted, since it is implicitly done. | |
7315 +(define_peephole2 | |
7316 + [(set (match_operand:QI 0 "nonimmediate_operand" "") | |
7317 + (plus:QI (match_operand:QI 1 "whole_general_operand" "") | |
7318 + (match_operand:QI 2 "immediate_operand" ""))) | |
7319 + (set (cc0) (match_dup 0))] | |
7320 + "m6809_match_peephole2 (PEEP_DEC_IMPLIES_CC, PEEP_END)" | |
7321 + [(set (match_dup 0) (plus:QI (match_dup 1) (match_dup 2)))] | |
7322 + "") | |
7323 + | |
7324 + | |
7325 +;; Merge an indexed register increment with a previous usage. | |
7326 +;; This is usually done automatically, but not always | |
7327 +;; The 'use' should be optional; in all cases where this has been | |
7328 +;; seen, it is required though. | |
7329 +(define_peephole2 | |
7330 + [(set (match_operand:QI 0 "register_operand" "") | |
7331 + (mem:QI (match_operand:HI 1 "index_register_operand" ""))) | |
7332 + (use (match_dup 0)) | |
7333 + (set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))] | |
7334 + "m6809_match_peephole2 (PEEP_INDEXED_INC, PEEP_END)" | |
7335 + [(set (match_dup 0) (mem:QI (post_inc:HI (match_dup 1)))) | |
7336 + (use (match_dup 0))] | |
7337 + "") | |
7338 + | |
7339 + | |
7340 +;;; Merge "ldX MEM; ldX ,X" into a single instruction using | |
7341 +;;; the indirect mode. | |
7342 +(define_peephole2 | |
7343 + [(set (reg:HI HARD_X_REGNUM) | |
7344 + (mem:HI (match_operand:HI 0 "general_operand" ""))) | |
7345 + (set (reg:HI HARD_X_REGNUM) (mem:HI (reg:HI HARD_X_REGNUM)))] | |
7346 + "reload_completed && m6809_match_peephole2 (PEEP_LDX_INDIRECT, PEEP_END)" | |
7347 + [(set (reg:HI HARD_X_REGNUM) | |
7348 + (mem:HI (mem:HI (match_dup 0))))] | |
7349 + "") | |
7350 + | |
7351 + | |
7352 +;;; Reorder a store followed by a unary operation on that memory | |
7353 +;;; so that the unary is performed and then the store. Consider | |
7354 +;;; a binary shift operation, which will be decomposed into | |
7355 +;;; identical single shifts, also. | |
7356 +;;; TODO - recognize more than just 'ashift' here. | |
7357 +(define_peephole2 | |
7358 + [(set (match_operand:QI 0 "memory_operand" "") | |
7359 + (match_operand:QI 1 "register_operand" "")) | |
7360 + (set (match_dup 0) | |
7361 + (ashift:QI (match_dup 0) (match_operand:QI 2 "immediate_operand")))] | |
7362 + "reload_completed" | |
7363 + [(set (match_dup 1) | |
7364 + (ashift:QI (match_dup 1) (match_operand:QI 2 "immediate_operand"))) | |
7365 + (set (match_dup 0) (match_dup 1))] | |
7366 + "") | |
7367 + | |
7368 +;;; Likewise, reorder a unary MEM followed by a load, so that the load | |
7369 +;;; is done first, then use the REG instead of the MEM. | |
7370 +;;;(define_peephole2 | |
7371 +;;; [(set (match_dup 0) | |
7372 +;;; (ashift:QI (match_dup 0) (match_operand:QI 2 "immediate_operand"))) | |
7373 +;;; (set (match_operand:QI 0 "register_operand" "") | |
7374 +;;; (match_operand:QI 1 "memory_operand" ""))] | |
7375 +;;; "reload_completed" | |
7376 +;;; [(set (match_dup 0) (match_dup 1)) | |
7377 +;;; (set (match_dup 0) | |
7378 +;;; (ashift:QI (match_dup 0) (match_operand:QI 2 "immediate_operand")))] | |
7379 +;;; "") | |
7380 + | |
7381 + | |
7382 +;;; Replace sex; leaX d,Y with leaX b,Y. | |
7383 +;;; | |
7384 +(define_peephole2 | |
7385 + [(set (reg:HI HARD_D_REGNUM) (sign_extend:HI (reg:QI HARD_D_REGNUM))) | |
7386 + (set (match_operand:HI 0 "index_register_operand" "") | |
7387 + (plus:HI (match_operand:HI 1 "index_register_operand" "") | |
7388 + (reg:HI HARD_D_REGNUM)))] | |
7389 + "reload_completed && m6809_match_peephole2 (PEEP_LEAB, PEEP_END)" | |
7390 + [(set (match_dup 0) | |
7391 + (plus:HI (match_dup 1) (reg:QI HARD_D_REGNUM)))] | |
7392 + "") | |
7393 + | |
7394 +(define_peephole2 | |
7395 + [(set (reg:HI HARD_D_REGNUM) (sign_extend:HI (reg:QI HARD_D_REGNUM))) | |
7396 + (set (match_operand:HI 0 "index_register_operand" "") | |
7397 + (plus:HI (reg:HI HARD_D_REGNUM) | |
7398 + (match_operand:HI 1 "index_register_operand" "")))] | |
7399 + "reload_completed && m6809_match_peephole2 (PEEP_LEAB, PEEP_END)" | |
7400 + [(set (match_dup 0) | |
7401 + (plus:HI (match_dup 1) (reg:QI HARD_D_REGNUM)))] | |
7402 + "") | |
7403 + | |
7404 + | |
7405 +;;; Replace ldb; decb; stb; tstb with dec(mem). If the | |
7406 +;;; register is not needed, then the load will get deleted | |
7407 +;;; automatically, but it may be needed for comparisons. | |
7408 +;;; Same for incb/inc. | |
7409 +(define_peephole2 | |
7410 + [(set (match_operand:QI 0 "register_operand" "") | |
7411 + (match_operand:QI 1 "nonimmediate_operand" "")) | |
7412 + (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) | |
7413 + (set (match_dup 1) (match_dup 0)) | |
7414 + (set (cc0) (match_dup 0))] | |
7415 + "m6809_match_peephole2 (PEEP_MEM_DEC_CMP, PEEP_END)" | |
7416 + [(set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))] | |
7417 + "") | |
7418 + | |
7419 + | |
7420 +;;; Replace ldb; decb; stb with dec(mem); ldb. If the | |
7421 +;;; register is not needed, then the load will get deleted | |
7422 +;;; automatically, but it may be needed for comparisons. | |
7423 +;;; Same for incb/inc. | |
7424 +(define_peephole2 | |
7425 + [(set (match_operand:QI 0 "register_operand" "") | |
7426 + (match_operand:QI 1 "nonimmediate_operand" "")) | |
7427 + (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1))) | |
7428 + (set (match_dup 1) (match_dup 0))] | |
7429 + "m6809_match_peephole2 (PEEP_MEM_DEC, PEEP_END)" | |
7430 + [(set (match_dup 1) (plus:QI (match_dup 1) (const_int -1))) | |
7431 + (set (match_dup 0) (match_dup 1))] | |
7432 + "") | |
7433 + | |
7434 +(define_peephole2 | |
7435 + [(set (match_operand:QI 0 "register_operand" "") | |
7436 + (match_operand:QI 1 "nonimmediate_operand" "")) | |
7437 + (set (match_dup 0) (plus:QI (match_dup 0) (const_int 1))) | |
7438 + (set (match_dup 1) (match_dup 0))] | |
7439 + "m6809_match_peephole2 (PEEP_MEM_INC, PEEP_END)" | |
7440 + [(set (match_dup 1) (plus:QI (match_dup 1) (const_int 1))) | |
7441 + (set (match_dup 0) (match_dup 1))] | |
7442 + "") | |
7443 + | |
7444 + | |
7445 +;;; Replace "andb #N; cmpb #N; bhi" with "andb #N", if it can be proven | |
7446 +;;; that the branch can never occur because of the limited range of B. | |
7447 +;;; N must be a power of two for this to make sense. This helps with | |
7448 +;;; the default cases of switch statements on a value (x & N). | |
7449 +(define_peephole2 | |
7450 + [(set (match_operand:QI 0 "register_operand" "") | |
7451 + (and:QI (match_dup 0) (match_operand:QI 1 "immediate_operand" ""))) | |
7452 + (set (cc0) | |
7453 + (compare (match_dup 0) (match_dup 1))) | |
7454 + (set (pc) (if_then_else (gtu (cc0) (const_int 0)) (match_operand 2 "" "") (match_operand 3 "" ""))) | |
7455 + ] | |
7456 + "reload_completed && power_of_two_p (INTVAL (operands[1]) + 1)" | |
7457 + [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))] | |
7458 + "") | |
7459 + | |
7460 +;;; Replace ldd <mem>; addd #1; std <mem> with 16-bit increment | |
7461 +;;; of the mem, but only if D is dead. Same for 16-bit decrement. | |
7462 +;;; <mem> must be offsettable for the instruction to match. | |
7463 +(define_peephole2 | |
7464 + [(set (match_operand:HI 0 "register_operand" "") (match_operand:HI 1 "memory_operand" "")) | |
7465 + (set (match_dup 0) (plus:HI (match_dup 0) (const_int 1))) | |
7466 + (set (match_dup 1) (match_dup 0))] | |
7467 + "reload_completed | |
7468 + && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF | |
7469 + && peep2_reg_dead_p (3, operands[0])" | |
7470 + [(set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))] | |
7471 + "") | |
7472 + | |
7473 +(define_peephole2 | |
7474 + [(set (match_operand:HI 0 "register_operand" "") (match_operand:HI 1 "memory_operand" "")) | |
7475 + (set (match_dup 0) (plus:HI (match_dup 0) (const_int -1))) | |
7476 + (set (match_dup 1) (match_dup 0))] | |
7477 + "reload_completed | |
7478 + && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF | |
7479 + && peep2_reg_dead_p (3, operands[0])" | |
7480 + [(set (match_dup 1) (plus:HI (match_dup 1) (const_int -1)))] | |
7481 + "") | |
7482 + | |
7483 + | |
7484 +;;; Replace a load or store using an indexed register, followed by an increment of that | |
7485 +;;; register, with the combined form using autoincrement. | |
7486 +(define_peephole2 | |
7487 + [(set (match_operand:QI 0 "register_operand" "") | |
7488 + (mem:QI (match_operand:HI 1 "index_register_operand" ""))) | |
7489 + (set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))] | |
7490 + "reload_completed" | |
7491 + [(set (match_dup 0) (mem:QI (post_inc (match_dup 1))))] | |
7492 + "") | |
7493 + | |
7494 + | |
7495 +;;- mode:emacs-lisp | |
7496 +;;- comment-start: ";;- " | |
7497 +;;- eval: (set-syntax-table (copy-sequence (syntax-table))) | |
7498 +;;- eval: (modify-syntax-entry ?[ "(]") | |
7499 +;;- eval: (modify-syntax-entry ?] ")[") | |
7500 +;;- eval: (modify-syntax-entry ?{ "(}") | |
7501 +;;- eval: (modify-syntax-entry ?} "){") | |
7502 +;-; vim: set ts=2: | |
7503 +;-; vim: set expandtab: | |
7504 +;-; vim: set filetype=lisp: | |
7505 +;;- End: | |
7506 diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.opt gcc-4.6.1/gcc/config/m6809/m6809.opt | |
7507 --- gcc-4.6.1-orig/gcc/config/m6809/m6809.opt 1969-12-31 17:00:00.000000000 -0700 | |
7508 +++ gcc-4.6.1/gcc/config/m6809/m6809.opt 2011-09-17 14:06:01.227643616 -0600 | |
7509 @@ -0,0 +1,98 @@ | |
7510 +; Options for the M6809 port of the compiler | |
7511 +; | |
7512 +; Copyright (C) 2005 Free Software Foundation, Inc. | |
7513 +; | |
7514 +; This file is part of GCC. | |
7515 +; | |
7516 +; GCC is free software; you can redistribute it and/or modify it under | |
7517 +; the terms of the GNU General Public License as published by the Free | |
7518 +; Software Foundation; either version 2, or (at your option) any later | |
7519 +; version. | |
7520 +; | |
7521 +; GCC is distributed in the hope that it will be useful, but WITHOUT | |
7522 +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
7523 +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
7524 +; License for more details. | |
7525 +; | |
7526 +; You should have received a copy of the GNU General Public License | |
7527 +; along with GCC; see the file COPYING. If not, write to the Free | |
7528 +; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA | |
7529 +; 02110-1301, USA. | |
7530 + | |
7531 +margcount | |
7532 +Target Mask(ARGCOUNT) | |
7533 +Push argument count | |
7534 + | |
7535 +mint8 | |
7536 +Target RejectNegative Mask(BYTE_INT) | |
7537 +Use 8-bit integers | |
7538 + | |
7539 +mint16 | |
7540 +Target RejectNegative | |
7541 +Use 16-bit integers InverseMask(BYTE_INT) | |
7542 + | |
7543 +mreg-args | |
7544 +Target Mask(REG_ARGS) | |
7545 +Use registers for function arguments | |
7546 + | |
7547 +mshort_size | |
7548 +Target RejectNegative Mask(SMALL_SIZE_T) | |
7549 +Use 8-bit size_t | |
7550 + | |
7551 +mlong_size | |
7552 +Target RejectNegative InverseMask(SMALL_SIZE_T) | |
7553 +Use 16-bit size_t | |
7554 + | |
7555 +mdirect | |
7556 +Target Mask(DIRECT) | |
7557 +Enable direct addressing | |
7558 + | |
7559 +mwpc | |
7560 +Target RejectNegative Mask(WPC) | |
7561 +Enable WPC platform extensions | |
7562 + | |
7563 +mexperiment | |
7564 +Target RejectNegative Mask(EXPERIMENT) | |
7565 +Enable current experimental feature | |
7566 + | |
7567 +m6309 | |
7568 +Target RejectNegative Mask(6309) | |
7569 +Enable Hitachi 6309 extensions | |
7570 + | |
7571 +mcasesi | |
7572 +Target RejectNegative Mask(CASESI) | |
7573 +Enable the casesi pattern | |
7574 + | |
7575 +mfar-code-page= | |
7576 +Target RejectNegative Joined Var(far_code_page_option) | |
7577 +Sets the far code page value for this compilation unit | |
7578 + | |
7579 +mcode-section= | |
7580 +Target RejectNegative Joined Var(code_section_ptr) | |
7581 +Sets the name of the section for code | |
7582 + | |
7583 +mdata-section= | |
7584 +Target RejectNegative Joined Var(data_section_ptr) | |
7585 +Sets the name of the section for initialized data | |
7586 + | |
7587 +mbss-section= | |
7588 +Target RejectNegative Joined Var(bss_section_ptr) | |
7589 +Sets the name of the section for uninitialized data | |
7590 + | |
7591 +mabi_version= | |
7592 +Target RejectNegative Joined Var(m6809_abi_version_ptr) | |
7593 +Sets the calling convention | |
7594 + | |
7595 +msoft-reg-count= | |
7596 +Target RejectNegative Joined Var(m6809_soft_reg_count) | |
7597 +Sets the number of soft registers that can be used | |
7598 + | |
7599 +mdret | |
7600 +Target RejectNegative Mask(DRET) | |
7601 +Put function call results in D, not X | |
7602 + | |
7603 +mfar-stack-param | |
7604 +Target Mask(FAR_STACK_PARAM) | |
7605 +Enable stack parameters to a farcall | |
7606 + | |
7607 + | |
7608 diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809-protos.h gcc-4.6.1/gcc/config/m6809/m6809-protos.h | |
7609 --- gcc-4.6.1-orig/gcc/config/m6809/m6809-protos.h 1969-12-31 17:00:00.000000000 -0700 | |
7610 +++ gcc-4.6.1/gcc/config/m6809/m6809-protos.h 2011-09-17 17:26:19.227644879 -0600 | |
7611 @@ -0,0 +1,94 @@ | |
7612 +/* GCC for 6809 : machine-specific function prototypes | |
7613 + | |
7614 +This file is part of GCC. | |
7615 + | |
7616 +GCC is free software; you can redistribute it and/or modify | |
7617 +it under the terms of the GNU General Public License as published by | |
7618 +the Free Software Foundation; either version 3, or (at your option) | |
7619 +any later version. | |
7620 + | |
7621 +GCC is distributed in the hope that it will be useful, | |
7622 +but WITHOUT ANY WARRANTY; without even the implied warranty of | |
7623 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
7624 +GNU General Public License for more details. | |
7625 + | |
7626 +You should have received a copy of the GNU General Public License | |
7627 +along with GCC; see the file COPYING3. If not see | |
7628 +<http://www.gnu.org/licenses/>. */ | |
7629 + | |
7630 +#ifndef __M6809_PROTOS_H__ | |
7631 +#define __M6809_PROTOS_H__ | |
7632 + | |
7633 +void print_options (FILE *file); | |
7634 +void m6809_cpu_cpp_builtins (void); | |
7635 +void m6809_override_options (void); | |
7636 +void m6809_init_builtins (void); | |
7637 +unsigned int m6809_get_live_regs (void); | |
7638 +const char * m6809_get_regs_printable (unsigned int regs); | |
7639 +unsigned int m6809_get_regs_size (unsigned int regs); | |
7640 +int m6809_function_has_type_attr_p (tree decl, const char *); | |
7641 +int m6809_current_function_has_type_attr_p (const char *); | |
7642 +int prologue_epilogue_required (void); | |
7643 +int noreturn_functionp (rtx x); | |
7644 +void output_function_prologue (FILE *file, int size); | |
7645 +void output_function_epilogue (FILE *file, int size); | |
7646 +int check_float_value (enum machine_mode mode, double *d, int overflow); | |
7647 +void m6809_asm_named_section (const char *name, unsigned int flags, tree decl); | |
7648 +void m6809_asm_file_start (void); | |
7649 +void m6809_output_ascii (FILE *fp, const char *str, unsigned long size); | |
7650 +void m6809_declare_function_name (FILE *asm_out_file, const char *name, tree decl); | |
7651 +void m6809_reorg (void); | |
7652 +int m6809_current_function_is_void (void); | |
7653 +int m6809_can_merge_pushpop_p (int op, int regs1, int regs2); | |
7654 +int m6809_function_value_regno_p (unsigned int regno); | |
7655 +void emit_prologue_insns (void); | |
7656 +void emit_epilogue_insns (bool); | |
7657 +void m6809_conditional_register_usage (void); | |
7658 +void m6809_output_quoted_string (FILE *asm_file, const char *string); | |
7659 +int m6809_match_peephole2 (unsigned int peephole_id, unsigned int stage); | |
7660 +int m6809_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode); | |
7661 +int power_of_two_p (unsigned int n); | |
7662 +void m6809_do_casesi (rtx index, rtx lower_bound, rtx range, rtx table_label, rtx default_label); | |
7663 +void m6809_output_addsi3 (int rtx_code, rtx *operands); | |
7664 +rtx m6809_function_arg_on_stack (CUMULATIVE_ARGS *cump); | |
7665 +void expand_constant_shift (int code, rtx dst, rtx src, rtx count); | |
7666 +int m6809_single_operand_operator (rtx exp); | |
7667 + | |
7668 +#ifdef TREE_CODE | |
7669 +int m6809_init_cumulative_args (CUMULATIVE_ARGS cum, tree fntype, rtx libname); | |
7670 +#endif /* TREE_CODE */ | |
7671 + | |
7672 +#ifdef RTX_CODE | |
7673 +void print_direct_prefix (FILE *file, rtx addr); | |
7674 +void print_operand (FILE *file, rtx x, int code); | |
7675 +void print_operand_address (FILE *file, rtx addr); | |
7676 +void notice_update_cc (rtx exp, rtx insn); | |
7677 +enum reg_class m6809_preferred_reload_class (rtx x, enum reg_class regclass); | |
7678 +rtx gen_rtx_const_high (rtx r); | |
7679 +rtx gen_rtx_const_low (rtx r); | |
7680 +rtx gen_rtx_register_pushpop (int pop_flag, int regs); | |
7681 +void emit_libcall_insns (enum machine_mode mode, const char *name, rtx *operands, int count); | |
7682 +const char * output_branch_insn (enum rtx_code code, rtx *operands, int length); | |
7683 +void output_far_call_insn (rtx *operands, int has_return); | |
7684 +void m6809_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt); | |
7685 +rtx m6809_expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, int ignore); | |
7686 +const char * far_functionp (rtx x); | |
7687 +rtx m6809_function_value (const tree valtype, const tree func); | |
7688 +void m6809_output_shift_insn (int rtx_code, rtx *operands); | |
7689 + | |
7690 +const char * m6809_get_decl_bank (tree decl); | |
7691 +void output_branch_insn1 (const char *opcode, rtx *operands, int long_p); | |
7692 +rtx m6809_builtin_operand (tree arglist, enum machine_mode mode, int opnum); | |
7693 +const char * far_function_type_p (tree type); | |
7694 +void m6809_asm_trampoline_template(FILE *f); | |
7695 +bool m6809_frame_pointer_required (void); | |
7696 +int m6809_can_eliminate (int from, int to); | |
7697 +int m6809_initial_elimination_offset (int from, int to); | |
7698 +void m6809_emit_move_insn (rtx dst, rtx src); | |
7699 +void m6809_split_shift (enum rtx_code code, rtx *operands); | |
7700 +bool m6809_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED); | |
7701 + | |
7702 + | |
7703 +#endif /* RTX_CODE */ | |
7704 + | |
7705 +#endif /* __M6809_PROTOS_H__ */ | |
7706 diff -urN gcc-4.6.1-orig/gcc/config/m6809/predicates.md gcc-4.6.1/gcc/config/m6809/predicates.md | |
7707 --- gcc-4.6.1-orig/gcc/config/m6809/predicates.md 1969-12-31 17:00:00.000000000 -0700 | |
7708 +++ gcc-4.6.1/gcc/config/m6809/predicates.md 2011-09-18 15:09:37.057653095 -0600 | |
7709 @@ -0,0 +1,78 @@ | |
7710 +;; Predicate definitions for Motorola 6809 | |
7711 +;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. | |
7712 +;; | |
7713 +;; This file is part of GCC. | |
7714 +;; | |
7715 +;; GCC is free software; you can redistribute it and/or modify | |
7716 +;; it under the terms of the GNU General Public License as published by | |
7717 +;; the Free Software Foundation; either version 3, or (at your option) | |
7718 +;; any later version. | |
7719 +;; | |
7720 +;; GCC is distributed in the hope that it will be useful, | |
7721 +;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
7722 +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
7723 +;; GNU General Public License for more details. | |
7724 +;; | |
7725 +;; You should have received a copy of the GNU General Public License | |
7726 +;; along with GCC; see the file COPYING3. If not see | |
7727 +;; <http://www.gnu.org/licenses/>. | |
7728 + | |
7729 +;; whole_register_operand is like register_operand, but it | |
7730 +;; does not allow SUBREGs. | |
7731 +(define_predicate "whole_register_operand" | |
7732 + (and (match_code "reg") | |
7733 + (match_operand 0 "register_operand"))) | |
7734 + | |
7735 + | |
7736 +;; A predicate that matches any index register. This can be used in nameless | |
7737 +;; patterns and peepholes which need a 16-bit reg, but not D. | |
7738 +(define_predicate "index_register_operand" | |
7739 + (and (match_code "reg") | |
7740 + (match_test "REGNO (op) == HARD_X_REGNUM || REGNO (op) == HARD_Y_REGNUM || REGNO (op) == HARD_U_REGNUM"))) | |
7741 + | |
7742 + | |
7743 +;; match only X | |
7744 +(define_predicate "register_operand_x" | |
7745 + (and (match_code "reg") | |
7746 + (match_test "REGNO (op) == HARD_X_REGNUM"))) | |
7747 + | |
7748 +;; match only D | |
7749 +(define_predicate "register_operand_d" | |
7750 + (and (match_code "reg") | |
7751 + (match_test "REGNO (op) == HARD_D_REGNUM"))) | |
7752 + | |
7753 + | |
7754 +;; Likwise, a replacement for general_operand which excludes | |
7755 +;; SUBREGs. | |
7756 +(define_predicate "whole_general_operand" | |
7757 + (and (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem") | |
7758 + (match_operand 0 "general_operand"))) | |
7759 + | |
7760 + | |
7761 +(define_predicate "add_general_operand" | |
7762 + (and (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem") | |
7763 + (match_operand 0 "general_operand") | |
7764 + (match_test "REGNO (op) != SOFT_AP_REGNUM"))) | |
7765 + | |
7766 + | |
7767 +(define_predicate "shift_count_operand" | |
7768 + (and (match_code "const_int") | |
7769 + (and (match_operand 0 "const_int_operand") | |
7770 + (match_test "INTVAL (op) == 1 || INTVAL (op) == 8")))) | |
7771 + | |
7772 + | |
7773 +;; A predicate that matches any bitwise logical operator. This | |
7774 +;; allows for a single RTL pattern to be used for multiple operations. | |
7775 +(define_predicate "logical_bit_operator" | |
7776 + (ior (match_code "and") (match_code "ior") (match_code "xor"))) | |
7777 + | |
7778 + | |
7779 +;; A predicate that matches any shift or rotate operator. This | |
7780 +;; allows for a single RTL pattern to be used for multiple operations. | |
7781 +(define_predicate "shift_rotate_operator" | |
7782 + (ior (match_code "ashift") (match_code "ashiftrt") (match_code "lshiftrt") | |
7783 + (match_code "rotate") (match_code "rotatert"))) | |
7784 + | |
7785 + | |
7786 +(define_predicate "symbolic_operand" (match_code "symbol_ref")) | |
7787 + | |
7788 diff -urN gcc-4.6.1-orig/gcc/config/m6809/t-coco gcc-4.6.1/gcc/config/m6809/t-coco | |
7789 --- gcc-4.6.1-orig/gcc/config/m6809/t-coco 1969-12-31 17:00:00.000000000 -0700 | |
7790 +++ gcc-4.6.1/gcc/config/m6809/t-coco 2011-09-17 14:06:01.227643616 -0600 | |
7791 @@ -0,0 +1,6 @@ | |
7792 +# For a few minor differences in code generation on the CoCo... | |
7793 +T_CFLAGS = -DTARGET_COCO | |
7794 + | |
7795 +# For doing the startup differently on the CoCo... | |
7796 +CRT0STUFF_T_CFLAGS += -Wa,--globalize-symbols -DTARGET_COCO | |
7797 +# vim: set filetype=make: | |
7798 diff -urN gcc-4.6.1-orig/gcc/config/m6809/t-m6809 gcc-4.6.1/gcc/config/m6809/t-m6809 | |
7799 --- gcc-4.6.1-orig/gcc/config/m6809/t-m6809 1969-12-31 17:00:00.000000000 -0700 | |
7800 +++ gcc-4.6.1/gcc/config/m6809/t-m6809 2011-09-17 21:38:35.437646470 -0600 | |
7801 @@ -0,0 +1,64 @@ | |
7802 + | |
7803 +# ranlib doesn't exist, so define it to 'true' to make it a no-op | |
7804 +RANLIB_FOR_TARGET = true | |
7805 + | |
7806 +# Stubs for libgcc defined by m6809 are here | |
7807 +LIB1ASMSRC = m6809/libgcc1.s | |
7808 + | |
7809 +# Here are the functions that are implemented within libgcc1.s | |
7810 +LIB1ASMFUNCS = _mulhi3 _divhi3 _modhi3 _udivhi3 _umodhi3 \ | |
7811 + _euclid _seuclid _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _softregs \ | |
7812 + _ashlhi3 _ashrhi3 _lshrhi3 | |
7813 + | |
7814 +# Flags to use when building libgcc. IN_GCC does not seem necessary, | |
7815 +# although the compile breaks without it. -DDF=SF is required to set | |
7816 +# the size of "double" to the same as the size of a "float". | |
7817 +TARGET_LIBGCC2_CFLAGS =-DIN_GCC -Dinhibit_libc -DDF=SF -DLIBGCC2_HAS_SF_MODE=0 -DLIBGCC2_HAS_DF_MODE=0 | |
7818 + | |
7819 +LIB2ADDEH = | |
7820 +LIB2ADDEHSTATIC = | |
7821 +LIB2ADDEHSHARED = | |
7822 + | |
7823 +LIBGCC2_DEBUG_CFLAGS = | |
7824 +LIBGCC2_CFLAGS = -Os $(LIBGCC2_INCLUDES) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2 | |
7825 + | |
7826 +# Multilib information | |
7827 +# This creates multiple versions of libgcc.a for each set of incompatible | |
7828 +# -mxxx options. | |
7829 +MULTILIB_OPTIONS = fpic mdret | |
7830 +MULTILIB_DIRNAMES = | |
7831 +MULTILIB_MATCHES = | |
7832 +MULTILIB_EXCEPTIONS = | |
7833 +EXTRA_MULTILIB_PARTS = crt0.o | |
7834 + | |
7835 +LIBGCC = stmp-multilib | |
7836 +INSTALL_LIBGCC = install-multilib | |
7837 + | |
7838 +# We want fine grained libraries, so use the new code to build the | |
7839 +# floating point emulation libraries. | |
7840 +FPBIT = fp-bit.c | |
7841 + | |
7842 +fp-bit.c: $(srcdir)/config/fp-bit.c | |
7843 + echo '#define FLOAT' > fp-bit.c | |
7844 + echo '#define FLOAT_ONLY' >> fp-bit.c | |
7845 + echo '#define CMPtype HItype' >> fp-bit.c | |
7846 + echo '#define SMALL_MACHINE' >> fp-bit.c | |
7847 + echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c | |
7848 + echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c | |
7849 + echo '#endif' >> fp-bit.c | |
7850 + echo '#define DI SI' >> fp-bit.c | |
7851 + cat $(srcdir)/config/fp-bit.c >> fp-bit.c | |
7852 + | |
7853 +# crt0.o is built from the following source file | |
7854 +CRT0_S = $(srcdir)/config/m6809/crt0.S | |
7855 +MCRT0_S = $(srcdir)/config/m6809/crt0.S | |
7856 + | |
7857 +# Flags to use when building crt0.o | |
7858 +CRT0STUFF_T_CFLAGS += -fno-builtin -nostartfiles -nostdlib | |
7859 + | |
7860 +# Assemble startup files. | |
7861 +$(T)crt0.o: $(CRT0_S) $(GCC_PASSES) | |
7862 + $(GCC_FOR_TARGET) $(CRT0STUFF_T_CFLAGS) $(MULTILIB_CFLAGS) -c -o $(T)crt0.o -x assembler-with-cpp $(CRT0_S) | |
7863 + | |
7864 +$(T)mcrt0.o: $(MCRT0_S) $(GCC_PASSES) | |
7865 + $(GCC_FOR_TARGET) $(CRT0STUFF_T_CFLAGS) $(MULTILIB_CFLAGS) -c -o $(T)mcrt0.o -x assembler-with-cpp $(MCRT0_S) | |
7866 diff -urN gcc-4.6.1-orig/gcc/config/m6809/t-sim gcc-4.6.1/gcc/config/m6809/t-sim | |
7867 --- gcc-4.6.1-orig/gcc/config/m6809/t-sim 1969-12-31 17:00:00.000000000 -0700 | |
7868 +++ gcc-4.6.1/gcc/config/m6809/t-sim 2011-09-17 14:06:01.227643616 -0600 | |
7869 @@ -0,0 +1 @@ | |
7870 +CRT0STUFF_T_CFLAGS += -DTARGET_SIM | |
7871 diff -urN gcc-4.6.1-orig/gcc/config.gcc gcc-4.6.1/gcc/config.gcc | |
7872 --- gcc-4.6.1-orig/gcc/config.gcc 2011-05-22 14:03:43.000000000 -0600 | |
7873 +++ gcc-4.6.1/gcc/config.gcc 2011-09-17 14:08:56.257643636 -0600 | |
7874 @@ -374,6 +374,9 @@ | |
7875 cpu_type=m32r | |
7876 extra_options="${extra_options} g.opt" | |
7877 ;; | |
7878 +m6809-*-*) | |
7879 + cpu_type=m6809 | |
7880 + ;; | |
7881 m68k-*-*) | |
7882 extra_headers=math-68881.h | |
7883 ;; | |
7884 @@ -1689,6 +1692,12 @@ | |
7885 thread_file='posix' | |
7886 fi | |
7887 ;; | |
7888 +m6809-coco-*) | |
7889 + tmake_file="${tmake_file} m6809/t-m6809 m6809/t-coco" | |
7890 + ;; | |
7891 +m6809-*-*) | |
7892 + tmake_file="${tmake_file} m6809/t-m6809 m6809/t-sim" | |
7893 + ;; | |
7894 # m68hc11 and m68hc12 share the same machine description. | |
7895 m68hc11-*-*|m6811-*-*) | |
7896 tm_file="dbxelf.h elfos.h usegas.h newlib-stdint.h m68hc11/m68hc11.h" | |
7897 diff -urN gcc-4.6.1-orig/gcc/gcse.c gcc-4.6.1/gcc/gcse.c | |
7898 --- gcc-4.6.1-orig/gcc/gcse.c 2011-02-02 23:04:04.000000000 -0700 | |
7899 +++ gcc-4.6.1/gcc/gcse.c 2011-09-18 17:25:17.527653952 -0600 | |
7900 @@ -833,7 +833,6 @@ | |
7901 max_distance = (GCSE_COST_DISTANCE_RATIO * cost) / 10; | |
7902 if (max_distance == 0) | |
7903 return 0; | |
7904 - | |
7905 gcc_assert (max_distance > 0); | |
7906 } | |
7907 else | |
7908 diff -urN gcc-4.6.1-orig/gcc/libgcc2.c gcc-4.6.1/gcc/libgcc2.c | |
7909 --- gcc-4.6.1-orig/gcc/libgcc2.c 2011-01-03 13:52:22.000000000 -0700 | |
7910 +++ gcc-4.6.1/gcc/libgcc2.c 2011-09-17 14:06:01.227643616 -0600 | |
7911 @@ -485,6 +485,7 @@ | |
7912 #endif | |
7913 | |
7914 #ifdef L_bswapsi2 | |
7915 +#if MIN_UNITS_PER_WORD > 1 | |
7916 SItype | |
7917 __bswapsi2 (SItype u) | |
7918 { | |
7919 @@ -494,7 +495,9 @@ | |
7920 | (((u) & 0x000000ff) << 24)); | |
7921 } | |
7922 #endif | |
7923 +#endif | |
7924 #ifdef L_bswapdi2 | |
7925 +#if LONG_LONG_TYPE_SIZE > 32 | |
7926 DItype | |
7927 __bswapdi2 (DItype u) | |
7928 { | |
7929 @@ -508,6 +511,7 @@ | |
7930 | (((u) & 0x00000000000000ffull) << 56)); | |
7931 } | |
7932 #endif | |
7933 +#endif | |
7934 #ifdef L_ffssi2 | |
7935 #undef int | |
7936 int | |
7937 @@ -1280,7 +1284,7 @@ | |
7938 UDWtype | |
7939 __fixunssfDI (SFtype a) | |
7940 { | |
7941 -#if LIBGCC2_HAS_DF_MODE | |
7942 +#if LIBGCC2_HAS_DF_MODE || (FLT_MANT_DIG >= W_TYPE_SIZE) | |
7943 /* Convert the SFtype to a DFtype, because that is surely not going | |
7944 to lose any bits. Some day someone else can write a faster version | |
7945 that avoids converting to DFtype, and verify it really works right. */ | |
7946 @@ -1298,7 +1302,7 @@ | |
7947 | |
7948 /* Assemble result from the two parts. */ | |
7949 return ((UDWtype) hi << W_TYPE_SIZE) | lo; | |
7950 -#elif FLT_MANT_DIG < W_TYPE_SIZE | |
7951 +#else | |
7952 if (a < 1) | |
7953 return 0; | |
7954 if (a < Wtype_MAXp1_F) | |
7955 @@ -1334,8 +1338,6 @@ | |
7956 return (DWtype)counter << shift; | |
7957 } | |
7958 return -1; | |
7959 -#else | |
7960 -# error | |
7961 #endif | |
7962 } | |
7963 #endif | |
7964 diff -urN gcc-4.6.1-orig/gcc/longlong.h gcc-4.6.1/gcc/longlong.h | |
7965 --- gcc-4.6.1-orig/gcc/longlong.h 2011-06-06 08:34:54.000000000 -0600 | |
7966 +++ gcc-4.6.1/gcc/longlong.h 2011-09-17 14:06:01.227643616 -0600 | |
7967 @@ -527,6 +527,11 @@ | |
7968 : "cbit") | |
7969 #endif /* __M32R__ */ | |
7970 | |
7971 +#if defined (__m6309__) || defined (__m6809__) | |
7972 +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) | |
7973 +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctz (X)) | |
7974 +#endif | |
7975 + | |
7976 #if defined (__mc68000__) && W_TYPE_SIZE == 32 | |
7977 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ | |
7978 __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ | |
7979 diff -urN gcc-4.6.1-orig/gcc/Makefile.in gcc-4.6.1/gcc/Makefile.in | |
7980 --- gcc-4.6.1-orig/gcc/Makefile.in 2011-05-23 12:12:34.000000000 -0600 | |
7981 +++ gcc-4.6.1/gcc/Makefile.in 2011-09-17 14:06:01.197643616 -0600 | |
7982 @@ -1987,14 +1987,14 @@ | |
7983 | |
7984 # Compile the start modules crt0.o and mcrt0.o that are linked with | |
7985 # every program | |
7986 -$(T)crt0.o: s-crt0 ; @true | |
7987 -$(T)mcrt0.o: s-crt0; @true | |
7988 +crt0.o: s-crt0 ; @true | |
7989 +mcrt0.o: s-crt0; @true | |
7990 | |
7991 s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H) | |
7992 $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \ | |
7993 - -o $(T)crt0.o -c $(CRT0_S) | |
7994 + -o crt0.o -c $(CRT0_S) | |
7995 $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \ | |
7996 - -o $(T)mcrt0.o -c $(MCRT0_S) | |
7997 + -o mcrt0.o -c $(MCRT0_S) | |
7998 $(STAMP) s-crt0 | |
7999 # | |
8000 # Compiling object files from source files. | |
8001 diff -urN gcc-4.6.1-orig/gcc/opth-gen.awk gcc-4.6.1/gcc/opth-gen.awk | |
8002 --- gcc-4.6.1-orig/gcc/opth-gen.awk 2011-02-08 10:41:00.000000000 -0700 | |
8003 +++ gcc-4.6.1/gcc/opth-gen.awk 2011-09-17 14:06:01.227643616 -0600 | |
8004 @@ -121,7 +121,7 @@ | |
8005 END { | |
8006 print "/* This file is auto-generated by opth-gen.awk. */" | |
8007 print "" | |
8008 -print "#ifndef OPTIONS_H" | |
8009 +print "#if !defined(OPTIONS_H) && !defined(IN_LIBGCC2)" | |
8010 print "#define OPTIONS_H" | |
8011 print "" | |
8012 print "#include \"flag-types.h\"" | |
8013 @@ -432,18 +432,9 @@ | |
8014 | |
8015 for (i = 0; i < n_opts; i++) { | |
8016 opt = opt_args("InverseMask", flags[i]) | |
8017 - if (opt ~ ",") { | |
8018 - vname = var_name(flags[i]) | |
8019 - macro = "OPTION_" | |
8020 - mask = "OPTION_MASK_" | |
8021 - if (vname == "") { | |
8022 - vname = "target_flags" | |
8023 - macro = "TARGET_" | |
8024 - mask = "MASK_" | |
8025 - } | |
8026 - print "#define " macro nth_arg(1, opt) \ | |
8027 - " ((" vname " & " mask nth_arg(0, opt) ") == 0)" | |
8028 - } | |
8029 + if (opt ~ ",") | |
8030 + print "#define TARGET_" nth_arg(1, opt) \ | |
8031 + " ((target_flags & MASK_" nth_arg(0, opt) ") == 0)" | |
8032 } | |
8033 print "" | |
8034 | |
8035 diff -urN gcc-4.6.1-orig/gcc/tree.h gcc-4.6.1/gcc/tree.h | |
8036 --- gcc-4.6.1-orig/gcc/tree.h 2011-06-14 09:28:21.000000000 -0600 | |
8037 +++ gcc-4.6.1/gcc/tree.h 2011-09-17 20:28:05.987646026 -0600 | |
8038 @@ -3563,6 +3563,8 @@ | |
8039 TI_UINTDI_TYPE, | |
8040 TI_UINTTI_TYPE, | |
8041 | |
8042 + TI_UINT8_TYPE, | |
8043 + TI_UINT16_TYPE, | |
8044 TI_UINT32_TYPE, | |
8045 TI_UINT64_TYPE, | |
8046 | |
8047 diff -urN gcc-4.6.1-orig/gcc/version.c gcc-4.6.1/gcc/version.c | |
8048 --- gcc-4.6.1-orig/gcc/version.c 2009-04-21 13:03:23.000000000 -0600 | |
8049 +++ gcc-4.6.1/gcc/version.c 2011-09-18 19:49:48.437654863 -0600 | |
8050 @@ -21,16 +21,16 @@ | |
8051 | |
8052 /* This is the location of the online document giving instructions for | |
8053 reporting bugs. If you distribute a modified version of GCC, | |
8054 - please configure with --with-bugurl pointing to a document giving | |
8055 - instructions for reporting bugs to you, not us. (You are of course | |
8056 - welcome to forward us bugs reported to you, if you determine that | |
8057 - they are not bugs in your modifications.) */ | |
8058 + please change this to refer to a document giving instructions for | |
8059 + reporting bugs to you, not us. (You are of course welcome to | |
8060 + forward us bugs reported to you, if you determine that they are | |
8061 + not bugs in your modifications.) */ | |
8062 | |
8063 -const char bug_report_url[] = BUGURL; | |
8064 +const char bug_report_url[] = "<URL:http://lost.l-w.ca/coco/lwtools/>"; | |
8065 | |
8066 /* The complete version string, assembled from several pieces. | |
8067 BASEVER, DATESTAMP, DEVPHASE, and REVISION are defined by the | |
8068 Makefile. */ | |
8069 | |
8070 -const char version_string[] = BASEVER DATESTAMP DEVPHASE REVISION; | |
8071 +const char version_string[] = BASEVER DATESTAMP DEVPHASE REVISION " (gcc6809lw)"; | |
8072 const char pkgversion_string[] = PKGVERSION; | |
8073 diff -urN gcc-4.6.1-orig/libgcc/config.host gcc-4.6.1/libgcc/config.host | |
8074 --- gcc-4.6.1-orig/libgcc/config.host 2011-03-14 00:06:23.000000000 -0600 | |
8075 +++ gcc-4.6.1/libgcc/config.host 2011-09-17 14:06:01.257643616 -0600 | |
8076 @@ -380,6 +380,8 @@ | |
8077 ;; | |
8078 m32rle-*-linux*) | |
8079 ;; | |
8080 +m6809*) | |
8081 + ;; | |
8082 m68hc11-*-*|m6811-*-*) | |
8083 ;; | |
8084 m68hc12-*-*|m6812-*-*) | |
8085 diff -urN gcc-4.6.1-orig/libgcc/fixed-obj.mk gcc-4.6.1/libgcc/fixed-obj.mk | |
8086 --- gcc-4.6.1-orig/libgcc/fixed-obj.mk 2007-09-17 16:18:13.000000000 -0600 | |
8087 +++ gcc-4.6.1/libgcc/fixed-obj.mk 2011-09-17 14:06:01.257643616 -0600 | |
8088 @@ -23,7 +23,7 @@ | |
8089 #$(info $o$(objext): -DL$($o-label) $($o-opt)) | |
8090 | |
8091 $o$(objext): %$(objext): $(gcc_srcdir)/config/fixed-bit.c | |
8092 - $(gcc_compile) -DL$($*-label) $($*-opt) -c $(gcc_srcdir)/config/fixed-bit.c $(vis_hide) | |
8093 + $(gcc_compile) -DL$($*-label) $($*-opt) -c $(gcc_srcdir)/config/fixed-bit.c $(vis_hide) -save-temps | |
8094 | |
8095 ifeq ($(enable_shared),yes) | |
8096 $(o)_s$(objext): %_s$(objext): $(gcc_srcdir)/config/fixed-bit.c | |
8097 diff -urN gcc-4.6.1-orig/libgcc/Makefile.in gcc-4.6.1/libgcc/Makefile.in | |
8098 --- gcc-4.6.1-orig/libgcc/Makefile.in 2011-01-25 21:19:58.000000000 -0700 | |
8099 +++ gcc-4.6.1/libgcc/Makefile.in 2011-09-17 14:06:01.257643616 -0600 | |
8100 @@ -374,8 +374,8 @@ | |
8101 # Build lib2funcs. For the static library also include LIB2FUNCS_ST. | |
8102 lib2funcs-o = $(patsubst %,%$(objext),$(lib2funcs) $(LIB2FUNCS_ST)) | |
8103 $(lib2funcs-o): %$(objext): $(gcc_srcdir)/libgcc2.c | |
8104 - $(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \ | |
8105 - $(vis_hide) | |
8106 + ln -sf $(gcc_srcdir)/libgcc2.c $*.c && \ | |
8107 + $(gcc_compile) -DL$* -c $*.c $(vis_hide) -save-temps | |
8108 libgcc-objects += $(lib2funcs-o) | |
8109 | |
8110 ifeq ($(enable_shared),yes) | |
8111 @@ -410,8 +410,9 @@ | |
8112 # Build LIB2_DIVMOD_FUNCS. | |
8113 lib2-divmod-o = $(patsubst %,%$(objext),$(LIB2_DIVMOD_FUNCS)) | |
8114 $(lib2-divmod-o): %$(objext): $(gcc_srcdir)/libgcc2.c | |
8115 - $(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \ | |
8116 - -fexceptions -fnon-call-exceptions $(vis_hide) | |
8117 + ln -sf $(gcc_srcdir)/libgcc2.c $*.c && \ | |
8118 + $(gcc_compile) -DL$* -c $*.c \ | |
8119 + -fexceptions -fnon-call-exceptions $(vis_hide) -save-temps | |
8120 libgcc-objects += $(lib2-divmod-o) | |
8121 | |
8122 ifeq ($(enable_shared),yes) | |
8123 @@ -443,7 +444,8 @@ | |
8124 ifneq ($(FPBIT),) | |
8125 fpbit-o = $(patsubst %,%$(objext),$(FPBIT_FUNCS)) | |
8126 $(fpbit-o): %$(objext): $(FPBIT) | |
8127 - $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(FPBIT) $(vis_hide) | |
8128 + ln -sf $(FPBIT) $*.c && \ | |
8129 + $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $*.c $(vis_hide) -save-temps | |
8130 libgcc-objects += $(fpbit-o) | |
8131 | |
8132 ifeq ($(enable_shared),yes) | |
8133 @@ -458,7 +460,8 @@ | |
8134 ifneq ($(DPBIT),) | |
8135 dpbit-o = $(patsubst %,%$(objext),$(DPBIT_FUNCS)) | |
8136 $(dpbit-o): %$(objext): $(DPBIT) | |
8137 - $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(DPBIT) $(vis_hide) | |
8138 + ln -sf $(DPBIT) $*.c && \ | |
8139 + $(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $*.c $(vis_hide) -save-temps | |
8140 libgcc-objects += $(dpbit-o) | |
8141 | |
8142 ifeq ($(enable_shared),yes) | |
8143 diff -urN gcc-4.6.1-orig/README.LW gcc-4.6.1/README.LW | |
8144 --- gcc-4.6.1-orig/README.LW 1969-12-31 17:00:00.000000000 -0700 | |
8145 +++ gcc-4.6.1/README.LW 2011-09-18 19:44:52.457654831 -0600 | |
8146 @@ -0,0 +1,14 @@ | |
8147 +This is a port of gcc6809 which is designed to work with the lwtools | |
8148 +cross-assembler and linker package. You will need several scripts from that | |
8149 +package, available at http://lost.l-w.ca/coco/lwtools/, in order to use | |
8150 +this. Instructions for building are present in the lwtools package. | |
8151 + | |
8152 +This work is based extensively on the gcc6809 4.3.4-3 release by Brian | |
8153 +Dominy (brian@oddchange.com) with some significant renovations to make it | |
8154 +work with gcc 4.6.1. | |
8155 + | |
8156 +There is no guarantee that it will work for any particular purpose you | |
8157 +choose to put it to. | |
8158 + | |
8159 +If you run into any problems, contact William Astle (lost@l-w.ca). DO NOT | |
8160 +contact the main GCC developers! |