changeset 182:e0cc66fd0551

Added gcc6809lw patch to extras
author lost@l-w.ca
date Wed, 21 Sep 2011 21:14:09 -0600
parents 5350ce9f446f
children c6a38fd8bd33
files extra/README extra/gcc6809lw-4.6.1-1.patch
diffstat 2 files changed, 8175 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/extra/README	Sat Sep 17 11:45:13 2011 -0600
+++ b/extra/README	Wed Sep 21 21:14:09 2011 -0600
@@ -4,12 +4,8 @@
 as
 
 This is a sort of front-end script that makes lwasm look approximately like
-gnu as which is useful for using lwasm as a backend to gcc. You will
-probably need to edit it to make it work fully. Simply put this in place
-of whatever gcc6809 installed for "as" (in the "m6809/bin" folder in
-"--prefix") after editing it to point to the real location of the "lwasm"
-binary.
-
+gnu as which is useful for using lwasm as a backend to gcc.  You may need to
+edit it to make it work fully.
 
 ld
 
@@ -20,13 +16,23 @@
 
 Similar to the "as" script above except for lwar.
 
+gcc6809lw-4.6.1-1.patch
+
+These are patches to the main gcc source distribution for specific releases. 
+The last number after the dash is a patch level for the specific patch. 
+These are different to the official gcc6809 releases in the following ways. 
+First, all the source for as-6809 is removed.  Also, the special "helper"
+makefile and directory is removed.  Also, as of this writing, the
+distribution side for gcc6809 has been down for months and the latest
+release was for gcc 4.3.4 which does not build on 64 bit linux.
+
 
 To use these scripts, you really need to understand how to build a gcc as a
 cross compiler. The basics are that you put the as, ld, and ar scripts
 whereever you plan to put your cross-development binaries. Then, when
 building the cross compiler, you tell it where the scripts are.
 
-The following worked with gcc6809 4.3.4-3:
+The following work
 
 1. Install the ar, as, and ld scripts named m6809-unknown-{as,ar,ld} in a
 directory in your path, say /usr/local/coco/bin/.
@@ -34,7 +40,8 @@
 2. Make symbolic links to /bin/true for similarly named nm, objdump, ranlib,
 and strip in the same directory  Some of these may not be necessary.
 
-3. Unpack gcc and apply the gcc6809 patch.
+3. Unpack gcc and apply the gcc6809 patch. The gcc6809lw* patch file
+in this directory is known to work with these instructions.
 
 4. Make sure /usr/local/coco/bin is in your PATH
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/gcc6809lw-4.6.1-1.patch	Wed Sep 21 21:14:09 2011 -0600
@@ -0,0 +1,8160 @@
+diff -urN gcc-4.6.1-orig/config.sub gcc-4.6.1/config.sub
+--- gcc-4.6.1-orig/config.sub	2010-05-25 07:22:07.000000000 -0600
++++ gcc-4.6.1/config.sub	2011-09-17 14:07:51.597643628 -0600
+@@ -313,7 +313,7 @@
+ 	c6x)
+ 		basic_machine=tic6x-unknown
+ 		;;
+-	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
++	m6809 | m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+ 		# Motorola 68HC11/12.
+ 		basic_machine=$basic_machine-unknown
+ 		os=-none
+@@ -354,7 +354,7 @@
+ 	| i*86-* | i860-* | i960-* | ia64-* \
+ 	| ip2k-* | iq2000-* \
+ 	| lm32-* \
+-	| m32c-* | m32r-* | m32rle-* \
++	| m32c-* | m32r-* | m32rle-* | m6809-* \
+ 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ 	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+ 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+@@ -509,6 +509,10 @@
+ 		basic_machine=arm-unknown
+ 		os=-cegcc
+ 		;;
++	coco)
++		basic_machine=coco
++		os=-none
++		;;
+ 	convex-c1)
+ 		basic_machine=c1-convex
+ 		os=-bsd
+diff -urN gcc-4.6.1-orig/configure gcc-4.6.1/configure
+--- gcc-4.6.1-orig/configure	2011-03-16 12:27:36.000000000 -0600
++++ gcc-4.6.1/configure	2011-09-17 14:06:01.187643616 -0600
+@@ -3441,6 +3441,9 @@
+   m32r-*-*)
+     noconfigdirs="$noconfigdirs ${libgcj}"
+     ;;
++  m6809*)
++    noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 target-libgloss ${libgcj}"
++    ;;
+   m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*)
+     noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
+     libgloss_dir=m68hc11
+diff -urN gcc-4.6.1-orig/configure.ac gcc-4.6.1/configure.ac
+--- gcc-4.6.1-orig/configure.ac	2011-03-16 12:27:36.000000000 -0600
++++ gcc-4.6.1/configure.ac	2011-09-17 14:06:01.187643616 -0600
+@@ -887,6 +887,9 @@
+   m32r-*-*)
+     noconfigdirs="$noconfigdirs ${libgcj}"
+     ;;
++  m6809*)
++    noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 target-libgloss ${libgcj}"
++    ;;
+   m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*)
+     noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
+     libgloss_dir=m68hc11
+diff -urN gcc-4.6.1-orig/gcc/calls.c gcc-4.6.1/gcc/calls.c
+--- gcc-4.6.1-orig/gcc/calls.c	2011-06-06 05:46:14.000000000 -0600
++++ gcc-4.6.1/gcc/calls.c	2011-09-17 14:06:01.217643616 -0600
+@@ -2434,7 +2434,7 @@
+ 	 call sequence.
+ 	 Also do the adjustments before a throwing call, otherwise
+ 	 exception handling can fail; PR 19225. */
+-      if (pending_stack_adjust >= 32
++      if (pending_stack_adjust >= 8
+ 	  || (pending_stack_adjust > 0
+ 	      && (flags & ECF_MAY_BE_ALLOCA))
+ 	  || (pending_stack_adjust > 0
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/crt0.S gcc-4.6.1/gcc/config/m6809/crt0.S
+--- gcc-4.6.1-orig/gcc/config/m6809/crt0.S	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/crt0.S	2011-09-17 14:06:01.227643616 -0600
+@@ -0,0 +1,180 @@
++;;;
++;;; Copyright 2006, 2007, 2008, 2009 by Brian Dominy <brian@oddchange.com>
++;;;
++;;; This file is part of GCC.
++;;;
++;;; GCC is free software; you can redistribute it and/or modify
++;;; it under the terms of the GNU General Public License as published by
++;;; the Free Software Foundation; either version 3, or (at your option)
++;;; any later version.
++;;;
++;;; GCC is distributed in the hope that it will be useful,
++;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
++;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++;;; GNU General Public License for more details.
++
++;;; You should have received a copy of the GNU General Public License
++;;; along with GCC; see the file COPYING3.  If not see
++;;; <http://www.gnu.org/licenses/>.
++
++	/* Declare external for main() */
++	.globl _main
++
++
++/* The startup is heavily dependent on the type of machine and
++OS environment that is available at the start point.
++For the most part, the general idea is the same across machines,
++but the implementation is vastly different.  This is managed via
++conditional compiles throughout the startup code for each of the
++supported machines. */
++
++#ifdef TARGET_COCO /* CoCo memory map */
++
++#define COCO_RAMROM_MODE 0xFFDE
++#define COCO_ALLRAM_MODE 0xFFDF
++#define COCO_PAGE1 0xFFD5
++
++/* SAM M1 and M0 adjusts the memory size */
++
++#define BASIC_WARMSTART_FLAG 0x0071
++#define BASIC_START 0xA027
++
++#define __STACK_TOP 0x6800
++
++#else /* Simulator (default) memory map */
++
++#define SIM_EXIT_REG 0xFF01
++
++#define __STACK_TOP 0xFE00
++
++#endif
++
++
++	/* Declare all linker sections, and combine them into a single bank */
++	.bank	prog
++	.area	.text  (BANK=prog)
++	.area .data  (BANK=prog)
++	.area .ctors (BANK=prog)
++	.word 0
++	.area .dtors (BANK=prog)
++	.word 0
++	.area .bss   (BANK=prog)
++
++   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	;;;
++	;;; __exit : Exit point from the program
++	;;; For simulation, this writes to a special I/O register that
++	;;; the simulator interprets as end-of-program.
++	;;;
++   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area	.text
++ 	.globl __exit
++__exit:
++#ifdef TARGET_COCO
++	;; Go back to ROM/RAM mode
++	sta	COCO_RAMROM_MODE
++	clr	BASIC_WARMSTART_FLAG
++	jmp   BASIC_START
++#else
++	tfr	x,d
++	stb	SIM_EXIT_REG
++	bra	__exit
++#endif
++
++
++   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	;;;
++	;;; __start : Entry point to the program
++	;;;
++   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area	.text
++	.globl __start
++__start:
++
++#ifdef HAVE_DIRECT
++	;; Initialize the direct page pointer
++	lda	#<s_.direct
++	tfr	a,dp
++#endif
++
++#ifdef TARGET_COCO
++	;; Turn off interrupts
++	orcc #(0x10|0x40)
++	
++	;; Setup All RAM Mode
++	sta COCO_ALLRAM_MODE
++#endif /* TARGET_COCO */
++
++	;; Initialize the stack
++	lds	#__STACK_TOP - 2
++	
++	;; Call any "initializer" functions
++	ldu	#s_.ctors
++__ctors_loop:
++	ldy	,u++
++	cmpy	#0
++	beq	__ctors_done
++	jsr	,y
++	bra	__ctors_loop
++__ctors_done:
++
++	;; Enable interrupts on the simulator
++#ifndef TARGET_COCO
++	andcc	#~(0x10|0x40)
++#endif
++
++	;; Set up the environment
++
++	;; Set up argc/argv arrays
++
++	;; Call the main function.  The exit code will
++	;; be returned in the X register, unless compiled
++	;; with -mdret, in which case it comes back in D.
++	jsr	_main
++
++	;; Call any finalizer functions
++	ldu	#s_.dtors
++__dtors_loop:
++	ldy	,u++
++	cmpy	#0
++	beq	__dtors_done
++	jsr	,y
++	bra	__dtors_loop
++__dtors_done:
++
++	;; If main returns, then invoke _exit() to stop the program
++	;; The C library doesn't support -mdret yet, so move the
++	;; argument first.
++#ifdef __DRET__
++	tfr	d,x
++#endif
++	jmp	_exit
++
++
++
++	;;;
++	;;; __crt0_vector : Default handler for interrupts
++	;;;
++	.area	.text
++___crt0_vector:
++	;; The default behavior is to simply ignore all
++	;; non-reset interrupts.
++	rti
++
++
++	;;;
++	;;; vector : The interrupt vector table
++	;;; The linker will ensure that this gets loaded at address 0xFFF0.
++	;;;
++	.area vector
++vectors:
++	.word ___crt0_vector
++	.word ___crt0_vector
++	.word ___crt0_vector
++	.word ___crt0_vector
++	.word ___crt0_vector
++	.word ___crt0_vector
++	.word ___crt0_vector
++	.word __start
++
++	.end __start
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/libgcc1.s gcc-4.6.1/gcc/config/m6809/libgcc1.s
+--- gcc-4.6.1-orig/gcc/config/m6809/libgcc1.s	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/libgcc1.s	2011-09-17 14:06:01.227643616 -0600
+@@ -0,0 +1,511 @@
++/* libgcc routines for m6809
++   Copyright (C) 2006 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++/* As a special exception, if you link this library with other files,
++   some of which are compiled with GCC, to produce an executable,
++   this library does not by itself cause the resulting executable
++   to be covered by the GNU General Public License.
++   This exception does not however invalidate any other reasons why
++   the executable file might be covered by the GNU General Public License.  */
++
++
++#define SIGFPE jmp _abort
++
++
++	; Shift functions
++	; On input, D is value to be shifted, and X has shift count.
++	; Result is also in D.
++
++#ifdef L_ashlhi3
++	.area .text
++	.globl _ashlhi3
++_ashlhi3:
++	pshs	x
++1$:
++	leax	-1,x
++	cmpx	#-1
++	beq	2$
++	aslb
++	rola
++	bra	1$
++2$:
++	puls	x,pc
++#endif
++
++#ifdef L_ashrhi3
++	.area .text
++	.globl _ashrhi3
++_ashrhi3:
++	pshs	x
++1$:
++	leax	-1,x
++	cmpx	#-1
++	beq	2$
++	asra
++	rorb
++	bra	1$
++2$:
++	puls	x,pc
++#endif
++
++
++#ifdef L_lshrhi3
++	.area .text
++	.globl _lshrhi3
++_lshrhi3:
++	pshs	x
++1$:
++	leax	-1,x
++	cmpx	#-1
++	beq	2$
++	lsra
++	rorb
++	bra	1$
++2$:
++	puls	x,pc
++#endif
++
++
++
++#ifdef L_softregs
++	.area		direct
++	.globl	m0, m1, m2, m3, m4, m5, m6, m7
++	.globl	m8, m9, m10, m11, m12, m13, m14, m15
++m0: .blkb 1
++m1: .blkb 1
++m2: .blkb 1
++m3: .blkb 1
++m4: .blkb 1
++m5: .blkb 1
++m6: .blkb 1
++m7: .blkb 1
++m8: .blkb 1
++m9: .blkb 1
++m10: .blkb 1
++m11: .blkb 1
++m12: .blkb 1
++m13: .blkb 1
++m14: .blkb 1
++m15: .blkb 1
++#endif
++
++
++#ifdef L_ashlsi3_one
++	.area		.text
++	.globl	_ashlsi3_one
++_ashlsi3_one:
++	asl	3,x
++	rol	2,x
++	rol	1,x
++	rol	,x
++	rts
++#endif
++
++#ifdef L_ashlsi3
++	/* X points to the SImode (source/dest)
++		B is the count */
++_ashlsi3:
++	pshs	u
++	cmpb	#16
++	blt	try8
++	subb	#16
++	; Shift by 16
++	ldu	2,x
++	stu	,x
++try8:
++	cmpb	#8
++	blt	try_rest
++	subb	#8
++	; Shift by 8
++
++try_rest:
++	tstb
++	beq	done
++do_rest:
++	; Shift by 1
++	asl	3,x
++	rol	2,x
++	rol	1,x
++	rol	,x
++	decb
++	bne	do_rest
++done:
++	puls	u,pc
++#endif
++
++#ifdef L_ashrsi3_one
++	.area		.text
++	.globl	_ashlsi3_one
++_ashrsi3_one:
++	asr	,x
++	ror	1,x
++	ror	2,x
++	ror	3,x
++	rts
++#endif
++
++
++#ifdef L_lshrsi3_one
++	.area		.text
++	.globl	_lshrsi3_one
++_lshrsi3_one:
++	lsr	,x
++	ror	1,x
++	ror	2,x
++	ror	3,x
++	rts
++#endif
++
++
++#ifdef L_clzsi2
++	.area .text
++	.globl ___clzhi2
++	; Input: X = 16-bit unsigned integer
++	; Output: X = number of leading zeros
++	; This function destroys the value in D.
++___clzhi2:
++	pshs	x
++	; Find the offset of the leftmost '1' bit in
++	; the left half of the word.
++	;
++	; Bits are numbered in the table with 1 meaning the
++	; LSB and 8 meaning the MSB.
++	;
++	; If nonzero, then clz is 8-a.
++	tfr	x,d
++	ldx	#___clz_tab
++	tfr	a,b
++	clra
++	ldb	d,x
++	bne	upper_bit_set
++
++lower_bit_set:
++	; If the upper byte is zero, then check the lower
++	; half of the word.  Return 16-a.
++	puls	d
++	clra
++	ldb	d,x
++	negb
++	addb	#16
++	bra	done
++
++upper_bit_set:
++	negb
++	addb	#8
++	puls	x
++
++done:
++	tfr	d,x
++	puls	pc
++#endif
++
++#ifdef L_clzdi2
++	.area .text
++	.globl ___clzsi2
++	; Input: 32-bit unsigned integer is on the stack, just
++	; above the return address
++	; Output: X = number of leading zeros
++___clzsi2:
++	; Check the upper 16-bit word
++	; If it is not zero, then return clzhi2(X).
++	; A branch can be used instead of a call since no
++	; postprocessing is needed.  Use long branch form
++	; though since functions may not be near each other.
++	ldx	2,s
++	lbne	___clzhi2
++	ldx	4,s
++	jsr	___clzhi2
++	leax	16,x
++	rts
++#endif
++
++#ifdef L_ctzsi2
++	.area .text
++	.globl ___ctzhi2
++	; Input: X = 16-bit unsigned integer
++	; Output: X = number of trailing zeros
++	; F(x) = 15 - clzhi2(X & -x)
++	; This function destroys the value in D.
++___ctzhi2:
++	tfr	x,d
++	coma
++	comb
++	addd	#1
++	pshs	a
++	pshs	b
++	tfr	x,d
++	andb	,s+
++	anda	,s+
++	tfr	d,x
++	jsr	___clzhi2
++	tfr	x,d
++	subd	#16
++	coma
++	comb
++	tfr	d,x
++	rts
++#endif
++
++
++#ifdef L_ctzdi2
++	.area .text
++	.globl ___ctzsi2
++	; Input: 32-bit unsigned integer is on the stack, just
++	; above the return address
++	; Output: X = number of leading zeros
++___ctzsi2:
++	; Check the lower 16-bit word
++	; If it is not zero, then return ctzhi2(X).
++	; A branch can be used instead of a call since no
++	; postprocessing is needed.  Use long branch form
++	; though since functions may not be near each other.
++	ldx	4,s
++	lbne	___ctzhi2
++	ldx	2,s
++	jsr	___ctzhi2
++	leax	16,x
++	rts
++#endif
++
++
++#ifdef L_mulhi3
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++;;; ___mulhi3 - signed/unsigned multiply
++;;; Called by GCC to implement 16x16 multiplication
++;;; Arguments: Two 16-bit values, one in stack, one in X.
++;;; Result: 16-bit result in X
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area .text
++	.globl _mulhi3
++_mulhi3:
++	pshs	x
++	lda   5,s   ; left msb * right lsb * 256
++	ldb   ,s
++	mul
++	tfr   b,a
++	clrb
++	tfr   d,x
++	ldb   1,s   ; left lsb * right msb * 256
++	lda   4,s
++	mul
++	tfr   b,a
++	clrb
++	leax  d,x
++	ldb   1,s   ; left lsb * right lsb
++	lda   5,s
++	mul
++	leax  d,x
++	puls	d,pc  ; kill D to remove initial push
++#endif
++
++
++#ifdef L_divhi3
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++;;; ___divhi3 - signed division
++;;; Arguments: Dividend in X, divisor on the stack
++;;; Returns result in X.
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area .text
++	.globl _divhi3
++_divhi3:
++	ldd	2,s
++	bne	do_div		; check dividend
++	SIGFPE
++do_div:
++	pshs	x
++	jsr	_seuclid
++	puls	x,pc
++#endif
++
++
++#ifdef L_modhi3
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++;;; ___modhi3 - signed modulo
++;;; Arguments: Dividend in X, divisor on the stack
++;;; Returns result in X.
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area .text
++	.globl _modhi3
++_modhi3:
++	ldd	2,s
++	bne	do_mod		; check dividend
++	SIGFPE
++do_mod:
++	pshs	x
++	jsr	_seuclid
++	leas	2,s
++	tfr	d,x
++	rts
++#endif
++
++
++
++#ifdef L_udivhi3
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++;;; ___udivhi3 - unsigned division
++;;; Arguments: Dividend in X, divisor on the stack
++;;; Returns result in X.
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area .text
++	.globl _udivhi3
++_udivhi3:
++	ldd	2,s
++	bne	do_udiv		; check dividend
++	SIGFPE
++do_udiv:
++	pshs	x
++	jsr	_euclid
++	puls	x,pc
++#endif
++
++
++#ifdef L_umodhi3
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++;;; ___umodhi3 - unsigned modulo
++;;; Arguments: Dividend in X, divisor on the stack
++;;; Returns result in X.
++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
++	.area .text
++	.globl _umodhi3
++_umodhi3:
++	ldd	2,s
++	bne	do_umod		; check dividend
++	SIGFPE
++do_umod:
++	pshs	x
++	jsr	_euclid
++	leas	2,s
++	tfr	d,x
++	rts
++#endif
++
++
++#ifdef L_euclid
++;	unsigned euclidean division
++;	calling: (left / right)
++;		push left
++;		ldd right
++;		jsr _euclid
++;	quotient on the stack (left)
++;	modulus in d
++
++	.area	.text
++	.globl	_euclid
++	left=5
++	right=1			; word
++	count=0			; byte
++	CARRY=1			; alias
++_euclid:
++	leas	-3,s		; 2 local variables
++	clr	count,s		; prescale divisor
++	inc	count,s
++	tsta
++presc:
++	bmi	presc_done
++	inc	count,s
++	aslb
++	rola
++	bra	presc
++presc_done:
++	std	right,s
++	ldd	left,s
++	clr	left,s		; quotient = 0
++	clr	left+1,s
++mod1:
++	subd	right,s		; check subtract
++	bcc	mod2
++	addd	right,s
++	andcc	#~CARRY
++	bra	mod3
++mod2:
++	orcc	#CARRY
++mod3:
++	rol	left+1,s	; roll in carry
++	rol	left,s
++	lsr	right,s
++	ror	right+1,s
++	dec	count,s
++	bne	mod1
++	leas	3,s
++	rts
++#endif
++
++#ifdef L_seuclid
++;	signed euclidean division
++;	calling: (left / right)
++;		push left
++;		ldd right
++;		jsr _seuclid
++;	quotient on the stack (left)
++;	modulus in d
++	.area	.text
++	.globl	_seuclid
++	left=6
++	right=2
++	quot_sign=1
++	mod_sign=0
++_seuclid:
++	leas	-4,s		; 3 local variables
++	std	right,s
++	clr	mod_sign,s
++	clr	quot_sign,s
++	ldd	left,s
++	bge	mod_abs
++	inc	mod_sign,s	; sign(mod) = sign(left)
++	inc	quot_sign,s
++	bsr	negd		; abs(left) -> D
++mod_abs:
++	pshs	b,a		; push abs(left)
++	ldd	right+2,s	; all references shifted by 2
++	bge	quot_abs
++	dec	quot_sign+2,s	; sign(quot) = sign(left) XOR sign(right)
++	bsr	negd		; abs(right) -> D
++quot_abs:
++	jsr	_euclid		; call (unsigned) euclidean division
++	std	right+2,s
++	puls	a,b		; quot -> D
++	tst	quot_sign,s	; all references no longer shifted
++	beq	quot_done
++	bsr	negd
++quot_done:
++	std	left,s		; quot -> left
++	ldd	right,s
++	tst	mod_sign,s
++	beq	mod_done
++	bsr	negd
++mod_done:
++	leas	4,s		; destroy stack frame
++	rts
++
++negd:				; self-explanatory !
++	nega
++	negb
++	sbca	#0
++	rts
++#endif
++
++
++
++#ifdef L_pending_addsi3
++_addsi3:
++	rts
++#endif /* L_pending_addsi3 */
++
++
++
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.c gcc-4.6.1/gcc/config/m6809/m6809.c
+--- gcc-4.6.1-orig/gcc/config/m6809/m6809.c	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/m6809.c	2011-09-18 19:48:42.137654855 -0600
+@@ -0,0 +1,3013 @@
++/*-------------------------------------------------------------------
++	FILE: m6809.c
++-------------------------------------------------------------------*/
++/* Subroutines for insn-output.c for MC6809.
++   Copyright (C) 1989-2007 Free Software Foundation, Inc.
++
++ MC6809 Version by Tom Jones (jones@sal.wisc.edu)
++ Space Astronomy Laboratory
++ University of Wisconsin at Madison
++
++ minor changes to adapt it to gcc-2.5.8 by Matthias Doerfel
++ ( msdoerfe@informatik.uni-erlangen.de )
++ also added #pragma interrupt (inspired by gcc-6811)
++
++ minor changes to adapt it to gcc-2.8.0 by Eric Botcazou
++ (ebotcazou@multimania.com)
++
++ minor changes to adapt it to gcc-2.95.3 by Eric Botcazou
++ (ebotcazou@multimania.com)
++
++ major cleanup, improvements, and upgrade to gcc 3.4 by Brian Dominy
++ (brian@oddchange.com)
++
++ additional adjustments, etc., for gcc 4.6.1 by William Astle (lost@l-w.ca)
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++#include <string.h>
++#include <time.h>
++#include <sys/types.h>
++#include <sys/timeb.h>
++#include <stdio.h>
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "tree.h"
++#include "rtl.h"
++#include "tm_p.h"
++#include "regs.h"
++#include "flags.h"
++#include "hard-reg-set.h"
++#include "real.h"
++#include "tree.h"
++#include "insn-config.h"
++#include "conditions.h"
++#include "insn-flags.h"
++#include "output.h"
++#include "insn-attr.h"
++#include "function.h"
++#include "target.h"
++#include "target-def.h"
++#include "expr.h"
++#include "recog.h"
++#include "cpplib.h"
++#include "c-family/c-pragma.h"
++#include "c-family/c-common.h"
++#include "toplev.h"
++#include "optabs.h"
++#include "version.h"
++#include "df.h"
++#include "rtlhooks-def.h"
++
++/* macro to return TRUE if length of operand mode is one byte */
++#define BYTE_MODE(X) ((GET_MODE_SIZE (GET_MODE (X))) == 1)
++
++
++/* REAL_REG_P(x) is a true if the rtx 'x' represents a real CPU
++register and not a fake one that is emulated in software. */
++#define REAL_REG_P(x) (REG_P(x) && !M_REG_P(x))
++
++/*-------------------------------------------------------------------
++    Target hooks, moved from target.h
++-------------------------------------------------------------------*/
++static void m6809_encode_section_info (tree decl, rtx rtl, int new_decl_p ATTRIBUTE_UNUSED);
++
++#undef TARGET_ENCODE_SECTION_INFO
++#define TARGET_ENCODE_SECTION_INFO m6809_encode_section_info
++
++#undef TARGET_ASM_FILE_START
++#define TARGET_ASM_FILE_START m6809_asm_file_start
++
++#undef TARGET_ASM_ALIGNED_HI_OP
++#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
++
++#undef TARGET_ASM_ALIGNED_SI_OP
++#define TARGET_ASM_ALIGNED_SI_OP NULL
++
++#undef TARGET_ASM_UNALIGNED_HI_OP
++#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
++
++#undef TARGET_ASM_UNALIGNED_SI_OP
++#define TARGET_ASM_UNALIGNED_SI_OP NULL
++
++#undef TARGET_RTX_COSTS
++#define TARGET_RTX_COSTS m6809_rtx_costs
++
++#undef TARGET_ATTRIBUTE_TABLE
++#define TARGET_ATTRIBUTE_TABLE m6809_attribute_table
++
++#undef TARGET_INIT_BUILTINS
++#define TARGET_INIT_BUILTINS m6809_init_builtins
++
++#undef TARGET_EXPAND_BUILTIN
++#define TARGET_EXPAND_BUILTIN m6809_expand_builtin
++
++#undef TARGET_DEFAULT_TARGET_FLAGS
++#define TARGET_DEFAULT_TARGET_FLAGS (MASK_REG_ARGS | MASK_DIRECT)
++
++#undef TARGET_FUNCTION_OK_FOR_SIBCALL
++#define TARGET_FUNCTION_OK_FOR_SIBCALL m6809_function_ok_for_sibcall
++
++#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
++#define TARGET_ASM_TRAMPOLINE_TEMPLATE m6809_asm_trampoline_template
++
++#undef TARGET_TRAMPOLINE_INIT
++#define TARGET_TRAMPOLINE_INIT m6809_initialize_trampoline
++
++#undef TARGET_FRAME_POINTER_REQUIRED
++#define TARGET_FRAME_POINTER_REQUIRED m6809_frame_pointer_required
++
++#undef TARGET_OPTION_OVERRIDE
++#define TARGET_OPTION_OVERRIDE m6809_override_options
++
++/* External variables used */
++extern int reload_completed;   /* set in toplev.c */
++extern FILE *asm_out_file;
++
++static int last_mem_size;   /* operand size (bytes) */
++
++/* True if the section was recently changed and another .area
++ * directive needs to be output before emitting the next label. */
++int section_changed = 0;
++
++/* Section names.  The defaults here are used until an
++ * __attribute__((section)) is seen that changes it. */
++char code_section_op[128] = "\t.area .text";
++char data_section_op[128] = "\t.area .data";
++char bss_section_op[128] = "\t.area .bss";
++const char *code_bank_option = 0;
++
++/* TRUE if the direct mode prefix might be valid in this context.
++ * This is set by 'print_address' prior to calling output_addr_const,
++ * which performs into 'print_direct_prefix' to do the final checks. */
++static int check_direct_prefix_flag;
++
++/* Nonzero if an address is being printed in a context which does not
++ * permit any PIC modifications to the address */
++static int pic_ok_for_addr_p = 1;
++
++/* Current code page.  This supports machines which can do bank
++ * switching to allow for more than 64KB of code/data. */
++char far_code_page[64];
++
++/* Current bank name */
++static char current_bank_name[8] = "-1";
++
++/* Default bank name */
++static char default_code_bank_name[8] = "-1";
++
++/* Direct memory reserved as soft registers */
++unsigned int m6809_soft_regs = 0;
++
++/* ABI version */
++unsigned int m6809_abi_version = M6809_ABI_VERSION_REGS;
++
++
++/**
++ * Called after options have been parsed.
++ * If overrides have been specified on the command-line, then
++ * these values are copied into the main storage variables.
++ */
++void
++m6809_override_options (void)
++{
++	/* Handle -mfar-code-page */
++	if (far_code_page_option == 0)
++		far_code_page_option = "__default_code_page";
++	strcpy (far_code_page, far_code_page_option);
++
++	/* Handle -mcode-section, -mdata-section, and -mbss-section */
++	if (code_section_ptr != 0)
++		sprintf (code_section_op, "\t.area %s", code_section_ptr);
++	if (data_section_ptr != 0)
++		sprintf (data_section_op, "\t.area %s", data_section_ptr);
++	if (bss_section_ptr != 0)
++		sprintf (bss_section_op, "\t.area %s", bss_section_ptr);
++
++	/* Handle -mcode-bank */
++	if (code_bank_option != 0)
++		sprintf (default_code_bank_name, "%s", code_bank_option);
++
++	/* Handle -mabi-version or -mno-reg-args */
++	if (m6809_abi_version_ptr != 0)
++	{
++		if (!strcmp (m6809_abi_version_ptr, "stack"))
++			m6809_abi_version = M6809_ABI_VERSION_STACK;
++		else if (!strcmp (m6809_abi_version_ptr, "regs"))
++			m6809_abi_version = M6809_ABI_VERSION_REGS;
++		else if (!strcmp (m6809_abi_version_ptr, "bx"))
++			m6809_abi_version = M6809_ABI_VERSION_BX;
++		else if (!strcmp (m6809_abi_version_ptr, "latest"))
++			m6809_abi_version = M6809_ABI_VERSION_LATEST;
++		else
++			m6809_abi_version = atoi (m6809_abi_version_ptr);
++	}
++
++	/* The older -mno-reg-args option is deprecated, and treated
++	as -mabi=stack. */
++	if (!TARGET_REG_ARGS)
++   {
++      warning (WARNING_OPT "-mno-reg-args deprecated; use -mabi=stack instead.");
++      m6809_abi_version = M6809_ABI_VERSION_STACK;
++   }
++
++	/* -fexceptions is unsupported */
++	flag_exceptions = 0;
++	flag_non_call_exceptions = 0;
++	flag_unwind_tables = 0;
++}
++
++
++/**
++ * Output prefix that directs the assembler to use a direct-mode
++ * instruction if globally enabled, address is a symbol, and symbol
++ * has been marked as in direct page.  Also, never do this if
++ * using the indirect mode. */
++void
++print_direct_prefix (FILE * file, rtx addr)
++{
++	if (TARGET_DIRECT &&
++       (GET_CODE (addr) == SYMBOL_REF) && 
++       SYMBOL_REF_FLAG (addr) &&
++       check_direct_prefix_flag)
++   {
++      putc ('*', file);
++   }
++}
++
++
++/** Prints an operand (that is not an address) in assembly from RTL. */
++void
++print_operand (FILE * file, rtx x, int code)
++{
++	if (REG_P (x)) {
++		/* gcc currently allocates the entire 16-bit 'd' register
++		 * even when it only needs an 8-bit value.  So here it
++		 * is tricked into printing only the lower 8-bit 'b'
++		 * register into the assembly output.
++		 *
++		 * Eventually gcc should be modified to allocate a/b
++		 * independently and this hack can be removed.
++		 *
++		 * Occasionally, we may want to do an operation using
++		 * the 'a' register instead of 'b'; use the 'A' code
++		 * to specify that.
++		 */
++		if (code == 'A')
++			fputs ("a", file);
++		else if ((BYTE_MODE (x)) && (REGNO (x) == HARD_D_REGNUM))
++			fputs ("b", file);
++		else if (M_REG_P (x) && code == 'L')
++			/* Soft registers can be treated like memory and accessed
++			 * at a particular offset. TODO : handle 'W' */
++			fputs (reg_names[REGNO (x)+1], file);
++		else
++			fputs (reg_names[REGNO (x)], file);
++	}
++
++	else if (MEM_P (x)) {
++		last_mem_size = GET_MODE_SIZE (GET_MODE (x));
++		if (code == 'L') {	/* LSH of word address */
++			if (GET_CODE (XEXP (x, 0)) == MEM)
++			{
++				/* Offseting an indirect addressing mode is not supported */
++				error ("expression too complex for 6809 (offset indirect mode)");
++				debug_rtx (x);
++			}
++			else
++				x = adjust_address (x, QImode, 1);
++		}
++		else if (code == 'M') { /* MSH of word address */
++			if (GET_CODE (XEXP (x, 0)) == MEM)
++			{
++				/* Offseting an indirect addressing mode is not supported */
++				error ("expression too complex for 6809 (offset indirect mode)");
++				debug_rtx (x);
++			}
++			else
++				x = adjust_address (x, QImode, 0);
++		}
++		else if (code == 'W') { /* least significant half of 32-bit */
++			x = adjust_address (x, HImode, 2);
++		}
++
++		pic_ok_for_addr_p = (code != 'C');
++		output_address (XEXP (x, 0));
++	}
++
++	else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode) {
++		union { double d; int i[2]; } u;
++		u.i[0] = CONST_DOUBLE_LOW (x);
++		u.i[1] = CONST_DOUBLE_HIGH (x);
++		fprintf (file, "#%#9.9g", u.d);
++	}
++
++	else if (code == 'R') {
++		fprintf (file, "%s", 
++			m6809_get_regs_printable (INTVAL (x)));
++	}
++
++	else {
++		if (code == 'L') {	/* LSH of word address */
++			x = gen_rtx_CONST_INT (VOIDmode, (INTVAL(x) & 0xff));
++		}
++		else if (code == 'M') {	/* MSH of word address */
++			x = gen_rtx_CONST_INT (VOIDmode, ((INTVAL(x) >> 8) & 0xff));
++		}
++
++		putc ('#', file);
++		output_addr_const (file, x);
++	}
++}
++
++
++/** Prints an address operand to assembler from its RTL representation. */
++void
++print_operand_address (FILE *file, rtx addr)
++{
++	register rtx base = 0;
++	register rtx offset = 0;
++	int regno;
++	int indirect_flag = 0;
++
++	check_direct_prefix_flag = 0;
++
++	/*** check for indirect addressing ***/
++	if (MEM_P (addr)) {
++		last_mem_size = GET_MODE_SIZE (GET_MODE (addr));
++		addr = XEXP (addr, 0);
++		if (pic_ok_for_addr_p)
++		{
++			indirect_flag = 1;
++			fprintf (file, "[");
++		}
++	}
++
++
++	switch (GET_CODE (addr)) {
++		case REG:
++			regno = REGNO (addr);
++			fprintf (file, ",%s", reg_names[regno]);
++			break;
++
++		case PRE_DEC:
++			regno = REGNO (XEXP (addr, 0));
++			fputs (((last_mem_size == 1) ? ",-" : ",--"), file);
++			fprintf (file, "%s", reg_names[regno]);
++			break;
++
++		case POST_INC:
++			regno = REGNO (XEXP (addr, 0));
++			fprintf (file, ",%s", reg_names[regno]);
++			fputs (((last_mem_size == 1) ? "+" : "++"), file);
++			break;
++
++		case PLUS:
++			base = XEXP (addr, 0);
++			if (MEM_P (base))
++				base = XEXP (base, 0);
++
++			offset = XEXP (addr, 1);
++			if (MEM_P (offset))
++				offset = XEXP (offset, 0);
++
++			if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset))) {
++				if (!indirect_flag)
++					check_direct_prefix_flag = 1;
++				output_addr_const (file, base);
++				check_direct_prefix_flag = 0;
++				fputs ("+", file);
++				output_addr_const (file, offset);
++			}
++
++			else if ((CONSTANT_ADDRESS_P (base)) && (A_REG_P (offset))) {
++				output_addr_const (file, base);
++				fprintf (file, ",%s", reg_names[REGNO (offset)]);
++			}
++
++			else if ((CONSTANT_ADDRESS_P (offset)) && (A_REG_P (base))) {
++				output_addr_const (file, offset);
++				fprintf (file, ",%s", reg_names[REGNO (base)]);
++			}
++
++			/*** accumulator offset ***/
++			else if (((D_REG_P (offset)) || (Q_REG_P (offset)))
++			&& (A_REG_P (base))) {
++				fprintf (file, "%s,%s",
++				reg_names[REGNO (offset)], reg_names[REGNO (base)]);
++			}
++
++			else if (((D_REG_P (base)) || (Q_REG_P (base)))
++			&& (A_REG_P (offset))) {
++				fprintf (file, "%s,%s",
++				reg_names[REGNO (base)], reg_names[REGNO (offset)]);
++			}
++
++			else if (GET_CODE (base) == PRE_DEC) {
++				regno = REGNO (XEXP (base, 0));
++				fputs (((last_mem_size == 1) ? ",-" : ",--"), file);
++				fprintf (file, "%s", reg_names[regno]);
++			}
++
++			else
++				abort ();
++
++			break;
++
++   default:
++		/* Set this global before calling output_addr_const() */
++		if (!indirect_flag)
++			check_direct_prefix_flag = 1;
++
++		/* When printing a SYMBOL_REF in PIC mode, do not print the leading
++		 * '#' and follow it by ',pcr' to enable relative addressing. */
++		if (flag_pic && pic_ok_for_addr_p && GET_CODE (addr) == SYMBOL_REF)
++		{
++			ASM_OUTPUT_SYMBOL_REF (file, addr);
++			fputs (",pcr", file);
++			pic_ok_for_addr_p = 1;
++		}
++		else
++		{
++      	output_addr_const (file, addr);
++		}
++
++		check_direct_prefix_flag = 0;
++      break;
++	}
++
++	if (indirect_flag)
++		fprintf (file, "]");
++}
++
++/*-------------------------------------------------------------------
++    Update the CC Status
++---------------------------------------------------------------------
++   Set the cc_status for the results of an insn whose pattern is EXP.
++   We assume that jumps don't affect the condition codes.
++   All else, clobbers the condition codes, by assumption.
++
++   We assume that ALL add, minus, etc. instructions effect the condition
++   codes.
++-------------------------------------------------------------------*/
++void
++notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
++{
++	int src_code;
++	int dst_code;
++
++	/*** recognize SET insn's ***/
++	if (GET_CODE (exp) == SET)
++	{
++		src_code = GET_CODE (SET_SRC (exp));
++		dst_code = GET_CODE (SET_DEST (exp));
++
++		/* Jumps do not alter the cc's.  */
++		if (SET_DEST (exp) == pc_rtx)
++			return;
++
++		/* Moving one register into another register (tfr):
++		Doesn't alter the cc's.  */
++		if (REG_P (SET_DEST (exp)) && (REG_P (SET_SRC (exp))))
++			return;
++
++		/* Moving memory into a register (load): Sets cc's. */
++		if (REG_P (SET_DEST (exp)) && src_code == MEM) {
++			cc_status.value1 = SET_SRC (exp);
++			cc_status.value2 = SET_DEST (exp);
++			return;
++		}
++
++		/* Moving register into memory (store): Sets cc's. */
++		if (dst_code == MEM && REG_P (SET_SRC (exp))) {
++			cc_status.value1 = SET_SRC (exp);
++			cc_status.value2 = SET_DEST (exp);
++			return;
++		}
++
++		/* Function calls clobber the cc's.  */
++		else if (GET_CODE (SET_SRC (exp)) == CALL) {
++			CC_STATUS_INIT;
++			return;
++		}
++
++		/* Tests and compares set the cc's in predictable ways.  */
++		else if (SET_DEST (exp) == cc0_rtx)
++		{
++			cc_status.flags = 0;
++			cc_status.value1 = SET_SRC (exp);
++			cc_status.value2 = SET_DEST (exp);
++			return;
++		}
++
++		else if (A_REG_P (SET_DEST (exp)))
++		{
++			CC_STATUS_INIT;
++			return;
++		}
++
++		else
++		{
++			/* Certain instructions affect the condition codes. */
++			switch (src_code)
++			{
++				case PLUS:
++				case MINUS:
++				case NEG:
++				case ASHIFT:
++					/* These instructions set the condition codes,
++					 * and may modify the V bit. */
++					cc_status.flags |= CC_NO_OVERFLOW;
++					/* FALLTHRU */
++
++				case AND:
++				case IOR:
++				case XOR:
++				case ASHIFTRT:
++				case LSHIFTRT:
++					/* These instructions set the condition codes,
++					 * but cannot overflow (V=0). */
++					cc_status.value1 = SET_SRC (exp);
++					cc_status.value2 = SET_DEST (exp);
++					break;
++
++				default:
++					/* Everything else is clobbered */
++					CC_STATUS_INIT;
++			}
++			return;
++		}
++	} /* SET */
++
++	else if (GET_CODE (exp) == PARALLEL
++		&& GET_CODE (XVECEXP (exp, 0, 0)) == SET)
++	{
++		if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
++			return;
++		if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
++		{
++			CC_STATUS_INIT;
++			cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
++			return;
++		}
++	}
++
++	/*** default action if we haven't recognized something
++	and returned earlier ***/
++	CC_STATUS_INIT;
++}
++
++
++/** Returns nonzero if the expression EXP can be implemented using one
++ * of the 6809's single operand instructions. */
++int
++m6809_single_operand_operator (rtx exp)
++{
++	rtx op1;
++	HOST_WIDE_INT val;
++	enum rtx_code code;
++
++	debug_rtx(exp);
++
++	code = GET_CODE (exp);
++
++	/* Unary operators always qualify */
++	switch (code)
++	{
++		case NEG:
++		case NOT:
++			return 1;
++
++		default:
++			break;
++	}
++
++	/* Binary operators can only qualify if the second
++	 * argument is a CONST_INT of certain value. */
++	op1 = XEXP (exp, 1);
++	if (GET_CODE (op1) != CONST_INT)
++		return 0;
++	val = INTVAL (op1);
++	switch (code)
++	{
++		case PLUS:
++		case MINUS:
++			if (val == -1 || val == 1)
++				return 1;
++			break;
++
++		case ASHIFT:
++		case ASHIFTRT:
++		case LSHIFTRT:
++		case ROTATE:
++		case ROTATERT:
++			if (val == 1)
++				return 1;
++			break;
++
++		default:
++			break;
++	}
++
++	return 0;
++}
++
++
++/** Return a bitarray of the hard registers which are used by a function. */
++unsigned int
++m6809_get_live_regs (void)
++{
++	unsigned int regs = 0;
++	int regno;
++
++	if (frame_pointer_needed)
++		regs |= (1 << HARD_FRAME_POINTER_REGNUM);
++
++	for (regno = HARD_X_REGNUM; regno <= HARD_U_REGNUM; regno++)
++		if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
++			regs |= (1 << regno);
++
++	return regs;
++}
++
++
++/** Return a printable version of a list of hard registers, suitable
++ * for use in a PSHx or PULx insn. */
++const char *
++m6809_get_regs_printable (unsigned int regs)
++{
++	static char list[64];
++	char *listp = list;
++	unsigned int regno;
++
++	for (regno=0; regno < FIRST_PSEUDO_REGISTER; regno++)
++		if ((regs & (1 << regno)) && !S_REGNO_P (regno))
++			listp += sprintf (listp,
++				(listp == list) ? "%s" : ",%s", reg_names[regno]);
++
++	return list;
++}
++
++
++/** Return the total number of bytes covered by a set of hard registers. */
++unsigned int
++m6809_get_regs_size (unsigned int regs)
++{
++	unsigned int regno;
++	unsigned int size = 0;
++
++	for (regno=0; regno < FIRST_PSEUDO_REGISTER; regno++)
++	{
++		/* Only count register in the given register set */
++		if (REGSET_CONTAINS_P (regno, regs))
++		{
++			/* Add 1 or 2 byte, depending on the size of the register.
++			 * Since 'D' may be in both sets, check for WORD_REGSET first. */
++			if (REGSET_CONTAINS_P(regno, WORD_REGSET))
++				size += 2;
++			else if (REGSET_CONTAINS_P(regno, BYTE_REGSET))
++				size++;
++		}
++	}
++	return size;
++}
++
++
++/* Given the target of call instruction in X,
++ * return the tree node that contains the function declaration for
++ * that target.
++ *
++ * If the rtx or the tree do not appear valid for any reason,
++ * then return NULL_TREE.
++ */
++static tree call_target_decl (rtx x)
++{
++   tree decl;
++
++	/* Make sure the target is really a MEM. */
++	if (!x || !MEM_P (x))
++		return NULL_TREE;
++
++	/* Make sure the address is a SYMBOL_REF. */
++	x = XEXP (x, 0);
++	if (!x || (GET_CODE (x) != SYMBOL_REF))
++		return NULL_TREE;
++
++	/* Get the declaration of this symbol */
++	decl = SYMBOL_REF_DECL (x);
++
++	/* Make sure the declaration is really a function. */
++	if (!decl || (TREE_CODE(decl) != FUNCTION_DECL))
++		return NULL_TREE;
++
++   return decl;
++}
++
++
++/** Returns nonzero if a function, whose declaration is in DECL,
++ * was declared to have the attribute given by ATTR_NAME. */
++int
++m6809_function_has_type_attr_p (tree decl, const char *attr_name)
++{
++	tree type;
++
++	type = TREE_TYPE (decl);
++	return lookup_attribute (attr_name, TYPE_ATTRIBUTES (type)) != NULL;
++}
++
++
++
++/** Returns nonzero if the current function was declared to have the
++ * attribute given by ATTR_NAME. */
++int
++m6809_current_function_has_type_attr_p (const char *attr_name)
++{
++	return m6809_function_has_type_attr_p (current_function_decl, attr_name);
++}
++
++
++/** Return nonzero if the current function has no return value. */
++int
++m6809_current_function_is_void (void)
++{
++   return (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))));
++}
++
++
++/** Get the value of a declaration's 'bank', as set by the 'bank'
++ * attribute.  If no bank was declared, it returns NULL by default. */
++const char *
++m6809_get_decl_bank (tree decl)
++{
++	tree attr;
++
++	/* Lookup the 'bank' attribute.  If it does not exist, then
++	 * return NULL */
++	attr = lookup_attribute ("bank", DECL_ATTRIBUTES (decl));
++	if (attr == NULL_TREE)
++		return NULL;
++
++	/* Make sure it has a value assigned to it */
++	attr = TREE_VALUE (attr);
++	if (attr == NULL_TREE)
++	{
++		warning (WARNING_OPT "banked function did not declare a bank number");
++		return NULL;
++	}
++
++	/* Return the bank name */
++	attr = TREE_VALUE (attr);
++	return TREE_STRING_POINTER (attr);
++}
++
++
++void
++m6809_declare_function_name (FILE *asm_out_file, const char *name, tree decl)
++{
++	/* Check the function declaration for special properties.
++	 *
++	 * If the function was declare with __attribute__((bank)), output
++	 * assembler definitions to force the function to go into the named
++	 * bank.
++	 */
++	const char *bank_name = m6809_get_decl_bank (decl);
++	if (bank_name != NULL)
++	{
++		/* Declare __self_bank as a local assembler value that denotes
++		 * which bank the current function is in.  This is required only
++		 * when the bank actually changes. */
++		if (strcmp (bank_name, current_bank_name))
++		{
++			fprintf (asm_out_file, "__self_bank\t.equ %s\n", bank_name);
++			strcpy (current_bank_name, bank_name);
++		}
++
++		/* Declare a global assembler value that denotes which bank the
++		 * named function is in. */
++		fprintf (asm_out_file, "__%s_bank\t.gblequ %s\n", name, bank_name);
++
++		/* Force the current function into a new area */
++		fprintf (asm_out_file, "\t.bank bank_%s (FSFX=_%s)\n",
++			bank_name, bank_name);
++		fprintf (asm_out_file, "\t.area bank_%s (BANK=bank_%s)\n",
++			bank_name, bank_name);
++	}
++
++	/* Emit the label for the function's name */
++	ASM_OUTPUT_LABEL (asm_out_file, name);
++}
++
++#if 0
++/**
++ * Handle pragmas.  Note that only the last branch pragma seen in the 
++ * source has any affect on code generation.  
++ */
++
++#define BAD_PRAGMA(msgid, arg) \
++	do { warning (WARNING_OPT msgid, arg); return -1; } while (0)
++
++static int
++pragma_parse (const char *name, tree *sect)
++{
++  tree s, x;
++
++  if (pragma_lex (&x) != CPP_OPEN_PAREN)
++    BAD_PRAGMA ("missing '(' after '#pragma %s' - ignored", name);
++
++  if (pragma_lex (&s) != CPP_STRING)
++    BAD_PRAGMA ("missing section name in '#pragma %s' - ignored", name);
++
++  if (pragma_lex (&x) != CPP_CLOSE_PAREN)
++    BAD_PRAGMA ("missing ')' for '#pragma %s' - ignored", name);
++
++  if (pragma_lex (&x) != CPP_EOF)
++    warning (WARNING_OPT "junk at end of '#pragma %s'", name);
++
++  *sect = s;
++  return 0;
++}
++
++
++/*
++ * Handle #pragma section.
++ * This is deprecated; code should use __attribute__(section("name"))
++ * instead.
++ */
++void pragma_section (cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++	tree sect;
++
++	if (pragma_parse ("section", &sect))
++		return;
++
++	snprintf (code_section_op, 6+TREE_STRING_LENGTH (sect),
++		".area\t%s", TREE_STRING_POINTER (sect));
++	snprintf (data_section_op, 6+TREE_STRING_LENGTH (sect),
++		".area\t%s", TREE_STRING_POINTER (sect));
++
++	/* Mark a flag that sections have changed.  Upon emitting another
++	 * declaration, the new .area directive will be written. */
++	section_changed++;
++}
++#endif
++
++/**
++ * Check a `double' value for validity for a particular machine mode.
++ * Called by the CHECK_FLOAT_VALUE() machine-dependent macro.
++ */
++int
++check_float_value (enum machine_mode mode, double *d, int overflow)
++{
++	if (mode == SFmode) {
++		if (*d > 1.7014117331926443e+38) {
++			error("magnitude of constant too large for `float'");
++			*d = 1.7014117331926443e+38;
++		}
++		else if (*d < -1.7014117331926443e+38) {
++			error("magnitude of constant too large for `float'");
++			*d = -1.7014117331926443e+38;
++		}
++		else if ((*d > 0) && (*d < 2.9387358770557188e-39)) {
++			warning(WARNING_OPT "`float' constant truncated to zero");
++			*d = 0.0;
++		}
++		else if ((*d < 0) && (*d > -2.9387358770557188e-39)) {
++			warning(WARNING_OPT "`float' constant truncated to zero");
++			*d = 0.0;
++		}
++	}
++	return overflow;
++}
++
++
++
++/** Declare that the target supports named output sections. */
++bool m6809_have_named_section = (bool)1;
++
++
++/** Write to the assembler file a directive to place
++ * subsequent objects to a different section in the
++ * object file.  ASxxxx uses the "area" directive for
++ * this purpose.  It does not however support generalized
++ * alignment, and can only place items on an odd/even
++ * boundary. */
++void
++m6809_asm_named_section (
++	const char *name, 
++	unsigned int flags ATTRIBUTE_UNUSED,
++	tree decl)
++{
++	fprintf (asm_out_file, "\t.area\t%s\n", name);
++}
++
++
++enum reg_class
++m6809_preferred_reload_class (rtx x, enum reg_class regclass)
++{
++	/* Check cases based on type code of rtx */
++	switch (GET_CODE(x))
++	{
++		case CONST_INT:
++		   /* Constants that can fit into 1 byte should be
++			 * loaded into a Q_REGS reg */
++			if (((unsigned) (INTVAL(x) + 0x80) < 0x100) &&
++  				 (regclass > A_REGS))
++      		return Q_REGS;
++
++			/* 16-bit constants should be loaded into A_REGS
++			 * when possible.  gcc may already require A_REGS
++			 * or D_REGS for certain types of instructions.
++			 * This case applies mostly to simple copy operations
++			 * to/from memory when any register will do, but
++			 * it's best to avoid using D register since it is
++			 * needed for other things.
++			 */
++			else if (((unsigned) (INTVAL(x) + 0x80) < 0x10000) &&
++  				 (regclass > A_REGS))
++      		return A_REGS;
++			break;
++
++		case SYMBOL_REF:
++		case LABEL_REF:
++			/* Addresses should always be loaded into A_REGS */
++			if (regclass >= A_REGS)
++				return (A_REGS);
++
++		default:
++			break;
++	}
++
++	/* Check cases based on mode of rtx */
++   if ((GET_MODE(x) == QImode) && (regclass != A_REGS))
++      return Q_REGS;
++
++	/* Default: return whatever class reload suggested */
++   return regclass;
++}
++
++
++/**
++ * Check a new declaration for the "section" attribute.
++ * If it exists, and the target section is "direct", then mark
++ * the declaration (in RTL) to indicate special treatment.
++ * When the variable is referenced later, we test for this flag
++ * and can emit special asm text to force the assembler to use
++ * short instructions.
++ */
++static void
++m6809_encode_section_info (tree decl, rtx rtl, int new_decl_p ATTRIBUTE_UNUSED)
++{
++   tree attr, id;
++   const char *name;
++   const char *decl_name;
++
++   /* We only care about variable declarations, not functions */
++   if (TREE_CODE (decl) != VAR_DECL)
++      return;
++
++	/* For debugging purposes only; grab the decl's name */
++   decl_name = IDENTIFIER_POINTER (DECL_NAME (decl));
++
++	/* Give up if the decl doesn't have any RTL */
++   if (!DECL_RTL (decl))
++      return;
++
++	/* See if it has a section attribute */
++   attr = lookup_attribute ("section", DECL_ATTRIBUTES (decl));
++   if (!attr)
++      return;
++
++	/* See if the section attribute has a value */
++   id = TREE_VALUE (TREE_VALUE (attr));
++   if (!id)
++      return;
++   name = TREE_STRING_POINTER (id);
++   if (!name)
++      return;
++
++	/* See if the value is 'direct'.  If so, mark it. */
++   if (!strcmp (name, "direct"))
++      SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
++}
++
++
++/**
++ * Output code to perform a complex shift, for which there is no
++ * direct support in the instruction set.
++ *
++ * shift1 is an instruction pattern for performing a 1-bit modification.
++ * This code wraps that pattern in a loop to perform the shift N times,
++ * where N is given by the address register in operands[2].
++ *
++ * To support 16-bit shifts, shift2 can also be provided: it is
++ * a second instruction to be included in the loop.  8-bit shift
++ * insns will pass NULL here.
++ *
++ * The insn length of shift1/shift2 is assumed to be 1 byte,
++ * which works in all of the cases it is needed so far.
++ */
++static void
++m6809_gen_register_shift (
++		rtx *operands,
++		const char *shift1,
++		const char *shift2 )
++{
++	char beq_pattern[32];
++   char bra_pattern[32];
++
++	int shiftlen = (shift1 && shift2) ? 2 : 1;
++	int cmplen = (REGNO (operands[2]) == HARD_X_REGNUM) ? 3 : 4;
++
++	int beq_offset = 2 + shiftlen + 2;
++	int bra_offset = shiftlen + 2 + cmplen + 2;
++
++	sprintf (beq_pattern, "beq\t.+%d", beq_offset);
++	sprintf (bra_pattern, "bra\t.-%d", bra_offset);
++
++	output_asm_insn ("pshs\t%2", operands);
++	output_asm_insn ("lea%2\t-1,%2", operands);
++   output_asm_insn ("cmp%2\t#-1", operands);
++   output_asm_insn (beq_pattern, operands);
++	if (shift1)
++		output_asm_insn (shift1, operands);
++	if (shift2)
++		output_asm_insn (shift2, operands);
++	output_asm_insn (bra_pattern, operands);
++	output_asm_insn ("puls\t%2", operands);
++}
++
++
++/** Generate RTL for the upper 8-bits of a 16-bit constant. */
++rtx
++gen_rtx_const_high (rtx r)
++{
++   unsigned char v = (INTVAL (r) >> 8) & 0xFF;
++	signed char s = (signed char)v;
++   return gen_int_mode (s, QImode);
++}
++
++
++/** Generate RTL for the lower 8-bits of a 16-bit constant. */
++rtx
++gen_rtx_const_low (rtx r)
++{
++   unsigned char v = INTVAL (r) & 0xFF;
++	signed char s = (signed char)v;
++   return gen_int_mode (s, QImode);
++}
++
++
++/** Generate RTL to allocate/free bytes on the stack.
++ * CODE is given as MINUS when allocating and PLUS when freeing,
++ * to match the semantics of a downward-growing stack.  SIZE
++ * is always given as a positive integer.
++ */
++static rtx
++gen_rtx_stack_adjust (enum rtx_code code, int size)
++{
++	if (size <= 0)
++		return NULL_RTX;
++
++	if (code == MINUS)
++		size = -size;
++
++	return gen_rtx_SET (Pmode, stack_pointer_rtx, 
++		gen_rtx_PLUS (Pmode, stack_pointer_rtx,
++			gen_int_mode (size, HImode)));
++}
++
++
++/** Generate RTL to push/pop a set of registers. */
++rtx
++gen_rtx_register_pushpop (int op, int regs)
++{
++	rtx nregs = gen_int_mode (regs, QImode);
++	
++	if (op == UNSPEC_PUSH_RS)
++		return gen_register_push (nregs);
++	else
++		return gen_register_pop (nregs);
++}
++
++
++/* Given a register set REGS, where the bit positions correspond to
++ * hard register numbers, return another bitmask that represents the
++ * order in which those registers would be pushed/popped.
++ * Registers that are pushed first have higher bit positions.
++ * The pop order is just the reverse bitmask.
++ * These values are the same as the bitmasks actually used in the
++ * machine instructions. */
++static unsigned int
++register_push_order (int regs)
++{
++	unsigned int order = 0;
++
++	if (REGSET_CONTAINS_P (HARD_PC_REGNUM, regs))
++		order |= 0x80;
++	if (REGSET_CONTAINS_P (HARD_U_REGNUM, regs))
++		order |= 0x40;
++	if (REGSET_CONTAINS_P (HARD_Y_REGNUM, regs))
++		order |= 0x20;
++	if (REGSET_CONTAINS_P (HARD_X_REGNUM, regs))
++		order |= 0x10;
++	if (REGSET_CONTAINS_P (HARD_DP_REGNUM, regs))
++		order |= 0x8;
++	if (REGSET_CONTAINS_P (HARD_B_REGNUM, regs))
++		order |= 0x4;
++	if (REGSET_CONTAINS_P (HARD_A_REGNUM, regs))
++		order |= 0x2;
++	if (REGSET_CONTAINS_P (HARD_CC_REGNUM, regs))
++		order |= 0x1;
++
++	if (REGSET_CONTAINS_P (HARD_D_REGNUM, regs))
++		order |= (0x4 | 0x2);
++	return order;
++}
++
++
++/* Returns nonzero if two consecutive push or pop instructions,
++ * as determined by the OP, can be merged into a single instruction.
++ * The first instruction in the sequence pushes/pops REGS1; the
++ * second applies to REGS2.
++ *
++ * If true, the resulting instruction can use (regs1 | regs2)
++ * safely.
++ */
++int
++m6809_can_merge_pushpop_p (int op, int regs1, int regs2)
++{
++	/* Register sets must not overlap */
++	if (regs1 & regs2)
++		return 0;
++
++	if (op == UNSPEC_PUSH_RS)
++		return (register_push_order (regs1) > register_push_order (regs2));
++	else if (op == UNSPEC_POP_RS)
++		return (register_push_order (regs1) < register_push_order (regs2));
++	else
++		return 0;
++}
++
++
++/** Emit instructions for making a library call.
++ * MODE is the mode of the operation.
++ * NAME is the library function name.
++ * OPERANDS is the rtx array provided by the recognizer.
++ * COUNT is the number of input operands to the call, and
++ * should be 1 for a unary op or 2 for a binary op.
++ */
++void
++emit_libcall_insns (enum machine_mode mode, 
++	const char *name, 
++	rtx *operands,
++	int count)
++{
++	/* Generate an rtx for the call target. */
++	rtx symbol = gen_rtx_SYMBOL_REF (Pmode, name);
++
++	/* Emit the library call.  Slightly different based
++	on the number of operands */
++	if (count == 2)
++		emit_library_call (symbol, LCT_NORMAL, mode,
++			2, operands[1], mode, operands[2], mode);
++	else
++		emit_library_call (symbol, LCT_NORMAL, mode,
++			1, operands[1], mode);
++
++	/* The library call is expected to put its result
++	in LIBCALL_VALUE, so need to copy it into the destination. */
++	emit_move_insn (operands[0], LIBCALL_VALUE(mode));
++}
++
++
++/**
++ * A small helper function that writes out a single branch instruction.
++ * OPCODE is the short name, e.g. "ble".
++ * OPERANDS has the rtx for the target label.
++ * LONG_P is nonzero if we are emitting a long branch, and need to
++ * prepend an 'l' to the opcode name.
++ */
++void output_branch_insn1 (const char *opcode, rtx *operands, int long_p)
++{
++	char pattern[64];
++	sprintf (pattern, "%s%s\t%%l0", long_p ? "l" : "", opcode);
++	output_asm_insn (pattern, operands);
++}
++
++/**
++ * Output a branch/conditional branch insn of the proper
++ * length.  code identifies the particular branch insn.
++ * operands holds the branch target in operands[0].
++ * length says what the size of this insn should be.
++ * Based on the length, we know whether it should be a
++ * short (8-bit) or long (16-bit) branch.
++ */
++const char *
++output_branch_insn (enum rtx_code code, rtx *operands, int length)
++{
++	int shortform; 
++
++	/* Decide whether or not to use the long or short form.
++	 * Calculate automatically based on insn lengths. */
++   shortform = ((length > 2) ? 0 : 1);
++
++	/* Determine the proper opcode.
++	 * Use the short (2-byte) opcode if the target is within
++	 * reach.  Otherwise, use jmp (3-byte opcode), unless
++	 * compiling with -fpic, in which case we'll need to use
++	 * lbra (4-byte opcode).
++	 */
++	switch (code)
++	{
++		case LABEL_REF: 
++			if (shortform)
++				output_branch_insn1 ("bra", operands, 0);
++			else if (flag_pic)
++				output_branch_insn1 ("bra", operands, 1);
++			else
++				output_branch_insn1 ("jmp", operands, 0);
++			break;
++		case EQ:
++			output_branch_insn1 ("beq", operands, !shortform);
++			break;
++		case NE:
++			output_branch_insn1 ("bne", operands, !shortform);
++			break;
++		case GT:
++			output_branch_insn1 ("bgt", operands, !shortform);
++			break;
++		case GTU:
++			output_branch_insn1 ("bhi", operands, !shortform);
++			break;
++		case LT:
++			if (cc_prev_status.flags & CC_NO_OVERFLOW)
++			{
++				output_branch_insn1 ("bmi", operands, !shortform);
++			}
++			else
++			{
++				output_branch_insn1 ("blt", operands, !shortform);
++			}
++			break;
++		case LTU:
++			output_branch_insn1 ("blo", operands, !shortform);
++			break;
++		case GE:
++			if (cc_prev_status.flags & CC_NO_OVERFLOW)
++			{
++				output_branch_insn1 ("bpl", operands, !shortform);
++			}
++			else
++			{
++				output_branch_insn1 ("bge", operands, !shortform);
++			}
++			break;
++		case GEU:
++			output_branch_insn1 ("bhs", operands, !shortform);
++			break;
++		case LE:
++			if (cc_prev_status.flags & CC_NO_OVERFLOW)
++			{
++				output_branch_insn1 ("bmi", operands, !shortform);
++				output_branch_insn1 ("beq", operands, !shortform);
++			}
++			else
++			{
++				output_branch_insn1 ("ble", operands, !shortform);
++			}
++			break;
++		case LEU:
++			output_branch_insn1 ("bls", operands, !shortform);
++			break;
++		default:
++			abort();
++			break;
++	}
++	return "";
++}
++
++
++/** Returns the "cost" of an RTL expression.
++ * In general, the expression "COSTS_N_INSNS(1)" is used to represent
++ * the cost of a fast 8-bit arithmetic instruction that operates on
++ * a reg/mem or a reg/immed.  Other costs are relative to this.
++ *
++ * Notes:
++ * - The cost of a REG is always zero; this cannot be changed.
++ *
++ * - On the 6809, instructions on two registers will nearly always take
++ *   longer than those that operate on a register and a constant/memory,
++ *   because of the way the instruction set is structured.
++ *
++ * TODO: multiply HImode by 2 should be done via shifts, instead of add.
++ */
++static bool
++m6809_rtx_costs (rtx X, int code, int outer_code ATTRIBUTE_UNUSED,
++	int *total, bool speed)
++{
++	int has_const_arg = 0;
++	HOST_WIDE_INT const_arg;
++	enum machine_mode mode;
++	int nargs = 1;
++	rtx op0, op1;
++
++	/* Data RTXs return a value between 0-3, depending on complexity.
++	All of these are less than COSTS_N_INSNS(1). */
++	switch (code)
++	{
++		case CC0:
++		case PC:
++			*total = 0;
++			return true;
++
++ 		case CONST_INT:
++    		if (X == const0_rtx)
++			{
++				*total = 0;
++				return true;
++			}
++			else if ((unsigned) INTVAL (X) < 077) 
++			{
++				*total = 1;
++				return true;
++			}
++			else
++			{
++				*total = 2;
++				return true;
++			}
++
++ 		case LABEL_REF: case CONST:
++   		*total = 2;
++			return true;
++
++ 		case SYMBOL_REF:
++			/* References to memory are made cheaper if they have
++			 * the 'direct' mode attribute set */
++			*total = (SYMBOL_REF_FLAG (X)) ? 1 : 2;
++			return true;
++
++		case MEM:
++			/* See what form of address was given */
++			X = XEXP (X, 0);
++			switch (GET_CODE (X))
++			{
++ 				case SYMBOL_REF:
++					*total = (SYMBOL_REF_FLAG (X)) ? 1 : 2;
++					break;
++
++				case CONST_INT:
++					*total = 2;
++					break;
++
++				case MEM:
++					*total = COSTS_N_INSNS (1) + 2;
++					break;
++
++				default:
++					break;
++			}
++			return true;
++
++ 		case CONST_DOUBLE:
++			/* TODO : not sure about this value. */
++   		*total = 3;
++			return true;
++
++		default:
++			break;
++	}
++
++	/* Decode the rtx */
++	mode = GET_MODE (X);
++	op0 = XEXP (X, 0);
++	op1 = XEXP (X, 1);
++
++	/* We don't implement anything in SImode or greater. */
++	if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode))
++	{
++		*total = COSTS_N_INSNS (100);
++		return true;
++	}
++
++	/* Figure out if there is a constant argument, and its value. */
++	if (GET_RTX_CLASS (code) == RTX_BIN_ARITH
++		|| GET_RTX_CLASS (code) == RTX_COMM_ARITH)
++	{
++		nargs = 2;
++		if (GET_CODE (op1) == CONST_INT)
++		{
++			has_const_arg = 1;
++			const_arg = INTVAL (op1);
++		}
++	}
++
++	/* Penalize a reg/reg operation by adding MEMORY_MOVE_COST,
++	 * Ignore soft registers, since these are really in memory.
++	 *
++	 * TODO: penalize HImode reg/reg for most operations, except maybe
++	 * additions since index registers allow for that.
++	 *
++	 * TODO: shifts by constant N do not always require N instructions;
++	 * some of this can be done cheaper.  The number of actual insns can be
++	 * predicted well.
++	 */
++	if (nargs == 2 && REAL_REG_P (op0) && REAL_REG_P (op1))
++	{
++		*total = MEMORY_MOVE_COST (mode, Q_REGS, 0);
++	}
++	else
++	{
++		*total = 0;
++	}
++
++	/* Operator RTXs are counted as COSTS_N_INSNS(N), where N is
++	the estimated number of actual machine instructions needed to
++	perform the computation.  Some small adjustments are made since
++	some "instructions" are more complex than others. */
++	switch (code)
++	{
++		case PLUS: case MINUS: case COMPARE:
++			/* 6809 handles these natively in QImode, and in HImode as long
++			 * as operand 1 is constant. */
++			if (mode == QImode || (mode == HImode && has_const_arg))
++				*total += COSTS_N_INSNS (1);
++			else 
++				*total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
++
++			/* -1, 0, and 1 can be done using inherent instructions
++			 * for PLUS and MINUS in QImode, so don't add extra cost. */
++  			if (has_const_arg
++				&& (mode == QImode || mode == HImode)
++				&& (const_arg == -1 || const_arg == 0 || const_arg == 1)
++				&& (code == PLUS || code == MINUS))
++			{
++				return true;
++			}
++			break;
++
++		case AND: case IOR: case XOR:
++		case NEG: case NOT:
++			/* 6809 handles these natively in QImode, but requires
++			 * splitting in HImode.   Treat these as 2 insns. */
++			*total += COSTS_N_INSNS (1) * GET_MODE_SIZE (mode);
++			break;
++
++  		case ASHIFT: case ASHIFTRT: case LSHIFTRT:
++  		case ROTATE: case ROTATERT:
++			/* 6809 can do shift/rotates of a QImode by a constant in
++			 * 1 insn times the shift count, or in HImode by a constant 
++			 * by splitting to 2 insns.
++			 *
++			 * Shift by a nonconstant will take significantly longer
++			 * than any of these. */
++  			if (has_const_arg)
++			{
++				const_arg %= (GET_MODE_SIZE (mode) * 8);
++				if (const_arg == 0)
++				{
++					*total += COSTS_N_INSNS(1);
++					return true;
++				}
++
++				/* HImode shifts greater than 8 get optimized due
++				 * to register transfer from b to a; this cuts down the
++				 * cost. */
++				if (const_arg >= 8)
++				{
++					*total += COSTS_N_INSNS (1);
++					const_arg -= 8;
++				}
++
++				/* The computed cost is 'const_arg' 1-bit shifts, doubled
++				if in HImode, minus the cost of the constant itself which
++				will be added in later but really shouldn't be. */
++				*total += COSTS_N_INSNS (const_arg) * GET_MODE_SIZE (mode) - 1;
++				return true;
++			}
++			else
++			{
++				/* It may take up to 7 iterations of about 6-7 real
++				 * instructions, so make this expensive. */
++				*total += COSTS_N_INSNS (50);
++			}
++  			break;
++
++		case MULT:
++ 		{
++ 			/* Multiply is cheap when both arguments are 8-bits.  They
++ 			could be QImode, or QImode widened to HImode, or a constant
++ 			that fits into 8-bits.  As long as both operands qualify,
++ 			we can use a single mul instruction.
++  
++ 			Assume that fast multiply can be used, and change this if we find
++ 			differently... */
++ 			int ok_for_qihi3 = 1;
++  
++ 			/* Check the first operand */	
++ 			switch (GET_MODE (op0))
++ 			{
++ 				case QImode:
++ 					break;
++ 				case HImode:
++ 					if (GET_CODE (op0) != SIGN_EXTEND && GET_CODE (op0) != ZERO_EXTEND)
++  						ok_for_qihi3 = 0;
++ 					break;
++ 				default:
++ 					ok_for_qihi3 = 0;
++ 					break;
++  			}
++ 
++			/* Likewise, check the second operand.  This is where constants may appear. */
++ 			switch (GET_MODE (op1))
++ 			{
++ 				case QImode:
++ 					break;
++ 				case HImode:
++					if (GET_CODE (op1) != SIGN_EXTEND && GET_CODE (op1) != ZERO_EXTEND)
++ 						ok_for_qihi3 = 0;
++ 					break;
++ 				case VOIDmode:
++					if (!CONST_OK_FOR_LETTER_P (const_arg, 'K'))
++ 						ok_for_qihi3 = 0;
++					break;
++ 				default:
++ 					ok_for_qihi3 = 0;
++ 					break;
++ 			}
++ 
++ 			/* Fast multiply takes about 4 times as many cycles as a normal
++ 			arithmetic operation.  Otherwise, it will take an expensive libcall. */
++ 			if (ok_for_qihi3)
++ 				*total += COSTS_N_INSNS (4);
++ 			else
++ 				*total = COSTS_N_INSNS (50);
++  	  		break;
++ 		}
++
++		case DIV: case UDIV: case MOD: case UMOD:
++			/* These all require more expensive libcalls. */
++			*total += COSTS_N_INSNS (100);
++  			break;
++
++		/* TODO : TRUNCATE, SIGN_EXTEND, and ZERO_EXTEND */
++
++		/* These can normally be done with autoincrement, etc., so
++		 * don't charge for them. */
++		case PRE_DEC:
++		case PRE_INC:
++		case POST_DEC:
++		case POST_INC:
++			break;
++
++		default:
++			break;
++	}
++
++	/* Always return false, and let the caller gather the costs
++	 * of the operands */
++	return false;
++}
++
++
++static tree
++m6809_handle_fntype_attribute (tree *node, tree name,
++	tree args ATTRIBUTE_UNUSED,
++	int flags ATTRIBUTE_UNUSED,
++	bool *no_add_attrs)
++{
++	if (TREE_CODE (*node) != FUNCTION_TYPE)
++	{
++		warning (WARNING_OPT "'%s' only valid for functions", 
++			IDENTIFIER_POINTER (name));
++		*no_add_attrs = TRUE;
++	}
++
++	return NULL_TREE;
++}
++
++
++static tree
++m6809_handle_data_type_attribute (tree *node ATTRIBUTE_UNUSED,
++	tree name ATTRIBUTE_UNUSED,
++	tree args ATTRIBUTE_UNUSED,
++	int flags ATTRIBUTE_UNUSED,
++	bool *no_add_attrs ATTRIBUTE_UNUSED)
++{
++	return NULL_TREE;
++}
++
++
++
++static tree
++m6809_handle_default_attribute (tree *node ATTRIBUTE_UNUSED, 
++	tree name ATTRIBUTE_UNUSED,
++	tree args ATTRIBUTE_UNUSED,
++	int flags ATTRIBUTE_UNUSED,
++	bool *no_add_attrs ATTRIBUTE_UNUSED )
++{
++	return NULL_TREE;
++}
++
++
++/* Table of valid machine attributes */
++const struct attribute_spec m6809_attribute_table[] = { /*
++{ name,        min, max, decl,  type, fntype, handler } */
++{ "interrupt", 0,   0,   false, true,  true,  m6809_handle_fntype_attribute },
++{ "naked",     0,   0,   false, true,  true,  m6809_handle_fntype_attribute },
++{ "far",       0,   1,   false, true,  true,  m6809_handle_fntype_attribute },
++{ "bank",      0,   1,   true,  false, false, m6809_handle_default_attribute },
++{ "boolean",   0,   0,   false, true,  false, m6809_handle_data_type_attribute },
++{ NULL,        0,   0,   false, true,  false, NULL },
++};
++
++
++/** Initialize builtin routines for the 6809. */
++void
++m6809_init_builtins (void)
++{
++	/* Create type trees for each function signature required.
++	 *
++	 * void_ftype_void = void f(void)
++	 * void_ftype_uchar = void f(unsigned char)
++	 * uchar_ftype_uchar2 = unsigned char f (unsigned char, unsigned char)
++	 */
++	tree void_ftype_void = 
++		build_function_type (void_type_node, void_list_node);
++
++	tree void_ftype_uchar =
++		build_function_type (void_type_node,
++			tree_cons (NULL_TREE, unsigned_char_type_node, void_list_node));
++
++	tree uchar_ftype_uchar2 =
++		build_function_type (unsigned_char_type_node,
++			tree_cons (NULL_TREE, unsigned_char_type_node, 
++				tree_cons (NULL_TREE, unsigned_char_type_node, void_list_node)));
++
++	/* Register each builtin function. */
++	add_builtin_function ("__builtin_swi", void_ftype_void,
++		M6809_SWI, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_swi2", void_ftype_void,
++		M6809_SWI2, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_swi3", void_ftype_void,
++		M6809_SWI3, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_cwai", void_ftype_uchar,
++		M6809_CWAI, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_sync", void_ftype_void,
++		M6809_SYNC, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_nop", void_ftype_void,
++		M6809_NOP, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_blockage", void_ftype_void,
++		M6809_BLOCKAGE, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_add_decimal", uchar_ftype_uchar2,
++		M6809_ADD_DECIMAL, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_add_carry", uchar_ftype_uchar2,
++		M6809_ADD_CARRY, BUILT_IN_MD, NULL, NULL_TREE);
++
++	add_builtin_function ("__builtin_sub_carry", uchar_ftype_uchar2,
++		M6809_SUB_CARRY, BUILT_IN_MD, NULL, NULL_TREE);
++}
++
++
++/** Used by m6809_expand_builtin, given a tree ARGLIST which
++ * refers to the operands of a builtin call, return an rtx
++ * that represents the nth operand, as denoted by OPNUM, which
++ * is a zero-based integer.  MODE gives the expected mode
++ * of the operand.
++ *
++ * This rtx is suitable for use in the emitted RTL for the
++ * builtin instruction. */
++rtx
++m6809_builtin_operand (tree arglist, enum machine_mode mode, int opnum)
++{
++	tree arg;
++	rtx r;
++
++	arg = CALL_EXPR_ARG (arglist, opnum);
++
++	/* Convert the tree to RTL */
++	r = expand_expr (arg, NULL_RTX, mode, EXPAND_NORMAL);
++	if (r == NULL_RTX)
++		return NULL_RTX;
++	return r;
++}
++
++
++/** Expand a builtin that was registered in init_builtins into
++ * RTL.  */
++rtx
++m6809_expand_builtin (tree exp, 
++	rtx target, 
++	rtx subtarget ATTRIBUTE_UNUSED,
++	enum machine_mode mode ATTRIBUTE_UNUSED,
++	int ignore ATTRIBUTE_UNUSED )
++{
++   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
++	tree arglist = exp;
++	unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
++	rtx r0, r1;
++
++	switch (fcode)
++	{
++		case M6809_SWI:
++			r0 = gen_rtx_CONST_INT (VOIDmode, 1);
++			emit_insn (target = gen_m6809_swi (r0));
++			return target;
++
++		case M6809_SWI2:
++			r0 = gen_rtx_CONST_INT (VOIDmode, 2);
++			emit_insn (target = gen_m6809_swi (r0));
++			return target;
++
++		case M6809_SWI3:
++			r0 = gen_rtx_CONST_INT (VOIDmode, 3);
++			emit_insn (target = gen_m6809_swi (r0));
++			return target;
++
++		case M6809_CWAI:
++			r0 = m6809_builtin_operand (arglist, QImode, 0);
++			emit_insn (target = gen_m6809_cwai (r0));
++			return target;
++
++		case M6809_SYNC:
++			emit_insn (target = gen_m6809_sync ());
++			return target;
++
++		case M6809_ADD_CARRY:
++			r0 = m6809_builtin_operand (arglist, QImode, 0);
++			r1 = m6809_builtin_operand (arglist, QImode, 1);
++			if (!target)
++				target = gen_reg_rtx (QImode);
++			emit_insn (gen_addqi3_carry (target, r0, r1));
++			return target;
++
++		case M6809_SUB_CARRY:
++			r0 = m6809_builtin_operand (arglist, QImode, 0);
++			r1 = m6809_builtin_operand (arglist, QImode, 1);
++			if (!target)
++				target = gen_reg_rtx (QImode);
++			emit_insn (gen_subqi3_carry (target, r0, r1));
++			return target;
++
++		case M6809_NOP:
++			emit_insn (target = gen_nop ());
++			return target;
++
++		case M6809_BLOCKAGE:
++			emit_insn (target = gen_blockage ());
++			return target;
++
++		case M6809_ADD_DECIMAL:
++			r0 = m6809_builtin_operand (arglist, QImode, 0);
++			r1 = m6809_builtin_operand (arglist, QImode, 1);
++			if (!target)
++				target = gen_reg_rtx (QImode);
++			emit_insn (gen_addqi3_decimal (target, r0, r1));
++			return target;
++
++		default:
++			warning (WARNING_OPT "unknown builtin expansion ignored");
++			return NULL_RTX;
++	}
++}
++
++
++
++/* Returns nonzero if 'x' represents a function that was declared
++ * as __noreturn__. */
++int
++noreturn_functionp (rtx x)
++{
++	tree decl = call_target_decl (x);
++
++	if (decl == NULL_TREE)
++		return 0;
++	else
++		return TREE_THIS_VOLATILE (decl);
++}
++
++
++const char *
++far_function_type_p (tree type)
++{
++	tree attr;
++	const char *page;
++
++	/* Return whether or not this decl has the far attribute */
++	attr = lookup_attribute ("far", TYPE_ATTRIBUTES (type));
++	if (attr == NULL_TREE)
++		return NULL;
++
++	/* If it is far, check for a value */
++	attr = TREE_VALUE (attr);
++	if (attr == NULL_TREE)
++	{
++		warning (WARNING_OPT "far code page not specified, using local value");
++		return far_code_page;
++	}
++
++	/* We have a TREE_LIST of attribute values, get the first one.
++	 * It should be an INTEGER_CST. */
++	attr = TREE_VALUE (attr);
++	page = TREE_STRING_POINTER (attr);
++	return page;
++}
++
++
++/* For a far function, returns the identifier that states which page
++ * it resides in.  Otherwise, returns NULL for ordinary functions. */
++const char *
++far_functionp (rtx x)
++{
++	tree decl, decl_type;
++	const char *page;
++
++	/* Find the FUNCTION_DECL corresponding to the rtx being called. */
++	decl = call_target_decl (x);
++	if (decl == NULL_TREE)
++		return NULL;
++
++	/* See if the function has the new 'banked' attribute.  These
++	 * are numeric instead of text */
++	page = m6809_get_decl_bank (decl);
++	if (page)
++		return page;
++
++	/* No, lookup the type of the function and see if the type
++	 * specifies far or not. */
++	decl_type = TREE_TYPE (decl);
++	if (decl_type == NULL_TREE)
++		return NULL;
++	return far_function_type_p (decl_type);
++}
++
++
++
++/** Outputs the assembly language for a far call. */
++void
++output_far_call_insn (rtx *operands, int has_return)
++{
++	static char page_data[64];
++	const char *called_page;
++
++  /* The logic is the same for functions whether or not there
++	* is a return value.  Skip over the return value in this
++	* case, so that the call location is always operands[0].  */
++  if (has_return)
++	  operands++;
++
++  /* Get the name of the page being called */
++  called_page = far_functionp (operands[0]);
++
++#if 0 /* TODO : broken logic */
++  /* See if the called page name is a 'bank' */
++  if (isdigit (*called_page))
++  {
++    /* New style banking */
++	 if (!strcmp (called_page, current_bank_name))
++	 {
++	 	/* Same page */
++  	  	output_asm_insn ("jsr\t%0", operands);
++	 }
++	 else
++	 {
++	 	/* Different page */
++		output_asm_insn ("jsr\t__far_call_handler\t;new style", operands);
++  	  	output_asm_insn ("\t.dw\t%0", operands);
++		sprintf (page_data, "\t.db\t%s", called_page);
++	 	output_asm_insn (page_data, operands);
++	 }
++	 return;
++  }
++#endif
++
++  /* Are we calling a different page than we are running in? */
++  if (!strcmp (called_page, far_code_page))
++  {
++    /* Same page : no need to execute a far call */
++		if (flag_pic)
++			output_asm_insn ("lbsr\t%C0", operands);
++		else
++			output_asm_insn ("jsr\t%0", operands);
++  }
++  else
++  {
++    /* Different page : need to emit far call thunk */
++
++    /* First output a call to the thunk for making far calls. */
++		if (flag_pic)
++			output_asm_insn ("lbsr\t__far_call_handler", operands);
++		else
++			output_asm_insn ("jsr\t__far_call_handler\t;old style", operands);
++  
++    /* Now output the name of the call site */
++    output_asm_insn ("\t.dw\t%C0", operands);
++  
++    /* Finally output the page number */
++    sprintf (page_data, "\t.db\t%s", far_functionp (operands[0]));
++    output_asm_insn (page_data, operands);
++  }
++}
++
++
++int
++m6809_init_cumulative_args (CUMULATIVE_ARGS cum ATTRIBUTE_UNUSED,
++     tree fntype,
++     rtx libname ATTRIBUTE_UNUSED)
++{
++	cum = 0;
++
++	/* For far functions, the current implementation does not allow for
++	 * stack parameters.  So note whenever the called function is far
++	 * and in a different page than the current one; such a function
++	 * should give an error if a stack parameter is generated. */
++	if (fntype)
++	{
++		const char *called_page = far_function_type_p (fntype);
++		if (called_page && strcmp (called_page, far_code_page) && !TARGET_FAR_STACK_PARAM)
++			cum |= CUM_STACK_INVALID;
++	}
++
++	if (fntype && TYPE_ARG_TYPES (fntype) != 0 &&
++		(TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))
++	{
++		/* has variable arguments, cannot use registers */
++		cum |= (CUM_X_MASK | CUM_B_MASK | CUM_STACK_ONLY);
++	}
++
++	if (m6809_abi_version == M6809_ABI_VERSION_STACK)
++	{
++		/* cannot use registers ; only use the stack */
++		cum |= (CUM_STACK_ONLY | CUM_X_MASK | CUM_B_MASK);
++	}
++
++	return cum;
++}
++
++
++rtx
++m6809_function_arg_on_stack (CUMULATIVE_ARGS *cump)
++{
++	if (*cump & CUM_STACK_INVALID)
++	{
++		*cump &= ~CUM_STACK_INVALID;
++		error ("far function needs stack, will not work");
++	}
++	return NULL_RTX;
++}
++
++void m6809_asm_trampoline_template(FILE *f)
++{
++	fprintf(f, "ldy #0000\n");
++	fprintf(f, "jmp 0x0000\n");
++}
++
++/*
++ * Trampoline output:
++ *
++ * ldu #&cxt      4 bytes   --LDY- ?? ??
++ * jmp fnaddr     3 bytes   JMP ?? ??
++ */
++void
++m6809_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
++{
++	rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
++	/* TODO - optimize by generating the entire trampoline code here,
++	 * and removing the template altogether, since there are only two
++	 * bytes there that matter. */
++	emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 2)), cxt);
++	emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, 5)), fnaddr);
++}
++
++
++/** Echo the version of the compiler and the name of the source file
++ * at the beginning of each assembler output file.  asm_out_file
++ * is a global FILE * pointing to the output stream. */
++void
++m6809_asm_file_start (void)
++{
++	const char *module_name;
++
++	fprintf (asm_out_file, "\n;;; gcc for m6809 : %s %s\n",
++		__DATE__, __TIME__);
++	fprintf (asm_out_file, ";;; %s\n", version_string);
++
++	fprintf (asm_out_file, ";;; ABI version %d\n", m6809_abi_version);
++	fprintf (asm_out_file, ";;; %s\n",
++		(TARGET_BYTE_INT ? "-mint8" : "-mint16"));
++	if (TARGET_EXPERIMENT)
++		fprintf (asm_out_file, ";;; -mexperiment\n");
++	if (TARGET_WPC)
++		fprintf (asm_out_file, ";;; -mwpc\n");
++	if (TARGET_6309)
++		fprintf (asm_out_file, ";;; -m6309\n");
++
++	/* Print the name of the module, which is taken as the base name
++	 * of the input file.
++	 * See the 'User-Defined Symbols' section of the assembler
++	 * documentation for the rules on valid symbols.
++	 */
++	module_name = lbasename (main_input_filename);
++
++	fprintf (asm_out_file, "\t.module\t");
++
++	if (*module_name >= '0' && *module_name <= '9')
++		fprintf (asm_out_file, "_");
++
++	while (*module_name)
++	{
++		if ((*module_name >= '0' && *module_name <= '9')
++			|| (*module_name >= 'A' && *module_name <= 'Z')
++			|| (*module_name >= 'a' && *module_name <= 'z')
++			|| *module_name == '$'
++			|| *module_name == '.'
++			|| *module_name == '_')
++		{
++			fprintf (asm_out_file, "%c", *module_name);
++		}
++		else
++		{
++			fprintf (asm_out_file, "_");
++		}
++		module_name++;
++	}
++
++	fprintf (asm_out_file, "\n");
++}
++
++
++/** Returns true if prologue/epilogue code is required for the
++ * current function being compiled.
++ *
++ * This is just the inverse of whether the function is declared as
++ * 'naked'.
++ */
++int
++prologue_epilogue_required (void)
++{
++	return !m6809_current_function_has_type_attr_p ("naked")
++		&& !m6809_current_function_has_type_attr_p ("noreturn");
++}
++
++
++/** Expand RTL for function entry */
++void
++emit_prologue_insns (void)
++{
++  rtx insn;
++  unsigned int live_regs = m6809_get_live_regs ();
++  unsigned int frame_size = get_frame_size ();
++
++  /* Save all registers used, including the frame pointer */
++  if (live_regs && !m6809_current_function_has_type_attr_p ("interrupt"))
++  {
++    insn = emit_insn (
++      gen_rtx_register_pushpop (UNSPEC_PUSH_RS, live_regs));
++    RTX_FRAME_RELATED_P (insn) = 1;
++  }
++
++  /* Allocate space for local variables */
++  if (frame_size != 0)
++  {
++    insn = emit_insn (gen_rtx_stack_adjust (MINUS, frame_size));
++    RTX_FRAME_RELATED_P (insn) = 1;
++  }
++
++  /* Set the frame pointer if it is needed */
++  if (frame_pointer_needed)
++  {
++    insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
++    RTX_FRAME_RELATED_P (insn) = 1;
++  }
++}
++
++
++/** Expand RTL for function exit */
++void
++emit_epilogue_insns (bool sibcall_p)
++{
++  unsigned int live_regs = m6809_get_live_regs ();
++  unsigned int frame_size = get_frame_size ();
++
++  if (frame_size != 0)
++    emit_insn (gen_rtx_stack_adjust (PLUS, frame_size));
++
++  if (sibcall_p)
++  {
++    if (live_regs)
++      emit_insn (gen_rtx_register_pushpop (UNSPEC_POP_RS, live_regs));
++  }
++  else
++  {
++    if (live_regs && !m6809_current_function_has_type_attr_p ("interrupt"))
++        emit_insn (
++          gen_rtx_register_pushpop (UNSPEC_POP_RS, PC_REGBIT | live_regs));
++  
++    if (m6809_current_function_has_type_attr_p ("interrupt"))
++      emit_jump_insn (gen_return_rti ());
++    else
++      emit_jump_insn (gen_return_rts ());
++  }
++}
++
++#if 0
++/** Predefine some preprocessor names according to the currently
++ * selected compiler options */
++void
++m6809_cpu_cpp_builtins (void)
++{
++	if (TARGET_6309)
++	{
++		builtin_define_std ("__M6309__");
++		builtin_define_std ("__m6309__");
++	}
++	else
++	{
++		builtin_define_std ("__M6809__");
++		builtin_define_std ("__m6809__");
++	}
++
++	if (TARGET_BYTE_INT)
++		builtin_define_std ("__int8__");
++	else
++		builtin_define_std ("__int16__");
++
++	switch (m6809_abi_version)
++	{
++		case M6809_ABI_VERSION_STACK:
++			builtin_define_std ("__regargs__");
++			builtin_define_std ("__ABI_STACK__");
++			break;
++		case M6809_ABI_VERSION_REGS:
++			builtin_define_std ("__ABI_REGS__");
++			break;
++		case M6809_ABI_VERSION_BX:
++			builtin_define_std ("__ABI_BX__");
++			break;
++		default:
++			break;
++	}
++
++	if (TARGET_WPC)
++		builtin_define_std ("__WPC__");
++
++	if (TARGET_DRET)
++		builtin_define_std ("__DRET__");
++}
++#endif
++
++#define MAX_ASM_ASCII_STRING 48
++
++void
++m6809_output_ascii (FILE *fp, const char *str, unsigned long size)
++{
++	unsigned long i;
++	bool use_ascii = true;
++
++	/* If the size is too large, then break this up into multiple
++	outputs.  The assembler can only output roughly 48 bytes at a
++	time.  Note that if there are lots of escape sequences in
++	the string, this may fail. */
++	if (size > MAX_ASM_ASCII_STRING)
++	{
++		m6809_output_ascii (fp, str, MAX_ASM_ASCII_STRING);
++		m6809_output_ascii (fp, str + MAX_ASM_ASCII_STRING, 
++			size - MAX_ASM_ASCII_STRING);
++		return;
++	}
++
++	/* Check for 8-bit codes, which cannot be embedded in an .ascii */
++	for (i = 0; i < size; i++)
++	{
++		int c = str[i] & 0377;
++		if (c >= 0x80)
++		{
++			use_ascii = false;
++			break;
++		}
++	}
++
++	if (use_ascii)
++		fprintf (fp, "\t.ascii \"");
++
++	for (i = 0; i < size; i++)
++	{
++		int c = str[i] & 0377;
++
++		if (use_ascii)
++		{
++		/* Just output the plain character if it is printable,
++		otherwise output the escape code for the character.
++		The assembler recognizes the same C-style octal escape sequences,
++		except that it only supports 7-bit codes. */
++		if (c >= ' ' && c < 0177 && c != '\\' && c != '"')
++  			putc (c, fp);
++		else switch (c) 
++		{
++			case '\n':
++#ifndef TARGET_COCO
++				fputs ("\\n", fp);
++				break;
++#endif
++				/* On the CoCo, we fallthrough and treat '\n' like '\r'. */
++			case '\r':
++				fputs ("\\r", fp);
++				break;
++			case '\t':
++				fputs ("\\t", fp);
++				break;
++			case '\f':
++				fputs ("\\f", fp);
++				break;
++			case 0:
++				fputs ("\\0", fp);
++				break;
++			default:
++				fprintf (fp, "\\%03o", c);
++				break;
++		}
++		}
++		else
++		{
++			fprintf (fp, "\t.byte\t0x%02X\n", c);
++		}
++	}
++
++	if (use_ascii)
++		fprintf (fp, "\"\n");
++}
++
++
++void
++m6809_output_quoted_string (FILE *asm_file, const char *string)
++{
++	char c;
++
++	if (strlen (string) > MAX_ASM_ASCII_STRING)
++	{
++		/* The string length is too large.  We'll have to truncate it.
++		This is only called from debugging functions, so it's usually
++		not critical. */
++
++		char truncated_string[MAX_ASM_ASCII_STRING+1];
++
++		/* Copy as many characters as we can. */
++		strncpy (truncated_string, string, MAX_ASM_ASCII_STRING);
++		truncated_string[MAX_ASM_ASCII_STRING] = '\0';
++		string = truncated_string;
++	}
++
++	/* Copied from toplev.c */
++
++	putc ('\"', asm_file);
++	while ((c = *string++) != 0) {
++		if (ISPRINT (c)) {
++			if (c == '\"' || c == '\\')
++				putc ('\\', asm_file);
++			putc (c, asm_file);
++		}
++      else
++			fprintf (asm_file, "\\%03o", (unsigned char) c);
++	}
++	putc ('\"', asm_file);
++}
++
++
++/** Output the assembly code for a shift instruction where the
++ * shift count is not constant. */
++void
++m6809_output_shift_insn (int rtx_code, rtx *operands)
++{
++	struct shift_opcode *op;
++
++	if (GET_CODE (operands[2]) == CONST_INT)
++		abort ();
++
++	if (optimize_size && GET_MODE (operands[0]) == HImode)
++	{
++		switch (rtx_code)
++		{
++			case ASHIFT:
++				output_asm_insn ("jsr\t_ashlhi3", operands);
++				break;
++			case ASHIFTRT:
++				output_asm_insn ("jsr\t_ashrhi3", operands);
++				break;
++			case LSHIFTRT:
++				output_asm_insn ("jsr\t_lshrhi3", operands);
++				break;
++		}
++	}
++	else if (GET_MODE (operands[0]) == HImode)
++	{
++		switch (rtx_code)
++		{
++			case ASHIFT:
++				m6809_gen_register_shift (operands, "aslb", "rola");
++				break;
++			case ASHIFTRT:
++				m6809_gen_register_shift (operands, "asra", "rorb");
++				break;
++			case LSHIFTRT:
++				m6809_gen_register_shift (operands, "lsra", "rorb");
++				break;
++		}
++	}
++	else
++	{
++		switch (rtx_code)
++		{
++			case ASHIFT:
++				m6809_gen_register_shift (operands, "aslb", NULL);
++				break;
++			case ASHIFTRT:
++				m6809_gen_register_shift (operands, "asrb", NULL);
++				break;
++			case LSHIFTRT:
++				m6809_gen_register_shift (operands, "lsrb", NULL);
++				break;
++		}
++	}
++}
++
++
++void
++m6809_emit_move_insn (rtx dst, rtx src)
++{
++	emit_insn (gen_rtx_SET (VOIDmode, dst, src));
++	if (ACC_A_REG_P (dst))
++		emit_insn (gen_rtx_USE (VOIDmode, dst));
++}
++
++
++/** Split a complex shift instruction into multiple CPU
++ * shift instructions. */
++void
++m6809_split_shift (enum rtx_code code, rtx *operands)
++{
++	enum machine_mode mode;
++	int count;
++
++	mode = GET_MODE (operands[0]);
++	count = INTVAL (operands[2]);
++	
++	/* Handle a shift count outside the range of 0 .. N-1, where
++	 * N is the mode size in bits.  We normalize the count, and
++	 * for negative counts we also invert the direction of the
++	 * shift. */
++	if ((count < 0) || (count >= 8 * GET_MODE_SIZE (mode)))
++	{
++		if (count < 0)
++		{
++			count = -count;
++			code = (code == ASHIFT) ? ASHIFTRT : ASHIFT;
++		}
++		count %= (8 * GET_MODE_SIZE (mode));
++		m6809_emit_move_insn (operands[0],
++			gen_rtx_fmt_ee (code, mode, operands[1],
++				gen_rtx_CONST_INT (VOIDmode, count)));
++	}
++
++	/* Handle shift by zero explicitly as a no-op. */
++	if (count == 0)
++	{
++		emit_insn (gen_nop ());
++		return;
++	}
++
++	/* Decompose the shift by a constant N > 8 into two
++	 * shifts, first by 8 and then by N-8.
++	 * This "speeds up" the process for large shifts that would be
++	 * handled below, but allows for some optimization.
++	 * In some cases shift by 8 can be implemented fast.  If an
++	 * instruction to shift by 8 is defined, it will be used here;
++	 * otherwise it will be further decomposed as below. */
++	if (mode == HImode && count > 8)
++	{
++		rtx output = operands[0];
++
++		m6809_emit_move_insn (operands[0],
++			gen_rtx_fmt_ee (code, mode, operands[1],
++				gen_rtx_CONST_INT (VOIDmode, 8)));
++
++		/* Unsigned shifts always produce a zero in either the
++		 * upper or lower half of the output; then, that part
++		 * does not need to be shifted anymore.  We modify the
++		 * output and the subsequent instructions to operate in
++		 * QImode only on the relevant part. */
++		if (REG_P (output))
++		{
++			if (code == ASHIFT)
++			{
++				output = gen_rtx_REG (QImode, HARD_A_REGNUM);
++				mode = QImode;
++			}
++			else
++			{
++				output = gen_rtx_REG (QImode, HARD_D_REGNUM);
++				mode = QImode;
++			}
++		}
++
++		m6809_emit_move_insn (output,
++			gen_rtx_fmt_ee (code, mode, copy_rtx (output), 
++				gen_rtx_CONST_INT (VOIDmode, count-8)));
++		return;
++	}
++
++	/* Rewrite the unsigned shift of an 8-bit register by a large constant N
++	 * (near to the maximum of 8) as a rotate and mask. */
++	if (mode == QImode && REG_P (operands[0]) && count >= ((code == ASHIFTRT) ? 7 : 6))
++	{
++		unsigned int mask;
++		unsigned int was_signed = (code == ASHIFTRT);
++
++		code = (code == ASHIFT) ? ROTATERT : ROTATE;
++		if (code == ROTATE)
++			mask = (count == 6) ? 0x03 : 0x01;
++		else
++			mask = (count == 6) ? 0xC0 - 0x100 : 0x80 - 0x100;
++		count = 9 - count;
++
++		do {
++			m6809_emit_move_insn (operands[0],
++				gen_rtx_fmt_ee (code, QImode, operands[1], const1_rtx));
++		} while (--count != 0);
++
++		m6809_emit_move_insn (operands[0],
++			gen_rtx_fmt_ee (AND, QImode, operands[1],
++				gen_rtx_CONST_INT (VOIDmode, mask)));
++
++		if (was_signed)
++		{
++			emit_insn (gen_negqi2 (operands[0], copy_rtx (operands[0])));
++			if (ACC_A_REG_P (operands[0]))
++				emit_insn (gen_rtx_USE (VOIDmode, operands[0]));
++		}
++		return;
++	}
++
++	/* Decompose the shift by any constant N > 1 into a sequence
++	 * of N shifts.
++	 * This is done recursively, by creating a shift by 1 and a
++	 * shift by N-1, as long as N>1. */
++	if (count > 1)
++	{
++		m6809_emit_move_insn (operands[0],
++			gen_rtx_fmt_ee (code, mode, operands[1], const1_rtx));
++	
++		m6809_emit_move_insn (operands[0],
++			gen_rtx_fmt_ee (code, mode, operands[1], 
++				gen_rtx_CONST_INT (VOIDmode, count-1)));
++		return;
++	}
++	
++	/* Decompose the single shift of a 16-bit quantity into two
++	 * CPU instructions, one for each 8-bit half.
++	 */
++	if (mode == HImode && count == 1)
++	{
++		rtx first, second;
++		enum rtx_code rotate_code;
++
++		rotate_code = (code == ASHIFT) ? ROTATE : ROTATERT;
++
++		/* Split the operand into two 8-bit entities.
++		 * FIRST is the one that will get shifted via a regular CPU
++		 * instruction.
++		 * SECOND is the one that will have the result of the first shift
++		 * rotated in.
++		 *
++		 * We initialize first and second as if we are doing a left shift,
++		 * then swap the operands if it's a right shift.
++		 */
++		if (REG_P (operands[0]))
++		{
++			first = gen_rtx_REG (QImode, HARD_D_REGNUM); /* HARD_B_REGNUM? */
++			second = gen_rtx_REG (QImode, HARD_A_REGNUM);
++		}
++		else
++		{
++			first = adjust_address (operands[0], QImode, 1);
++			second = adjust_address (operands[0], QImode, 0);
++		}
++
++		if (rotate_code == ROTATERT)
++		{
++			rtx tmp; tmp = first; first = second; second = tmp;
++		}
++
++		/* Decompose into a shift and a rotate instruction. */
++		m6809_emit_move_insn (first,
++			gen_rtx_fmt_ee (code, QImode, copy_rtx (first), const1_rtx));
++		m6809_emit_move_insn (second,
++			gen_rtx_fmt_ee (rotate_code, QImode, copy_rtx (second), const1_rtx));
++		return;
++	}
++}
++
++
++/** Adjust register usage based on compile-time flags. */
++void
++m6809_conditional_register_usage (void)
++{
++	unsigned int soft_regno;
++
++#ifdef CONFIG_SOFT_REGS_ALWAYS
++	m6809_soft_regs = CONFIG_SOFT_REGS_ALWAYS;
++#else
++	if (!m6809_soft_reg_count)
++		return;
++	m6809_soft_regs = atoi (m6809_soft_reg_count);
++#endif
++
++	if (m6809_soft_regs == 0)
++		return;
++
++	if (m6809_soft_regs > NUM_M_REGS)
++		m6809_soft_regs = NUM_M_REGS;
++
++	/* Registers are marked FIXED by default.  Free up if
++	the user wishes. */
++	for (soft_regno = 1; soft_regno < m6809_soft_regs; soft_regno++)
++	{
++		fixed_regs[SOFT_M0_REGNUM + soft_regno] = 0;
++
++		/* Mark the softregs as call-clobbered, so that they need
++		 * not be saved/restored on function entry/exit. */
++		call_used_regs[SOFT_M0_REGNUM + soft_regno] = 1;
++	}
++}
++
++
++/** Return a RTX representing how to return a value from a function.
++  VALTYPE gives the type of the value, FUNC identifies the function
++  itself.
++
++  In general, we only care about the width of the result. */
++rtx
++m6809_function_value (const tree valtype, const tree func ATTRIBUTE_UNUSED)
++{
++   unsigned int regno;
++	enum machine_mode mode;
++
++	/* Get the mode (i.e. width) of the result. */
++	mode = TYPE_MODE (valtype);
++
++	if (lookup_attribute ("boolean", TYPE_ATTRIBUTES (valtype)))
++      regno = HARD_Z_REGNUM;
++   else if (mode == QImode || (TARGET_DRET && mode == HImode))
++      regno = HARD_D_REGNUM;
++   else
++      regno = HARD_X_REGNUM;
++   return gen_rtx_REG (mode, regno);
++}
++
++
++/** Return 1 if REGNO is possibly needed to return the result
++of a function, 0 otherwise. */
++int
++m6809_function_value_regno_p (unsigned int regno)
++{
++	if (regno == HARD_Z_REGNUM)
++		return 1;
++	else if ((TARGET_BYTE_INT || TARGET_DRET) && regno == HARD_D_REGNUM)
++		return 1;
++	else if (!TARGET_DRET && regno == HARD_X_REGNUM)
++		return 1;
++	else
++		return 0;
++}
++
++
++#ifdef TRACE_PEEPHOLE
++int
++m6809_match_peephole2 (unsigned int peephole_id, unsigned int stage)
++{
++	if (stage == PEEP_END)
++	{
++		printf ("%s: peephole %d pattern and predicate matched\n",
++			main_input_filename, peephole_id);
++		fflush (stdout);
++	}
++	else if (stage == PEEP_COND)
++	{
++		printf ("%s: peephole %d? at least pattern matched\n",
++			main_input_filename, peephole_id);
++		fflush (stdout);
++	}
++	return 1;
++}
++#else
++int
++m6809_match_peephole2 (unsigned int peephole_id ATTRIBUTE_UNUSED,
++	unsigned int stage ATTRIBUTE_UNUSED)
++{
++	return 1;
++}
++#endif /* TRACE_PEEPHOLE */
++
++
++/** Return 1 if it is OK to store a value of MODE in REGNO. */
++int
++m6809_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
++{
++   /* Soft registers, as they are just memory, can really hold
++   values of any type.  However we restrict them to values of
++   size HImode or QImode to prevent exhausting them for larger
++   values.
++      Word values cannot be placed into the first soft register,
++   as it is the low byte that is being placed there, which
++   corrupts the (non-soft) register before it. */
++   if (M_REGNO_P (regno))
++   {
++      switch (GET_MODE_SIZE (mode))
++      {
++         case 1:
++            return 1;
++         case 2:
++            return regno != SOFT_M0_REGNUM;
++         default:
++            return 0;
++      }
++   }
++
++   /* VOIDmode can be stored anywhere */
++   else if (mode == VOIDmode)
++      return 1;
++
++   /* Zero is a reserved register, but problems occur if we don't
++   say yes here??? */
++   else if (regno == 0)
++      return 1;
++
++   /* For other registers, return true only if the requested size
++   exactly matches the hardware size. */
++   else if ((G_REGNO_P (regno)) && (GET_MODE_SIZE (mode) == 2))
++      return 1;
++   else if ((BYTE_REGNO_P (regno)) && (GET_MODE_SIZE (mode) == 1))
++      return 1;
++   else
++      return 0;
++}
++
++
++/* exp is the call expression.  DECL is the called function,
++ * or NULL for an indirect call */
++bool
++m6809_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
++{
++	tree type, arg;
++   const char *name;
++	bool result = 0;
++	int argcount = 0;
++	int step = 1;
++
++	/* If there is no DECL, it is an indirect call.
++	 * Never optimize this??? */
++	if (decl == NULL)
++		goto done;
++
++	/* Never allow an interrupt handler to be optimized this way. */
++	if (m6809_function_has_type_attr_p (decl, "interrupt"))
++		goto done;
++
++	/* Skip sibcall if the type can't be found for
++	 * some reason */
++	step++;
++	name = IDENTIFIER_POINTER (DECL_NAME (decl));
++	type = TREE_TYPE (decl);
++	if (type == NULL)
++		goto done;
++
++	/* Skip sibcall if the target is a far function */
++	step++;
++	if (far_function_type_p (type) != NULL)
++		goto done;
++
++	/* Skip sibcall if the called function's arguments are
++	 * variable */
++	step++;
++	if (TYPE_ARG_TYPES (type) == NULL)
++		goto done;
++
++	/* Allow sibcalls in other cases. */
++	result = 1;
++done:
++	/* printf ("%s ok for sibcall? %s, step %d, args %d\n", name, result ? "yes" : "no", step, argcount); */
++	return result;
++}
++
++
++/** Emit code for the 'casesi' pattern.
++ * This pattern is only used in 8-bit mode, and can be disabled
++ * with -mold-case there as well.  The rationale for this is to
++ * do a better job than the simpler but well-tested 'tablejump'
++ * method.
++ *
++ * For small jumptables, where the switch expression is an
++ * 8-bit value, the lookup can be done more efficiently
++ * using the "B,X" style index mode. */
++void
++m6809_do_casesi (rtx index, rtx lower_bound, rtx range,
++	rtx table_label, rtx default_label)
++{
++	enum machine_mode mode;
++	rtx scaled;
++	rtx table_in_reg;
++
++	/* expr.c has to be patched so that it does not promote
++	 * the expression to SImode, but rather to HImode.
++	 * Fail now if that isn't the case. */
++	if (GET_MODE_SIZE (GET_MODE (index)) > GET_MODE_SIZE (HImode))
++		error ("try_casesi promotion bug");
++
++	/* Determine whether or not we are going to work primarily in
++	 * QImode or HImode.  This depends on the size of the index
++	 * into the lookup table.  QImode can only be used when the
++	 * index is less than 0x40, since it will be doubled but
++	 * must remain unsigned. */
++	if ((GET_CODE (range) == CONST_INT) && (INTVAL (range) < 0x40))
++		mode = QImode;
++	else
++		mode = HImode;
++
++	/* Convert to QImode if necessary */
++	if (mode == QImode)
++	{
++		index = gen_lowpart_general (mode, index);
++		lower_bound = gen_lowpart_general (mode, lower_bound);
++	}
++
++	/* Translate from case value to table index by subtraction */
++	if (lower_bound != const0_rtx)
++		index = expand_binop (mode, sub_optab, index, lower_bound,
++			NULL_RTX, 0, OPTAB_LIB_WIDEN);
++
++	/* Emit compare-and-jump to test for index out-of-range */
++	emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
++		default_label);
++
++	/* Put the table address is in a register */
++	table_in_reg = gen_reg_rtx (Pmode);
++	emit_move_insn (table_in_reg, gen_rtx_LABEL_REF (Pmode, table_label));
++
++	/* Emit table lookup and jump */
++	if (mode == QImode)
++	{
++		/* Scale the index */
++		scaled = gen_reg_rtx (QImode);
++		emit_insn (gen_ashlqi3 (scaled, index, const1_rtx));
++
++		/* Emit the jump */
++		emit_jump_insn (gen_tablejump_short_offset (scaled, table_in_reg));
++	}
++	else
++	{
++		/* Scale the index */
++		emit_insn (gen_ashlhi3 (index, index, const1_rtx));
++
++		/* Emit the jump */
++		emit_jump_insn (gen_tablejump_long_offset (index, table_in_reg));
++	}
++
++	/* Copied from expr.c */
++	if (!CASE_VECTOR_PC_RELATIVE && !flag_pic)
++		emit_barrier ();
++}
++
++
++/** Output the assembly code for a 32-bit add/subtract. */
++void
++m6809_output_addsi3 (int rtx_code, rtx *operands)
++{
++	rtx xoperands[8];
++	rtx dst = operands[0];
++
++	/* Prepare the operands by splitting each SImode into two HImodes
++	that can be operated independently.  The high word of operand 1
++	is further divided into two QImode components for use with 'adc'
++	style instructions. */
++	xoperands[7] = operands[3];
++
++	xoperands[0] = adjust_address (dst, HImode, 2);
++	xoperands[3] = adjust_address (dst, HImode, 0);
++
++#if 1
++	xoperands[2] = adjust_address (operands[1], HImode, 2);
++	xoperands[6] = adjust_address (operands[1], HImode, 0);
++
++	/* Operand 2 may be a MEM or a CONST_INT */
++	if (GET_CODE (operands[2]) == CONST_INT)
++	{
++		xoperands[1] = gen_int_mode (INTVAL (operands[2]) & 0xFFFF, HImode);
++		xoperands[4] = gen_int_mode ((INTVAL (operands[2]) >> 24) & 0xFF, QImode);
++		xoperands[5] = gen_int_mode ((INTVAL (operands[2]) >> 16) & 0xFF, QImode);
++	}
++	else
++	{
++		xoperands[1] = adjust_address (operands[2], HImode, 2);
++		xoperands[4] = adjust_address (operands[2], QImode, 0);
++		xoperands[5] = adjust_address (operands[2], QImode, 1);
++	}
++
++#endif
++
++#if 0
++	xoperands[1] = adjust_address (operands[1], HImode, 2);
++	xoperands[4] = adjust_address (operands[1], QImode, 0);
++	xoperands[5] = adjust_address (operands[1], QImode, 1);
++
++	/* Operand 2 may be a MEM or a CONST_INT */
++	if (GET_CODE (operands[2]) == CONST_INT)
++	{
++		xoperands[2] = gen_int_mode ((INTVAL (operands[2])) & 0xFFFF, HImode);
++		xoperands[6] = gen_int_mode ((INTVAL (operands[2]) >> 16) & 0xFFFF, HImode);
++	}
++	else
++	{
++		xoperands[2] = adjust_address (operands[2], HImode, 2);
++		xoperands[6] = adjust_address (operands[2], HImode, 0);
++	}
++#endif
++
++	/* Output the assembly code. */
++	if (rtx_code == PLUS)
++	{
++		output_asm_insn ("ld%7\t%2", xoperands);
++		output_asm_insn ("add%7\t%1", xoperands);
++		output_asm_insn ("st%7\t%0", xoperands);
++		output_asm_insn ("ld%7\t%6", xoperands);
++		output_asm_insn ("adcb\t%5", xoperands);
++		output_asm_insn ("adca\t%4", xoperands);
++		output_asm_insn ("st%7\t%3", xoperands);
++	}
++	else
++	{
++		output_asm_insn ("ld%7\t%2", xoperands);
++		output_asm_insn ("sub%7\t%1", xoperands);
++		output_asm_insn ("st%7\t%0", xoperands);
++		output_asm_insn ("ld%7\t%6", xoperands);
++		output_asm_insn ("sbcb\t%5", xoperands);
++		output_asm_insn ("sbca\t%4", xoperands);
++		output_asm_insn ("st%7\t%3", xoperands);
++	}
++}
++
++
++#if 0
++/** Output the assembly code for a 32-bit shift.
++Operands 0 and 1 must be the same rtx, forced by a matching
++constraint.  Operand 2 must be a CONST_INT.  Operand 3 is
++"d" in case a temporary reg is needed. */
++void
++m6809_output_shiftsi3 (int rtx_code, rtx *operands)
++{
++	unsigned int count = INTVAL (operands[2]) % 32;
++	unsigned int size = 4; /* sizeof (SImode) */
++	int s;
++	rtx xoperands[4];
++	int op;
++	int start, end, step;
++
++	/* Initialize */
++	if (rtx_code == ASHIFT)
++	{
++		start = size-1;
++		end = -1;
++		step = -1;
++	}
++	else
++	{
++		start = 0;
++		end = size;
++		step = 1;
++	}
++
++	xoperands[2] = operands[2];
++	xoperands[3] = operands[3];
++
++	if (count <= 0)
++		abort ();
++	if (rtx_code == ROTATE || rtx_code == ROTATERT)
++		abort ();
++
++	/* Extract bit shifts over 16 bits by HImode moves. */
++	if (count >= 16)
++	{
++	}
++
++	/* Extract bit shifts over 8 bits by QImode moves. */
++	if (count >= 8)
++	{
++	}
++
++	/* Iterate over the number of bits to be shifted. */
++	while (count > 0)
++	{
++		/* Each bit to be shifted requires 1 proper bit shift
++		and 3 rotates. */
++
++		/* First, do the arithmetic/logical shift.  Left shifts
++		start from the LSB; right shifts start from the MSB. */
++		xoperands[0] = adjust_address (operands[0], QImode, start);
++		switch (rtx_code)
++		{
++			case ASHIFT:
++				output_asm_insn ("asl\t%0", xoperands);
++				start--;
++				break;
++			case ASHIFTRT:
++				output_asm_insn ("asr\t%0", xoperands);
++				start++;
++				break;
++			case LSHIFTRT:
++				output_asm_insn ("lsr\t%0", xoperands);
++				start++;
++				break;
++		}
++
++		/* Next, rotate the other bytes */
++		for (s = start; s != end; s += step)
++		{
++			xoperands[0] = adjust_address (operands[0], QImode, s);
++			switch (rtx_code)
++			{
++				case ASHIFT:
++					output_asm_insn ("rol\t%0", xoperands);
++					break;
++				case ASHIFTRT:
++				case LSHIFTRT:
++					output_asm_insn ("ror\t%0", xoperands);
++					break;
++			}
++		}
++		count--;
++	}
++}
++#endif
++
++int
++power_of_two_p (unsigned int n)
++{
++	return (n & (n-1)) == 0;
++}
++
++
++int
++m6809_can_eliminate (int from, int to)
++{
++	if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
++		return !frame_pointer_needed;
++	return 1;
++}
++
++
++int
++m6809_initial_elimination_offset (int from, int to)
++{
++	switch (from)
++	{
++		case ARG_POINTER_REGNUM:
++			return get_frame_size () + m6809_get_regs_size (m6809_get_live_regs ());
++		case FRAME_POINTER_REGNUM:
++			return get_frame_size ();
++		default:
++			gcc_unreachable ();
++	}
++}
++
++
++bool
++m6809_frame_pointer_required (void)
++{
++	return false;
++}
++
++
++/* Defines the target-specific hooks structure. */
++struct gcc_target targetm = TARGET_INITIALIZER;
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.h gcc-4.6.1/gcc/config/m6809/m6809.h
+--- gcc-4.6.1-orig/gcc/config/m6809/m6809.h	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/m6809.h	2011-09-18 19:47:50.207654849 -0600
+@@ -0,0 +1,1352 @@
++/* Definitions of target machine for GNU compiler.  MC6809 version.
++
++ MC6809 Version by Tom Jones (jones@sal.wisc.edu)
++ Space Astronomy Laboratory
++ University of Wisconsin at Madison
++
++ minor changes to adapt it to gcc-2.5.8 by Matthias Doerfel
++ ( msdoerfe@informatik.uni-erlangen.de )
++ also added #pragma interrupt (inspired by gcc-6811)
++
++ minor changes to adapt it to gcc-2.8.0 by Eric Botcazou
++ (ebotcazou@multimania.com)
++
++ minor changes to adapt it to egcs-1.1.2 by Eric Botcazou
++ (ebotcazou@multimania.com)
++
++ minor changes to adapt it to gcc-2.95.3 by Eric Botcazou
++ (ebotcazou@multimania.com)
++
++ changes for gcc-3.1.1 by ???
++
++ further changes for gcc-3.1.1 and beyond by Brian Dominy
++ (brian@oddchange.com)
++
++ even more changes for gcc-4.6.1 by William Astle (lost@l-w.ca)
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++
++/* Helper macros for creating strings with macros */
++#define C_STRING(x) C_STR(x)
++#define C_STR(x) #x
++
++/* Certain parts of GCC include host-side includes, which is bad.
++ * Some things that get pulled in need to be undone.
++ */
++#undef HAVE_GAS_HIDDEN
++
++/* Names to predefine in the preprocessor for this target machine.  */
++/*#define TARGET_CPU_CPP_BUILTINS() m6809_cpu_cpp_builtins () */
++#define TARGET_CPU_CPP_BUILTINS() do \
++	{ \
++		if (TARGET_6309) \
++		{ \
++			builtin_define_std ("__M6309__"); \
++			builtin_define_std ("__m6309__"); \
++		} \
++		else \
++		{ \
++			builtin_define_std ("__M6809__"); \
++			builtin_define_std ("__m6809__"); \
++		} \
++ \
++		if (TARGET_BYTE_INT) \
++			builtin_define_std ("__int8__"); \
++		else \
++			builtin_define_std ("__int16__"); \
++ \
++		switch (m6809_abi_version) \
++		{ \
++			case M6809_ABI_VERSION_STACK: \
++				builtin_define_std ("__regargs__"); \
++				builtin_define_std ("__ABI_STACK__"); \
++				break; \
++			case M6809_ABI_VERSION_REGS: \
++				builtin_define_std ("__ABI_REGS__"); \
++				break; \
++			case M6809_ABI_VERSION_BX: \
++				builtin_define_std ("__ABI_BX__"); \
++				break; \
++			default: \
++				break; \
++		} \
++ \
++		if (TARGET_WPC) \
++			builtin_define_std ("__WPC__"); \
++ \
++		if (TARGET_DRET) \
++			builtin_define_std ("__DRET__"); \
++	} while (0)
++
++/* As an embedded target, we have no libc.  */
++#ifndef inhibit_libc
++#define inhibit_libc
++#endif
++
++/* Print subsidiary information on the compiler version in use.  */
++#define TARGET_VERSION fprintf (stderr, " (MC6809)");
++
++/* Run-time compilation parameters selecting different hardware subsets.  */
++/*extern int target_flags; */
++extern short *reg_renumber;	/* def in local_alloc.c */
++
++/* Runtime current values of section names */
++extern int section_changed;
++extern char code_section_op[], data_section_op[], bss_section_op[];
++
++#define WARNING_OPT 0,
++/*extern const char *m6809_abi_version_ptr; */
++extern unsigned int m6809_soft_regs;
++extern unsigned int m6809_abi_version;
++
++/* ABI versions */
++
++#define M6809_ABI_VERSION_STACK 0
++#define M6809_ABI_VERSION_REGS 1
++#define M6809_ABI_VERSION_BX 2
++#define M6809_ABI_VERSION_LATEST  (M6809_ABI_VERSION_BX)
++
++/* Allow $ in identifiers */
++#define DOLLARS_IN_IDENTIFIERS 1
++
++/*--------------------------------------------------------------
++	Target machine storage layout
++--------------------------------------------------------------*/
++
++/* Define this if most significant bit is lowest numbered
++   in instructions that operate on numbered bit-fields.  */
++#define BITS_BIG_ENDIAN 0
++
++/* Define to 1 if most significant byte of a word is the lowest numbered. */
++#define BYTES_BIG_ENDIAN 1
++
++/* Define to 1 if most significant word of a multiword value is the lowest numbered. */
++#define WORDS_BIG_ENDIAN 1
++
++/* Number of bits in an addressible storage unit */
++#define BITS_PER_UNIT 8
++
++/* Width in bits of a "word", or the contents of a machine register.
++ * Although the 6809 has a few byte registers, define this to 16-bits
++ * since this is the natural size of most registers. */
++#define BITS_PER_WORD 16
++
++/* Width of a word, in units (bytes).  */
++#define UNITS_PER_WORD (BITS_PER_WORD/8)
++
++/* Width in bits of a pointer.  See also the macro `Pmode' defined below.  */
++#define POINTER_SIZE 16
++
++/* Allocation boundary (bits) for storing pointers in memory.  */
++#define POINTER_BOUNDARY 8
++
++/* Allocation boundary (bits) for storing arguments in argument list.  */
++/* PARM_BOUNDARY is divided by BITS_PER_WORD in expr.c -- tej */
++#define PARM_BOUNDARY 8
++
++/* Boundary (bits) on which stack pointer should be aligned.  */
++#define STACK_BOUNDARY 8
++
++/* Allocation boundary (bits) for the code of a function.  */
++#define FUNCTION_BOUNDARY 8
++
++/* Alignment of field after `int : 0' in a structure.  */
++#define EMPTY_FIELD_BOUNDARY 8
++
++/* Every structure's size must be a multiple of this.  */
++#define STRUCTURE_SIZE_BOUNDARY 8
++
++/* Largest mode size to use when putting an object, including
++ * a structure, into a register.  By limiting this to 16, no
++ * 32-bit objects will ever be allocated to a pair of hard
++ * registers.  This is a good thing, since there aren't that
++ * many of them.  32-bit objects are only needed for floats
++ * and "long long"s.  Larger values have been tried and did not
++ * work. */
++#define MAX_FIXED_MODE_SIZE 16
++
++/* No data type wants to be aligned rounder than this.  */
++#define BIGGEST_ALIGNMENT 8
++
++/* Define this if move instructions will actually fail to work
++   when given unaligned data.  */
++#define STRICT_ALIGNMENT 0
++
++/*--------------------------------------------------------------
++	 Standard register usage.
++--------------------------------------------------------------*/
++
++/* Register values as bitmasks.
++ * TODO : merge D_REGBIT and B_REGBIT, and treat this as the same
++ * register. */
++#define RSVD1_REGBIT    (1 << HARD_RSVD1_REGNUM)
++#define D_REGBIT			(1 << HARD_D_REGNUM)
++#define X_REGBIT			(1 << HARD_X_REGNUM)
++#define Y_REGBIT			(1 << HARD_Y_REGNUM)
++#define U_REGBIT			(1 << HARD_U_REGNUM)
++#define S_REGBIT			(1 << HARD_S_REGNUM)
++#define PC_REGBIT			(1 << HARD_PC_REGNUM)
++#define Z_REGBIT        (1 << HARD_Z_REGNUM)
++#define A_REGBIT			(1 << HARD_A_REGNUM)
++#define B_REGBIT			(1 << HARD_B_REGNUM)
++#define CC_REGBIT			(1 << HARD_CC_REGNUM)
++#define DP_REGBIT			(1 << HARD_DP_REGNUM)
++#define SOFT_FP_REGBIT  (1 << SOFT_FP_REGNUM)
++#define SOFT_AP_REGBIT  (1 << SOFT_AP_REGNUM)
++#define M_REGBIT(n)		(1 << (SOFT_M0_REGNUM + n))
++
++/* Macros for dealing with set of registers.
++ * A register set is just a bitwise-OR of all the register
++ * bitmask values. */
++
++/* Which registers can hold 8-bits */
++#define BYTE_REGSET \
++	(Z_REGBIT | A_REGBIT | D_REGBIT | CC_REGBIT | DP_REGBIT | SOFT_M_REGBITS)
++
++/* Which registers can hold 16-bits.
++ * Note: D_REGBIT is defined as both an 8-bit and 16-bit register */
++#define WORD_REGSET \
++	(D_REGBIT | X_REGBIT | Y_REGBIT | U_REGBIT | S_REGBIT | PC_REGBIT | SOFT_FP_REGBIT | SOFT_AP_REGBIT | RSVD1_REGBIT)
++
++/* Returns nonzero if a given REGNO is in the REGSET. */
++#define REGSET_CONTAINS_P(regno, regset)  (((1 << (regno)) & (regset)) != 0)
++
++/* Defines related to the number of soft registers supported.
++ * The actual number used may be less depending on -msoft-reg-count.
++ * If you change one of these, you should change them all. */
++#define NUM_M_REGS 8
++#define M_REGS_FIXED 1, 1, 1, 1, 1, 1, 1, 1
++#define M_REGS_CALL_USED 1, 1, 1, 1, 1, 1, 1, 1
++#define HARD_M_REGNUMS \
++   SOFT_M0_REGNUM+0, SOFT_M0_REGNUM+1, SOFT_M0_REGNUM+2, SOFT_M0_REGNUM+3, \
++   SOFT_M0_REGNUM+4, SOFT_M0_REGNUM+5, SOFT_M0_REGNUM+6, SOFT_M0_REGNUM+7
++
++#define SOFT_M_REGBITS  (((1UL << NUM_M_REGS) - 1) << (SOFT_M0_REGNUM))
++
++/* Number of actual hardware registers.
++   The hardware registers are assigned numbers for the compiler
++   from 0 to just below FIRST_PSEUDO_REGISTER.
++   All registers that the compiler knows about must be given numbers,
++   even those that are not normally considered general registers.
++   Make sure the constant below matches the value of SOFT_M0_REGNUM;
++   for some reason, GCC won't compile if that name is used here directly. */
++#ifdef SOFT_M0_REGNUM
++#if (SOFT_M0_REGNUM != 14)
++#error "bad register numbering"
++#endif
++#endif
++#define FIRST_PSEUDO_REGISTER (14 + NUM_M_REGS)
++
++/* 1 for registers that have pervasive standard uses
++   and are not available for the register allocator.
++   The psuedoregisters (M_REGS) are declared fixed here, but
++   will be unfixed if -msoft-reg-count is seen later.  */
++#define FIXED_REGISTERS \
++    {1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, M_REGS_FIXED, }
++  /* -, X, Y, U, S, PC,D, Z, A, B, C, DP,FP,AP,M... */
++
++/* 1 for registers not available across function calls.
++   These must include the FIXED_REGISTERS and also any
++   registers that can be used without being saved.
++   The latter must include the registers where values are returned
++   and the register where structure-value addresses are passed.
++   Aside from that, you can include as many other registers as you like.  */
++#define CALL_USED_REGISTERS \
++    {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, M_REGS_CALL_USED, }
++  /* -, X, Y, U, S, PC,D, Z, A, B, C, DP,FP,AP,M... */
++
++/* Return number of consecutive hard regs needed starting at reg REGNO
++   to hold something of mode MODE.
++	For the 6809, we distinguish between word-length and byte-length
++	registers. */
++#define HARD_REGNO_NREGS(REGNO, MODE) \
++   (REGSET_CONTAINS_P (REGNO, WORD_REGSET) ? \
++		((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) : \
++      (GET_MODE_SIZE (MODE)))
++
++
++/* Value is 1 if hard register REGNO can hold a value
++of machine-mode MODE. */
++#define HARD_REGNO_MODE_OK(REGNO, MODE) m6809_hard_regno_mode_ok (REGNO, MODE)
++
++/* Value is 1 if it is a good idea to tie two pseudo registers
++   when one has mode MODE1 and one has mode MODE2.
++   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
++   for any hard reg, then this must be 0 for correct output.  */
++#define MODES_TIEABLE_P(MODE1, MODE2) 0
++
++/* Specify the registers used for certain standard purposes.
++   The values of these macros are register numbers.  */
++
++/* program counter if referenced as a register */
++#define PC_REGNUM HARD_PC_REGNUM
++
++/* Register to use for pushing function arguments.  */
++#define STACK_POINTER_REGNUM HARD_S_REGNUM
++
++/* Base register for access to local variables of the function.
++ * Before reload, FRAME_POINTER_REGNUM will be used.  Later,
++ * the elimination pass will convert these to STACK_POINTER_REGNUM
++ * if possible, or else HARD_FRAME_POINTER_REGNUM.  The idea is to
++ * avoid tying up a hard register (U) for the frame pointer if
++ * it can be eliminated entirely, making it available for use as
++ * a general register. */
++#define FRAME_POINTER_REGNUM       SOFT_FP_REGNUM
++#define HARD_FRAME_POINTER_REGNUM  HARD_U_REGNUM
++
++/* Define a table of possible eliminations.
++ * The idea is to try to avoid using hard registers for the argument
++ * and frame pointers if they can be derived from the stack pointer
++ * instead, which already has a hard register reserved for it.
++ *
++ * The order of entries in this table will try to convert
++ * ARG_POINTER_REGNUM and FRAME_POINTER_REGNUM into stack pointer
++ * references first, but if that fails, they will be converted to use
++ * HARD_FRAME_POINTER_REGNUM.
++ */
++#define ELIMINABLE_REGS \
++{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
++ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
++ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
++ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }}
++
++/* #define CAN_ELIMINATE(FROM, TO) m6809_can_eliminate (FROM, TO) */
++
++/* Define how to offset the frame or argument pointer to turn it
++ * into a stack pointer reference.  This is based on the way that
++ * the frame is constructed in the function prologue. */
++#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
++	(OFFSET) = m6809_initial_elimination_offset (FROM, TO)
++
++/* Base register for access to arguments of the function.
++ * This is only used prior to reload; no instructions will ever
++ * be output referring to this register. */
++#define ARG_POINTER_REGNUM SOFT_AP_REGNUM
++
++/* Register in which static-chain is passed to a function.  */
++#define STATIC_CHAIN_REGNUM HARD_Y_REGNUM
++
++/* #define CONDITIONAL_REGISTER_USAGE (m6809_conditional_register_usage ()) */
++
++/* Order in which hard registers are allocated to pseudos.
++ *
++ * Since the D register is the only valid reg for 8-bit values
++ * now, avoid using it for 16-bit values by putting it after all
++ * other 16-bits.
++ *
++ * Prefer X first since the first 16-bit function argument goes
++ * there.  We may be able to pass in to a subroutine without
++ * a copy.
++ *
++ * Prefer U over Y since instructions using Y take one extra
++ * byte, and thus one extra cycle to execute.
++ */
++#define REG_ALLOC_ORDER \
++   {  HARD_X_REGNUM, HARD_U_REGNUM, HARD_Y_REGNUM, HARD_D_REGNUM, \
++	   HARD_M_REGNUMS, HARD_S_REGNUM, HARD_PC_REGNUM, \
++		HARD_B_REGNUM, HARD_A_REGNUM, HARD_CC_REGNUM, \
++		HARD_DP_REGNUM, SOFT_FP_REGNUM, SOFT_AP_REGNUM, \
++		6, HARD_Z_REGNUM }
++
++/*--------------------------------------------------------------
++	classes of registers
++--------------------------------------------------------------*/
++
++/* Define the classes of registers for register constraints in the
++   machine description.  Also define ranges of constants.
++
++   One of the classes must always be named ALL_REGS and include all hard regs.
++   If there is more than one class, another class must be named NO_REGS
++   and contain no registers.
++
++   The name GENERAL_REGS must be the name of a class (or an alias for
++   another name such as ALL_REGS).  This is the class of registers
++   that is allowed by "g" or "r" in a register constraint.
++   Also, registers outside this class are allocated only when
++   instructions express preferences for them.
++
++   The classes must be numbered in nondecreasing order; that is,
++   a larger-numbered class must never be contained completely
++   in a smaller-numbered class.
++
++   For any two classes, it is very desirable that there be another
++   class that represents their union.  */
++   
++enum reg_class {
++    NO_REGS,    /* The trivial class with no registers in it */
++    D_REGS,     /* 16-bit (word (HI)) data (D) */
++    ACC_A_REGS, /* The A register */
++    ACC_B_REGS, /* The B register */
++	 X_REGS,     /* The X register */
++	 Z_REGS,     /* The Z (zero-bit) register */
++    Q_REGS,     /* 8-bit (byte (QI)) data (A,B) */
++    M_REGS,     /* 8-bit (byte (QI)) soft registers */
++	 CC_REGS,    /* 8-bit condition code register */
++    I_REGS,     /* An index register (A,B,D) */
++    T_REGS,     /* 16-bit addresses, not including stack or PC (X,Y,U) */
++    A_REGS,     /* 16-bit addresses (X,Y,U,S,PC) */
++	 S_REGS,     /* 16-bit soft registers (FP, AP) */
++	 P_REGS,     /* 16-bit pushable registers (D,X,Y,U); omit PC and S */
++    G_REGS,     /* 16-bit data and address (D,X,Y,U,S,PC) */
++    ALL_REGS,   /* All registers */
++    LIM_REG_CLASSES
++};
++
++#define N_REG_CLASSES (int) LIM_REG_CLASSES
++
++/* Since GENERAL_REGS is a smaller class than ALL_REGS,
++   it is not an alias to ALL_REGS, but to G_REGS. */
++#define GENERAL_REGS G_REGS
++
++/* Give names of register classes as strings for dump file.   */
++#define REG_CLASS_NAMES \
++ {  "NO_REGS", "D_REGS", "ACC_A_REGS", "ACC_B_REGS", "X_REGS", "Z_REGS", "Q_REGS", "M_REGS", \
++	 "CC_REGS", "I_REGS", "T_REGS", "A_REGS", "S_REGS", "P_REGS", "G_REGS", \
++	 "ALL_REGS" }
++
++/* Define which registers fit in which classes.
++   This is an initializer for a vector of HARD_REG_SET
++   of length N_REG_CLASSES.  */
++
++#define D_REGSET	(D_REGBIT)
++#define ACC_A_REGSET (A_REGBIT)
++#define ACC_B_REGSET (D_REGBIT)
++#define X_REGSET (X_REGBIT)
++#define Z_REGSET (Z_REGBIT)
++#define Q_REGSET (D_REGBIT | A_REGBIT)
++#define M_REGSET (SOFT_M_REGBITS)
++#define CC_REGSET (CC_REGBIT)
++#define I_REGSET (A_REGBIT | B_REGBIT | D_REGBIT)
++#define T_REGSET (X_REGBIT | Y_REGBIT | U_REGBIT)
++#define A_REGSET (X_REGBIT | Y_REGBIT | U_REGBIT | S_REGBIT | PC_REGBIT)
++#define S_REGSET (SOFT_FP_REGBIT | SOFT_AP_REGBIT)
++#define P_REGSET (D_REGBIT | X_REGBIT | Y_REGBIT | U_REGBIT)
++#define G_REGSET \
++   (D_REGSET | Q_REGSET | I_REGSET | A_REGSET | M_REGSET | S_REGSET)
++#define ALL_REGSET (G_REGSET)
++
++#define REG_CLASS_CONTENTS { \
++	{0}, \
++	{D_REGSET}, \
++   {ACC_A_REGSET}, \
++   {ACC_B_REGSET}, \
++   {X_REGSET}, \
++   {Z_REGSET}, \
++	{Q_REGSET}, \
++	{M_REGSET}, \
++   {CC_REGSET}, \
++	{I_REGSET}, \
++	{T_REGSET}, \
++	{A_REGSET}, \
++	{S_REGSET}, \
++	{P_REGSET}, \
++	{G_REGSET}, \
++	{ALL_REGSET}, \
++}
++
++/* The same information, inverted.
++ * This is defined to use the REG_CLASS_CONTENTS defines above, so that
++ * these two sets of definitions are always consistent. */
++
++#define REGNO_REG_CLASS(REGNO) \
++  (D_REGNO_P (REGNO) ? D_REGS : \
++  (Z_REGNO_P (REGNO) ? Z_REGS : \
++  (ACC_A_REGNO_P (REGNO) ? ACC_A_REGS : \
++  (ACC_B_REGNO_P (REGNO) ? ACC_B_REGS : \
++  (X_REGNO_P (REGNO) ? X_REGS : \
++  (Q_REGNO_P (REGNO) ? Q_REGS : \
++  (M_REGNO_P (REGNO) ? M_REGS : \
++  (CC_REGNO_P (REGNO) ? CC_REGS : \
++  (I_REGNO_P (REGNO) ? I_REGS : \
++  (T_REGNO_P (REGNO) ? T_REGS : \
++  (A_REGNO_P (REGNO) ? A_REGS : \
++  (S_REGNO_P (REGNO) ? S_REGS : \
++  (P_REGNO_P (REGNO) ? P_REGS : \
++  (G_REGNO_P (REGNO) ? G_REGS : ALL_REGS))))))))))))))
++
++#define D_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, D_REGSET))
++#define ACC_A_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, ACC_A_REGSET))
++#define ACC_B_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, ACC_B_REGSET))
++#define X_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, X_REGSET))
++#define Z_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, Z_REGSET))
++#define Q_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, Q_REGSET))
++#define M_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, M_REGSET))
++#define CC_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, CC_REGSET))
++#define I_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, I_REGSET))
++#define T_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, T_REGSET))
++#define A_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, A_REGSET))
++#define S_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, S_REGSET))
++#define P_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, P_REGSET))
++#define G_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, G_REGSET))
++
++/* Macros that test an rtx 'X' to see if it's in a particular
++ * register class.  'X' need not be a REG necessarily. */
++
++#define D_REG_P(X) (REG_P (X) && D_REGNO_P (REGNO (X)))
++#define ACC_A_REG_P(X) (REG_P (X) && ACC_A_REGNO_P (REGNO (X)))
++#define ACC_B_REG_P(X) (REG_P (X) && ACC_B_REGNO_P (REGNO (X)))
++#define X_REG_P(X) (REG_P (X) && X_REGNO_P (REGNO (X)))
++#define Z_REG_P(X) (REG_P (X) && Z_REGNO_P (REGNO (X)))
++#define I_REG_P(X) (REG_P (X) && I_REGNO_P (REGNO (X)))
++#define T_REG_P(X) (REG_P (X) && T_REGNO_P (REGNO (X)))
++#define A_REG_P(X) (REG_P (X) && A_REGNO_P (REGNO (X)))
++#define S_REG_P(X) (REG_P (X) && S_REGNO_P (REGNO (X)))
++#define P_REG_P(X) (REG_P (X) && P_REGNO_P (REGNO (X)))
++#define Q_REG_P(X) (REG_P (X) && Q_REGNO_P (REGNO (X)))
++#define M_REG_P(X) (REG_P (X) && M_REGNO_P (REGNO (X)))
++#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
++
++/* Redefine this in terms of BYTE_REGSET */
++#define BYTE_REGNO_P(REGNO) (REGSET_CONTAINS_P (REGNO, BYTE_REGSET))
++
++/* The class value for index registers, and the one for base regs.  */
++#define INDEX_REG_CLASS I_REGS
++#define BASE_REG_CLASS A_REGS
++
++/* Get reg_class from a letter in the machine description.  */
++#define REG_CLASS_FROM_LETTER(C) \
++  (((C) == 'a' ? A_REGS : \
++   ((C) == 'd' ? D_REGS : \
++	((C) == 'x' ? I_REGS : \
++	((C) == 't' ? M_REGS : \
++	((C) == 'c' ? CC_REGS : \
++	((C) == 'A' ? ACC_A_REGS : \
++	((C) == 'B' ? ACC_B_REGS : \
++	((C) == 'v' ? X_REGS : \
++	((C) == 'u' ? S_REGS : \
++	((C) == 'U' ? P_REGS : \
++	((C) == 'T' ? T_REGS : \
++	((C) == 'z' ? Z_REGS : \
++   ((C) == 'q' ? Q_REGS : NO_REGS))))))))))))))
++
++/*--------------------------------------------------------------
++   The letters I through O in a register constraint string
++   can be used to stand for particular ranges of immediate operands.
++   This macro defines what the ranges are.
++   C is the letter, and VALUE is a constant value.
++   Return 1 if VALUE is in the range specified by C.
++
++   For the 6809, J, K, L are used for indexed addressing.
++   `I' is used for the constant 1.
++   `J' is used for the 5-bit offsets.
++   `K' is used for the 8-bit offsets.
++   `L' is used for the range of signed numbers that fit in 16 bits.
++   `M' is used for the exact value '8'.
++   `N' is used for the constant -1.
++   `O' is used for the constant 0.
++--------------------------------------------------------------*/
++
++#define CONST_OK_FOR_LETTER_P(VALUE, C) \
++  ((C) == 'I' ? ((VALUE) == 1) : \
++   (C) == 'J' ? ((VALUE) >= -16 && (VALUE) <= 15) : \
++   (C) == 'K' ? ((VALUE) >= -128 && (VALUE) <= 127) : \
++   (C) == 'L' ? ((VALUE) >= -32768 && (VALUE) <= 32767) : \
++   (C) == 'M' ? ((VALUE) == 8) : \
++   (C) == 'N' ? ((VALUE) == -1) : \
++   (C) == 'O' ? ((VALUE) == 0) : 0)
++
++/* Similar, but for floating constants, and defining letters G and H.
++   No floating-point constants are valid on MC6809.  */
++#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
++   ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \
++     && VALUE == CONST0_RTX (GET_MODE (VALUE))) : 0)
++
++/* Given an rtx X being reloaded into a reg required to be
++   in class CLASS, return the class of reg to actually use.
++   In general this is just CLASS; but on some machines
++   in some cases it is preferable to use a more restrictive class.  */
++#define PREFERRED_RELOAD_CLASS(X,CLASS) m6809_preferred_reload_class(X,CLASS)
++
++#define SMALL_REGISTER_CLASSES  1
++
++/* Return the maximum number of consecutive registers
++   needed to represent mode MODE in a register of class CLASS.  */
++#define CLASS_MAX_NREGS(CLASS, MODE) \
++    ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
++
++/*--------------------------------------------------------------
++	Stack layout; function entry, exit and calling.
++--------------------------------------------------------------*/
++
++/* Define this if pushing a word on the stack
++   makes the stack pointer a smaller address.  */
++#define STACK_GROWS_DOWNWARD
++
++
++/* Define this if the nominal address of the stack frame
++   is at the high-address end of the local variables;
++   that is, each additional local variable allocated
++   goes at a more negative offset in the frame.  */
++#define FRAME_GROWS_DOWNWARD 1
++
++
++/* Offset within stack frame to start allocating local variables at.
++   If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
++   first local allocated.  Otherwise, it is the offset to the BEGINNING
++   of the first local allocated.  */
++#define STARTING_FRAME_OFFSET 0
++
++
++/* Always push stack arguments for now.  Accumulation is not yet working. */
++#define PUSH_ROUNDING(BYTES) (BYTES)
++
++
++/* Offset of first parameter from the argument pointer register value.
++ * ARG_POINTER_REGNUM is defined to point to the return address pushed
++ * onto the stack, so we must offset by 2 bytes to get to the arguments. */
++#define FIRST_PARM_OFFSET(FNDECL) 2
++
++/* Value is 1 if returning from a function call automatically
++   pops the arguments described by the number-of-args field in the call.
++   FUNTYPE is the data type of the function (as a tree),
++   or for a library call it is an identifier node for the subroutine name. */
++/* #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 */
++
++/* Define how to find the value returned by a function.
++   VALTYPE is the data type of the value (as a tree).
++   If the precise function being called is known, FUNC is its FUNCTION_DECL;
++   otherwise, FUNC is 0.  */
++#define FUNCTION_VALUE(VALTYPE, FUNC) m6809_function_value (VALTYPE, FUNC)
++
++/* Define how to find the value returned by a library function
++   assuming the value has mode MODE.  */
++
++/* All return values are in the X-register. */
++#define LIBCALL_VALUE(MODE)  gen_rtx_REG (MODE, HARD_X_REGNUM)
++
++/* Define this if using the nonreentrant convention for returning
++   structure and union values.  No; it is inefficient and buggy. */
++#undef PCC_STATIC_STRUCT_RETURN
++
++/* 1 if N is a possible register number for a function value. */
++#define FUNCTION_VALUE_REGNO_P(N) m6809_function_value_regno_p (N)
++
++/* Define this to be true when FUNCTION_VALUE_REGNO_P is true for
++   more than one register.  */
++#define NEEDS_UNTYPED_CALL 1
++
++/* 1 if N is a possible register number for function argument passing. */
++#define FUNCTION_ARG_REGNO_P(N) \
++	((m6809_abi_version != M6809_ABI_VERSION_STACK) ? \
++   	(((N) == HARD_D_REGNUM) || ((N) == HARD_X_REGNUM)) : \
++		0)
++
++/*--------------------------------------------------------------
++	Argument Lists
++--------------------------------------------------------------*/
++
++/* Cumulative arguments are tracked in a single integer, 
++ * which is the number of bytes of arguments scanned so far,
++ * plus which registers have already been used.  The register
++ * info is kept in some of the upper bits */
++#define CUMULATIVE_ARGS unsigned int
++
++#define CUM_STACK_ONLY 0x80000000
++#define CUM_X_MASK     0x40000000
++#define CUM_B_MASK     0x20000000
++#define CUM_STACK_INVALID 0x10000000
++#define CUM_STACK_MASK 0xFFFFFFF
++
++#define CUM_ADVANCE_8BIT(cum) \
++	(((cum) & CUM_B_MASK) ? (cum)++ : ((cum) |= CUM_B_MASK))
++
++#define CUM_ADVANCE_16BIT(cum) \
++	(((cum) & CUM_X_MASK) ? (cum) += 2 : ((cum) |= CUM_X_MASK))
++
++/* Initialize a variable CUM of type CUMULATIVE_ARGS
++   for a call to a function whose data type is FNTYPE.
++   For a library call, FNTYPE is 0.
++	N_NAMED was added in gcc 3.4 and is not used currently. */
++#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT,N_NAMED) \
++	((CUM) = m6809_init_cumulative_args (CUM, FNTYPE, LIBNAME))
++
++#define FUNCTION_ARG_SIZE(MODE, TYPE)	\
++  ((MODE) != BLKmode ? GET_MODE_SIZE (MODE)	\
++   : (unsigned) int_size_in_bytes (TYPE))
++
++/* Update the data in CUM to advance over an argument
++   of mode MODE and data type TYPE.
++   (TYPE is null for libcalls where that information may not be available.)  */
++#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
++	 (((MODE == QImode) && !((CUM) & CUM_STACK_ONLY)) ? \
++		CUM_ADVANCE_8BIT (CUM) : \
++	  ((MODE == HImode) && !((CUM) & CUM_STACK_ONLY)) ? \
++		CUM_ADVANCE_16BIT (CUM) : \
++	  ((CUM) = ((CUM) + (TYPE ? int_size_in_bytes (TYPE) : 2))))
++
++/* Define where to put the arguments to a function.
++   Value is zero to push the argument on the stack,
++   or a hard register rtx in which to store the argument.
++	This macro is used _before_ FUNCTION_ARG_ADVANCE.
++
++	For the 6809, the first 8-bit function argument can be placed into B,
++	and the first 16-bit arg can go into X.  All other arguments
++	will be pushed onto the stack.
++
++	Command-line options can adjust this behavior somewhat.
++ */
++#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
++	((MODE == VOIDmode) ? NULL_RTX : \
++	((MODE == BLKmode) || (GET_MODE_SIZE (MODE) > 2)) ? NULL_RTX : \
++	((MODE == QImode) && !((CUM) & (CUM_STACK_ONLY | CUM_B_MASK))) ? \
++		gen_rtx_REG (QImode, HARD_D_REGNUM) : \
++	((MODE == HImode) && !((CUM) & (CUM_STACK_ONLY | CUM_X_MASK))) ?  \
++		gen_rtx_REG (HImode, HARD_X_REGNUM) : m6809_function_arg_on_stack (&CUM))
++
++/* Output assembler code to FILE to increment profiler label # LABELNO
++   for profiling a function entry.  */
++#define FUNCTION_PROFILER(FILE, LABELNO) \
++   fprintf (FILE, "\tldd\t#LP%u\n\tjsr\tmcount\n", (LABELNO));
++
++/* Stack pointer must be correct on function exit */
++#define EXIT_IGNORE_STACK 0
++
++/*****************************************************************************
++**
++** Trampolines for Nested Functions
++**
++*****************************************************************************/
++
++/* Length in units of the trampoline for entering a nested function.  */
++#define TRAMPOLINE_SIZE 7
++
++/*--------------------------------------------------------------
++	Addressing modes,
++	and classification of registers for them.
++--------------------------------------------------------------*/
++
++/* 6809 has postincrement and predecrement addressing modes */
++#define HAVE_POST_INCREMENT  1
++#define HAVE_PRE_DECREMENT  1
++
++/* Whether or not to use index registers is configurable.
++ * Experiments show that things work better when this is off, so
++ * that's the way it is for now. */
++#undef USE_INDEX_REGISTERS
++
++
++/* Macros to check register numbers against specific register classes.  */
++#define REG_VALID_FOR_BASE_P(REGNO) \
++	(((REGNO) < FIRST_PSEUDO_REGISTER) && A_REGNO_P (REGNO))
++
++/* MC6809 index registers do not allow scaling, */
++/* but there is "accumulator-offset" mode. */
++#ifdef USE_INDEX_REGISTERS
++#define REG_VALID_FOR_INDEX_P(REGNO) \
++	(((REGNO) < FIRST_PSEUDO_REGISTER) && I_REGNO_P (REGNO))
++#else
++#define REG_VALID_FOR_INDEX_P(REGNO) 0
++#endif
++
++/* Internal macro, the nonstrict definition for REGNO_OK_FOR_BASE_P */
++#define REGNO_OK_FOR_BASE_NONSTRICT_P(REGNO) \
++   ((REGNO) >= FIRST_PSEUDO_REGISTER \
++	|| REG_VALID_FOR_BASE_P (REGNO) \
++	|| (REGNO) == FRAME_POINTER_REGNUM \
++	|| (REGNO) == HARD_FRAME_POINTER_REGNUM \
++	|| (REGNO) == ARG_POINTER_REGNUM \
++	|| (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO])))
++
++/* Internal macro, the nonstrict definition for REGNO_OK_FOR_INDEX_P */
++#define REGNO_OK_FOR_INDEX_NONSTRICT_P(REGNO) \
++   ((REGNO) >= FIRST_PSEUDO_REGISTER \
++	|| REG_VALID_FOR_INDEX_P (REGNO) \
++	|| (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO])))
++
++
++/* Internal macro, the strict definition for REGNO_OK_FOR_BASE_P */
++#define REGNO_OK_FOR_BASE_STRICT_P(REGNO) \
++	((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_BASE_P (REGNO) \
++	: (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO])))
++
++
++/* Internal macro, the strict definition for REGNO_OK_FOR_INDEX_P */
++#define REGNO_OK_FOR_INDEX_STRICT_P(REGNO) \
++	((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_INDEX_P (REGNO) \
++	: (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO])))
++
++
++#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_BASE_STRICT_P (REGNO)
++
++#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_INDEX_STRICT_P (REGNO)
++
++#define REG_OK_FOR_BASE_STRICT_P(X)     REGNO_OK_FOR_BASE_STRICT_P (REGNO (X))
++#define REG_OK_FOR_BASE_NONSTRICT_P(X)  REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (X))
++#define REG_OK_FOR_INDEX_STRICT_P(X)    REGNO_OK_FOR_INDEX_STRICT_P (REGNO (X))
++#define REG_OK_FOR_INDEX_NONSTRICT_P(X) REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (X))
++
++#ifndef REG_OK_STRICT
++#define REG_OK_FOR_BASE_P(X)     REG_OK_FOR_BASE_NONSTRICT_P(X)
++#ifdef USE_INDEX_REGISTERS
++#define REG_OK_FOR_INDEX_P(X)    REG_OK_FOR_INDEX_NONSTRICT_P(X)
++#else
++#define REG_OK_FOR_INDEX_P(X)    0
++#endif
++#else
++#define REG_OK_FOR_BASE_P(X)     REG_OK_FOR_BASE_STRICT_P (X)
++#ifdef USE_INDEX_REGISTERS
++#define REG_OK_FOR_INDEX_P(X)    REG_OK_FOR_INDEX_STRICT_P (X)
++#else
++#define REG_OK_FOR_INDEX_P(X)    0
++#endif
++#endif
++
++/* Maximum number of registers that can appear in a valid memory address */
++#ifdef USE_INDEX_REGISTERS
++#define MAX_REGS_PER_ADDRESS 2
++#else
++#define MAX_REGS_PER_ADDRESS 1
++#endif
++
++/* 1 if X is an rtx for a constant that is a valid address.
++ * We allow any constant, plus the sum of any two constants (this allows
++ * offsetting a symbol ref) */
++#define CONSTANT_ADDRESS_P(X) \
++	((CONSTANT_P (X)) \
++	|| ((GET_CODE (X) == PLUS) \
++	      && (CONSTANT_P (XEXP (X, 0))) && (CONSTANT_P (XEXP (X, 1)))))
++
++/* Nonzero if the constant value X is a legitimate general operand.
++   It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
++/* Any single-word constant is ok; the only contexts
++   allowing general_operand of mode DI or DF are movdi and movdf. */
++#define LEGITIMATE_CONSTANT_P(X) (GET_CODE (X) != CONST_DOUBLE)
++
++/* Nonzero if the X is a legitimate immediate operand in PIC mode. */
++#define LEGITIMATE_PIC_OPERAND_P(X)	!symbolic_operand (X, VOIDmode)
++
++/*--------------------------------------------------------------
++	Test for valid memory addresses
++--------------------------------------------------------------*/
++/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
++   that is a valid memory address for an instruction.
++   The MODE argument is the machine mode for the MEM expression
++   that wants to use this address. */
++
++/*--------------------------------------------------------------
++   Valid addresses are either direct or indirect (MEM) versions
++   of the following forms.
++	constant		N
++	register		,X
++	constant indexed	N,X
++	accumulator indexed	D,X
++	auto_increment		,X++
++	auto_decrement		,--X
++--------------------------------------------------------------*/
++
++#define REGISTER_ADDRESS_P(X) \
++  (REG_P (X) && REG_OK_FOR_BASE_P (X))
++
++#define EXTENDED_ADDRESS_P(X) \
++    CONSTANT_ADDRESS_P (X) \
++
++#define LEGITIMATE_BASE_P(X) \
++  ((REG_P (X) && REG_OK_FOR_BASE_P (X))	\
++   || (GET_CODE (X) == SIGN_EXTEND			\
++       && GET_CODE (XEXP (X, 0)) == REG			\
++       && GET_MODE (XEXP (X, 0)) == HImode		\
++       && REG_OK_FOR_BASE_P (XEXP (X, 0))))
++
++#define LEGITIMATE_OFFSET_P(X) \
++    (CONSTANT_ADDRESS_P (X) || (REG_P (X) && REG_OK_FOR_INDEX_P (X)))
++
++/* 1 if X is the sum of a base register and an offset. */
++#define INDEXED_ADDRESS(X) \
++   ((GET_CODE (X) == PLUS \
++       && LEGITIMATE_BASE_P (XEXP (X, 0)) \
++       && LEGITIMATE_OFFSET_P (XEXP (X, 1))) \
++   || (GET_CODE (X) == PLUS \
++       && LEGITIMATE_BASE_P (XEXP (X, 1)) \
++       && LEGITIMATE_OFFSET_P (XEXP (X, 0))))
++
++#define STACK_REG_P(X) (REG_P(X) && REGNO(X) == HARD_S_REGNUM)
++
++#define STACK_PUSH_P(X) \
++   (MEM_P (X) && GET_CODE (XEXP (X, 0)) == PRE_DEC && STACK_REG_P (XEXP (XEXP (X, 0), 0)))
++
++#define STACK_POP_P(X) \
++   (MEM_P (X) && GET_CODE (XEXP (X, 0)) == POST_INC && STACK_REG_P (XEXP (XEXP (X, 0), 0)))
++
++#define PUSH_POP_ADDRESS_P(X) \
++    (((GET_CODE (X) == PRE_DEC) || (GET_CODE (X) == POST_INC)) \
++	&& (LEGITIMATE_BASE_P (XEXP (X, 0))))
++
++/* Go to ADDR if X is a valid address. */
++#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
++{ \
++  if (REGISTER_ADDRESS_P(X)) goto ADDR; \
++  if (PUSH_POP_ADDRESS_P (X)) goto ADDR; \
++  if (EXTENDED_ADDRESS_P (X)) goto ADDR; \
++  if (INDEXED_ADDRESS (X)) goto ADDR; \
++  if (MEM_P (X) && REGISTER_ADDRESS_P(XEXP (X, 0))) goto ADDR; \
++  if (MEM_P (X) && PUSH_POP_ADDRESS_P (XEXP (X, 0))) goto ADDR; \
++  if (MEM_P (X) && EXTENDED_ADDRESS_P (XEXP (X, 0))) goto ADDR; \
++  if (MEM_P (X) && INDEXED_ADDRESS (XEXP (X, 0))) goto ADDR; \
++}
++
++/*--------------------------------------------------------------
++	Address Fix-up
++--------------------------------------------------------------*/
++/* Go to LABEL if ADDR (a legitimate address expression)
++   has an effect that depends on the machine mode it is used for.
++	In the latest GCC, this case is already handled by the core code
++	so no action is required here. */
++#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
++
++
++/*--------------------------------------------------------------
++	Miscellaneous Parameters
++--------------------------------------------------------------*/
++/* Specify the machine mode that this machine uses
++   for the index in the tablejump instruction.  */
++#define CASE_VECTOR_MODE Pmode
++
++/* Define this as 1 if `char' should by default be signed; else as 0.  */
++#define DEFAULT_SIGNED_CHAR 0
++
++/* This flag, if defined, says the same insns that convert to a signed fixnum
++   also convert validly to an unsigned one.  */
++#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
++
++/* Max number of bytes we can move from memory to memory/register
++   in one reasonably fast instruction.  */
++#define MOVE_MAX 2
++
++/* Int can be 8 or 16 bits (default is 16) */
++#define INT_TYPE_SIZE (TARGET_BYTE_INT ? 8 : 16)
++
++/* Short is always 16 bits */
++#define SHORT_TYPE_SIZE (TARGET_BYTE_INT ? 8 : 16)
++
++/* Size (bits) of the type "long" on target machine */
++#define LONG_TYPE_SIZE (TARGET_BYTE_INT ? 16 : 32)
++
++/* Size (bits) of the type "long long" on target machine */
++#define LONG_LONG_TYPE_SIZE 32
++
++/* Size (bits) of the type "char" on target machine */
++#define CHAR_TYPE_SIZE 8
++
++/* Size (bits) of the type "float" on target machine */
++#define FLOAT_TYPE_SIZE 32
++
++/* Size (bits) of the type "double" on target machine.
++ * Note that the C standard does not require that doubles
++ * hold any more bits than float.  Since the 6809 has so few
++ * registers, we cannot really support more than 32-bits. */
++#define DOUBLE_TYPE_SIZE 32 
++
++/* Size (bits) of the type "long double" on target machine */
++#define LONG_DOUBLE_TYPE_SIZE 32
++
++/* Define the type used for "size_t".  With a 64KB address space,
++ * only a 16-bit value here makes sense. */
++#define SIZE_TYPE (TARGET_BYTE_INT ? "long unsigned int" : "unsigned int")
++
++/* Likewise, the difference between two pointers is also a 16-bit
++ * signed value. */
++#define PTRDIFF_TYPE (TARGET_BYTE_INT ? "long int" : "int")
++
++/* Nonzero if access to memory by bytes is slow and undesirable.  */
++#define SLOW_BYTE_ACCESS 0
++
++/* Define if shifts truncate the shift count
++   which implies one can omit a sign-extension or zero-extension
++   of a shift count.  */
++#define SHIFT_COUNT_TRUNCATED 0
++
++/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
++   is done just by pretending it is already truncated.  */
++#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
++
++/* It is as good to call a constant function address as to
++   call an address kept in a register. */
++#define NO_FUNCTION_CSE
++
++/* Specify the machine mode that pointers have.
++   After generation of rtl, the compiler makes no further distinction
++   between pointers and any other objects of this machine mode.  */
++#define Pmode HImode
++
++/* A function address in a call instruction
++   is a byte address (for indexing purposes)
++   so give the MEM rtx a byte's mode.  */
++#define FUNCTION_MODE HImode
++
++/* Define the cost of moving a value from a register in CLASS1
++ * to CLASS2, of a given MODE.
++ *
++ * On the 6809, hard register transfers are all basically equivalent.
++ * But soft register moves are treated more like memory moves. */
++#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
++	(((CLASS1 == M_REGS) || (CLASS2 == M_REGS)) ? 4 : 7)
++
++/* Define the cost of moving a value between a register and memory. */
++#define MEMORY_MOVE_COST(MODE, CLASS, IN) 5
++
++/* Check a `double' value for validity for a particular machine mode.  */
++
++#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
++  ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
++
++
++/*--------------------------------------------------------------
++	machine-dependent
++--------------------------------------------------------------*/
++/* Tell final.c how to eliminate redundant test instructions.  */
++
++/* Here we define machine-dependent flags and fields in cc_status
++   (see `conditions.h').  */
++
++/* Store in cc_status the expressions
++   that the condition codes will describe
++   after execution of an instruction whose pattern is EXP.
++   Do not alter them if the instruction would not alter the cc's.  */
++
++/* On the 6809, most of the insns to store in an address register
++   fail to set the cc's.  However, in some cases these instructions
++   can make it possibly invalid to use the saved cc's.  In those
++   cases we clear out some or all of the saved cc's so they won't be used.  */
++
++#define NOTICE_UPDATE_CC(EXP, INSN) \
++  notice_update_cc((EXP), (INSN))
++
++/*****************************************************************************
++**
++** pragma support
++**
++*****************************************************************************/
++
++#if 0
++#define REGISTER_TARGET_PRAGMAS() \
++do { \
++	extern void pragma_section PARAMS ((cpp_reader *)); \
++	c_register_pragma (0, "section", pragma_section); \
++} while (0)
++
++#endif
++
++/*--------------------------------------------------------------
++	ASSEMBLER FORMAT
++--------------------------------------------------------------*/
++
++#define FMT_HOST_WIDE_INT "%ld"
++
++/* Output to assembler file text saying following lines
++   may contain character constants, extra white space, comments, etc.  */
++#define ASM_APP_ON ";----- asm -----\n"
++
++/* Output to assembler file text saying following lines
++   no longer contain unusual constructs.  */
++#define ASM_APP_OFF ";--- end asm ---\n"
++
++/* Use a semicolon to begin a comment. */
++#define ASM_COMMENT_START "; "
++
++/* Output assembly directives to switch to section 'name' */
++#undef TARGET_ASM_NAMED_SECTION
++#define TARGET_ASM_NAMED_SECTION	m6809_asm_named_section
++
++#undef TARGET_HAVE_NAMED_SECTION
++#define TARGET_HAVE_NAMED_SECTION m6809_have_named_section
++
++/* Output before read-only data.  */
++#define TEXT_SECTION_ASM_OP (code_section_op)
++
++/* Output before writable data.  */
++#define DATA_SECTION_ASM_OP (data_section_op)
++
++/* Output before uninitialized data.  */
++#define BSS_SECTION_ASM_OP (bss_section_op)
++
++/* Support the ctors and dtors sections for g++.  */
++ 
++#undef CTORS_SECTION_ASM_OP
++#define CTORS_SECTION_ASM_OP    "\t.area .ctors"
++#undef DTORS_SECTION_ASM_OP
++#define DTORS_SECTION_ASM_OP    "\t.area .dtors"
++
++
++#undef DO_GLOBAL_CTORS_BODY
++#undef DO_GLOBAL_DTORS_BODY
++
++#define HAS_INIT_SECTION
++
++/* This is how to output an assembler line
++   that says to advance the location counter
++   to a multiple of 2**LOG bytes.  */
++
++#define ASM_OUTPUT_ALIGN(FILE,LOG) \
++  if ((LOG) > 1) \
++    fprintf (FILE, "\t.bndry %u\n", 1 << (LOG))
++
++/* The .set foo,bar construct doesn't work by default */
++#undef SET_ASM_OP
++#define ASM_OUTPUT_DEF(FILE, LABEL1, LABEL2)			\
++  do								\
++    {								\
++      fputc ('\t', FILE);					\
++      assemble_name (FILE, LABEL1);				\
++      fputs (" = ", FILE);					\
++      assemble_name (FILE, LABEL2);				\
++      fputc ('\n', FILE);					\
++    }								\
++  while (0)
++
++/* How to refer to registers in assembler output.
++   This sequence is indexed by compiler's hard-register-number (see above).  */
++#define MNAME(x) [SOFT_M0_REGNUM+(x)] = "*m" C_STRING(x) ,
++
++#define REGISTER_NAMES { \
++	[HARD_D_REGNUM]= "d", \
++	[HARD_X_REGNUM]= "x", \
++	[HARD_Y_REGNUM]= "y", \
++	[HARD_U_REGNUM]= "u", \
++	[HARD_S_REGNUM]= "s", \
++	[HARD_PC_REGNUM]= "pc", \
++	[HARD_A_REGNUM]= "a", \
++	[HARD_B_REGNUM]= "b", \
++	[HARD_CC_REGNUM]= "cc",\
++	[HARD_DP_REGNUM]= "dp", \
++	[SOFT_FP_REGNUM]= "soft_fp", \
++	[SOFT_AP_REGNUM]= "soft_ap", \
++	MNAME(0) MNAME(1) MNAME(2) MNAME(3) \
++	MNAME(4) MNAME(5) MNAME(6) MNAME(7) \
++	[HARD_RSVD1_REGNUM] = "-", \
++	[HARD_Z_REGNUM] = "z" /* bit 2 of CC */ }
++
++/*****************************************************************************
++**
++** Debug Support
++**
++*****************************************************************************/
++
++/* Default to DBX-style debugging */
++#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
++
++#define DBX_DEBUGGING_INFO
++
++#define DEFAULT_GDB_EXTENSIONS 0
++
++#define ASM_STABS_OP ";\t.stabs\t"
++#define ASM_STABD_OP ";\t.stabd\t"
++#define ASM_STABN_OP ";\t.stabn\t"
++
++#define DBX_CONTIN_LENGTH 54
++
++#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(ASMFILE, FILENAME) \
++do { \
++	const char *p = FILENAME; \
++	while ((p = strchr (p, '/')) != NULL) { \
++		p = FILENAME = p+1; \
++	} \
++  fprintf (ASMFILE, "%s", ASM_STABS_OP); \
++  output_quoted_string (ASMFILE, FILENAME); \
++  fprintf (ASMFILE, ",%d,0,0,", N_SO); \
++  assemble_name (ASMFILE, ltext_label_name); \
++  fputc ('\n', ASMFILE); \
++  switch_to_section (text_section); \
++  (*targetm.asm_out.internal_label) (ASMFILE, "Ltext", 0); \
++} while (0)
++
++/* With -g, GCC sometimes outputs string literals that are longer than
++ * the assembler can handle.  Without actual debug support, these are
++ * not really required.  Redefine the function to output strings to
++ * output as much as possible. */
++#define OUTPUT_QUOTED_STRING(FILE, STR) m6809_output_quoted_string (FILE, STR)
++
++/*****************************************************************************
++**
++** Output and Generation of Labels
++**
++*****************************************************************************/
++
++/* Prefixes for various assembly-time objects */
++
++#define REGISTER_PREFIX ""
++
++#define LOCAL_LABEL_PREFIX ""
++
++#define USER_LABEL_PREFIX "_"
++
++#define IMMEDIATE_PREFIX "#"
++
++/* This is how to output the definition of a user-level label named NAME,
++   such as the label on a static function or variable NAME.  */
++
++#define ASM_OUTPUT_LABEL(FILE,NAME) \
++do { \
++  if (section_changed) { \
++	  fprintf (FILE, "\n%s\n\n", code_section_op); \
++     section_changed = 0; \
++  } \
++  assemble_name (FILE, NAME); \
++  fputs (":\n", FILE); \
++} while (0)
++
++/* This is how to output the label for a function definition.  It
++   invokes ASM_OUTPUT_LABEL, but may examine the DECL tree node for
++	other properties. */
++#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
++  m6809_declare_function_name (FILE,NAME,DECL)
++
++/* This is how to output a command to make the user-level label
++    named NAME defined for reference from other files.  */
++
++#define GLOBAL_ASM_OP "\t.globl "
++
++/* This is how to output a reference to a user label named NAME. */
++#define ASM_OUTPUT_LABELREF(FILE,NAME) \
++  fprintf (FILE, "_%s", NAME)
++
++/* This is how to output a reference to a symbol ref
++ * Check to see if the symbol is in the direct page */
++#define ASM_OUTPUT_SYMBOL_REF(FILE,sym) \
++{ \
++	print_direct_prefix (FILE, sym); \
++	assemble_name (FILE, XSTR (sym, 0)); \
++}
++
++/* External references aren't necessary, so don't emit anything */
++#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME)
++
++/* This is how to store into the string LABEL
++   the symbol_ref name of an internal numbered label where
++   PREFIX is the class of label and NUM is the number within the class.
++   This is suitable for output with `assemble_name'.  */
++#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
++  sprintf (LABEL, "*%s%lu", PREFIX, (unsigned long int)NUM)
++
++/* This is how to output an assembler line defining an `int' constant.  */
++#define ASM_OUTPUT_INT(FILE,VALUE) \
++( fprintf (FILE, "\t.word "), \
++  output_addr_const (FILE, (VALUE)), \
++  fprintf (FILE, "\n"))
++
++/* Likewise for `char' and `short' constants.  */
++#define ASM_OUTPUT_SHORT(FILE,VALUE) \
++( fprintf (FILE, "\t.word "), \
++  output_addr_const (FILE, (VALUE)), \
++  fprintf (FILE, "\n"))
++
++/* This is how to output a string. */ 
++#define ASM_OUTPUT_ASCII(FILE,STR,SIZE) m6809_output_ascii (FILE, STR, SIZE)
++
++/* This is how to output an insn to push a register on the stack.
++   It need not be very fast code.  */
++
++#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
++   fprintf (FILE, "\tpshs\t%s\n", reg_names[REGNO])
++
++/* This is how to output an insn to pop a register from the stack.
++   It need not be very fast code.  */
++
++#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
++   fprintf (FILE, "\tpuls\t%s\n", reg_names[REGNO])
++
++/* This is how to output an element of a case-vector that is absolute. */
++
++#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
++  fprintf (FILE, "\t.word L%u\n", VALUE)
++
++/* This is how to output an element of a case-vector that is relative. */
++
++#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
++  fprintf (FILE, "\t.word L%u-L%u\n", VALUE, REL)
++
++
++/*****************************************************************************
++**
++** Assembler Commands for Alignment
++**
++*****************************************************************************/
++
++/* ASM_OUTPUT_SKIP is supposed to zero initialize the data.
++ * So use the .byte and .word directives instead of .blkb */
++#define ASM_OUTPUT_SKIP(FILE,SIZE) \
++  do { \
++    int __size = SIZE; \
++    while (__size > 0) { \
++      if (__size >= 2) \
++      { \
++        fprintf (FILE, "\t.word\t0\t;skip space %d\n", __size); \
++        __size -= 2; \
++      } \
++      else \
++      { \
++        fprintf (FILE, "\t.byte\t0\t;skip space\n"); \
++        __size--; \
++      } \
++    } \
++  } while (0)
++
++/* This says how to output an assembler line
++   to define a global common symbol.  */
++
++#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
++  do { \
++  switch_to_section (bss_section); \
++  fputs ("\t.globl\t", FILE); \
++  assemble_name ((FILE), (NAME)); \
++  fputs ("\n", FILE); \
++  assemble_name ((FILE), (NAME)); \
++  fprintf ((FILE), ":\t.blkb\t" FMT_HOST_WIDE_INT "\n", (ROUNDED));} while(0)
++
++/* This says how to output an assembler line
++   to define a local common symbol.  */
++
++#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
++do { \
++  switch_to_section (bss_section); \
++  assemble_name ((FILE), (NAME)); \
++  fprintf ((FILE), ":\t.blkb\t" FMT_HOST_WIDE_INT "\n", (ROUNDED));} while(0)
++
++/* Store in OUTPUT a string (made with alloca) containing
++   an assembler-name for a local static variable named NAME.
++   LABELNO is an integer which is different for each call.  */
++
++#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
++( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
++  sprintf ((OUTPUT), "%s.%lu", (NAME), (unsigned long int)(LABELNO)))
++
++/* Print an instruction operand X on file FILE.
++   CODE is the code from the %-spec for printing this operand.
++   If `%z3' was used to print operand 3, then CODE is 'z'. */
++#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
++
++/* Print a memory operand whose address is X, on file FILE. */
++#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
++
++/* Don't let stack pushes build up too much. */
++#define MAX_PENDING_STACK 8
++
++/* Define values for builtin operations */
++enum m6809_builtins
++{
++	M6809_SWI,
++	M6809_SWI2,
++	M6809_SWI3,
++	M6809_CWAI,
++	M6809_SYNC,
++	M6809_ADD_CARRY,
++	M6809_SUB_CARRY,
++	M6809_ADD_DECIMAL,
++	M6809_NOP,
++	M6809_BLOCKAGE
++};
++
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.md gcc-4.6.1/gcc/config/m6809/m6809.md
+--- gcc-4.6.1-orig/gcc/config/m6809/m6809.md	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/m6809.md	2011-09-21 20:40:01.287068005 -0600
+@@ -0,0 +1,2359 @@
++;; GCC machine description for Motorola 6809
++;; Copyright (C) 1989, 2005, 2006, 2007, 2008,
++;; 2009 Free Software Foundation, Inc.
++;;
++;; Mostly by Brian Dominy (brian@oddchange.com) with substantial renovations
++;; by William Astle (lost@l-w.ca).
++;;
++;; Based on earlier work by Tom Jones (jones@sal.wisc.edu) and
++;; Matthias Doerfel (msdoerfe@informatik.uni-erlangen.de)
++;;
++;; This file is part of GCC.
++;;
++;; GCC is free software; you can redistribute it and/or modify
++;; it under the terms of the GNU General Public License as published by
++;; the Free Software Foundation; either version 3, or (at your option)
++;; any later version.
++;;
++;; GCC is distributed in the hope that it will be useful,
++;; but WITHOUT ANY WARRANTY; without even the implied warranty of
++;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++;; GNU General Public License for more details.
++;;
++;; You should have received a copy of the GNU General Public License
++;; along with GCC; see the file COPYING3.  If not see
++;; <http://www.gnu.org/licenses/>.
++;;
++;; General information:
++;; --------------------
++;; * This backend is mostly a rewrite from earlier (3.1.1 and before)
++;; versions.
++;;
++;; * The 'A' and 'B' registers are treated as a single register by the
++;; register allocator; hence, the instruction templates assume that
++;; both can be modified if either one is available for use.  No
++;; attempt is made to split instructions to refer to a particular half
++;; of the register.  It is always referred to as the 'D' register, even
++;; in QImode (when it will be displayed as 'B').
++;;
++;; * There is full support for proper branch instruction generation,
++;; based on instruction lengths.  However, many instruction patterns
++;; are still overloaded to emit lots of real instructions, which can
++;; make the length calculation difficult; in those cases, I've tried
++;; to be pessimistic and assume the worst-case.
++;;
++;; * The instruction type attributes are only defined for branch
++;; vs. non branch instructions for now, since there is seemingly no
++;; reason to define these for other types anyway.
++;;
++;; * The limited number of total registers presents the greatest
++;; challenge.  There are 'soft registers' -- memory locations
++;; used to simulate real regs -- which can be helpful.
++;;
++;; * Position-independent code (PIC) is supported and has been tested
++;; but not to the extent of absolute code generation.
++;;
++;; * All of the 6809 special opcodes, e.g. SWI and SYNC, are defined
++;; as UNSPEC instructions, and can be accessed from C code using
++;; __builtin_xxxx() style functions.
++;;
++;; What still needs to be done:
++;; ----------------------------
++;; * Replace remaining instances of (define_peephole) with
++;; (define_peephole2), or remove them completely if they are not
++;; matching anyway.  Add more peepholes for things actually encountered.
++;;
++;; * Indexing addressing can lead to crashes in complex functions when
++;; register pressure is high.  Only the 'D' register can actually be
++;; used as an index register, and its demand by other instructions
++;; can sometimes mean that it is impossible to satisfy constraints.
++;; Currently, indexing is completely disabled to avoid these types
++;; of problems, although code is slightly more inefficient in some
++;; working cases.
++;;
++;; * 32-bit math is terribly inefficient.
++;;
++
++
++;;--------------------------------------------------------------------
++;;-  Constants
++;;--------------------------------------------------------------------
++
++;
++; Define constants for hard register numbers.
++;
++(define_constants [
++  (HARD_RSVD1_REGNUM 0)
++  (HARD_X_REGNUM 1) (HARD_Y_REGNUM 2) (HARD_U_REGNUM 3)
++  (HARD_S_REGNUM 4) (HARD_PC_REGNUM 5) (HARD_D_REGNUM 6)
++  (HARD_Z_REGNUM 7)
++  (HARD_A_REGNUM 8) (HARD_B_REGNUM 9)
++  (HARD_CC_REGNUM 10) (HARD_DP_REGNUM 11)
++  (SOFT_FP_REGNUM 12) (SOFT_AP_REGNUM 13)
++  (SOFT_M0_REGNUM 14) (SOFT_M1_REGNUM 15)
++  (SOFT_M2_REGNUM 16) (SOFT_M3_REGNUM 17)
++])
++
++
++;
++; The range in which a short branch insn can be used.
++;
++(define_constants [
++  (MIN_SHORT_BRANCH_OFFSET -127)
++  (MAX_SHORT_BRANCH_OFFSET 128)
++])
++
++
++;
++; The lengths of various types of real 6809 instructions.
++;
++; By default, ordinary insns are 4 bytes long.  This is often not
++; right, and the insn patterns below will redefine this to the
++; correct value.
++;
++; Branch instruction lengths (conditional and unconditionals) are
++; well known and declared here.  The short insns are used when the
++; offset is within the range declared above (between MIN_SHORT
++; and MAX_SHORT) ; otherwise the long form is used.
++;
++(define_constants [
++  (DEFAULT_INSN_LENGTH 4)
++  (SHORT_CBRANCH_LENGTH 2)
++  (LONG_CBRANCH_LENGTH 4)
++  (SHORT_BRANCH_LENGTH 2)
++  (LONG_BRANCH_LENGTH 3)
++])
++
++
++;
++; Constants for insn cycle counts.
++; Note that these counts all assume 1-byte opcodes.  2-byte
++; opcodes require 1 extra cycles for fetching the extra byte.
++;
++(define_constants [
++  ;; The default insn length, when it cannot be calculated.
++  ;; Take a conservative approach and estimate high.
++  (DEFAULT_INSN_CYCLES 10)
++
++  ;; Cycle counts for ALU and load operations.
++  (ALU_INHERENT_CYCLES 2)
++  (ALU_IMMED_CYCLES 2)
++  (ALU_DIRECT_CYCLES 4)
++  (ALU_INDEXED_BASE_CYCLES 4)
++  (ALU_EXTENDED_CYCLES 5)
++
++  ;; If an ALU operation is on a 16-bit register (D), then
++  ;; add this number of cycles to the total count.
++  (ALU_16BIT_CYCLES 2)
++
++  ;; A load of a 16-bit register incurs this extra amount.
++  (LOAD_16BIT_CYCLES 1)
++
++  ;; Cycle counts for memory-only operations (bit shifts, clear, test)
++  (MEM_DIRECT_CYCLES 6)
++  (MEM_INDEXED_BASE_CYCLES 6)
++  (MEM_EXTENDED_CYCLES 7)
++
++  ;; Cycle count for any reg-reg transfer (regardless of size)
++  (EXG_CYCLES 8)
++  (TFR_CYCLES 6)
++
++  ;; Cycle count for a condition code update (andcc/orcc)
++  (CC_CYCLES 3)
++
++  (JMP_DIRECT_CYCLES 3)
++  (JMP_INDEXED_BASE_CYCLES 3)
++  (JMP_EXTENDED_CYCLES 4)
++
++  (JSR_DIRECT_CYCLES 7)
++  (JSR_INDEXED_BASE_CYCLES 7)
++  (JSR_EXTENDED_CYCLES 8)
++
++  (LEA_BASE_CYCLES 4)
++
++  ;; Cycle count for a psh/pul operations.  Add to this the
++  ;; total number of bytes moved for the correct count.
++  (PSH_PUL_CYCLES 5)
++
++  ;; Miscellaneous cycle counts
++  (CWAI_CYCLES 20)
++  (MUL_CYCLES 11)
++  (NOP_CYCLES 2)
++  (RTI_CYCLES 15)
++  (RTS_CYCLES 5)
++  (SWI_CYCLES 20)
++  (SYNC_CYCLES 4)
++])
++
++
++;
++; An enumeration of values for each "unspec"; i.e. unspecified
++; instruction.  These represent insns that are meaningful on the
++; 6809 but which have no intrinsic meaning to GCC itself.
++; These insns can be generated explicitly using the __builtin_xxx
++; syntax; they are also implicitly generated by the backend
++; as needed to implement other insns.
++;
++(define_constants [
++  (UNSPEC_BLOCKAGE 0)
++  (UNSPEC_PUSH_RS 1)
++  (UNSPEC_POP_RS 2)
++  (UNSPEC_SWI 3)
++  (UNSPEC_CWAI 4)
++  (UNSPEC_ADD_CARRY 5)
++  (UNSPEC_SUB_CARRY 6)
++  (UNSPEC_SYNC 7)
++  (UNSPEC_ADD_DECIMAL 8)
++])
++
++
++;;--------------------------------------------------------------------
++;;-  Predicates
++;;--------------------------------------------------------------------
++
++(include "predicates.md")
++
++;;--------------------------------------------------------------------
++;;-  Attributes
++;;--------------------------------------------------------------------
++
++;;
++;; The type attribute is used to distinguish between different
++;; types of branch instructions, so that their lengths can be
++;; calculated correctly.
++;;
++(define_attr "type" "branch,cbranch,unknown" (const_string "unknown"))
++
++;;
++;; The length of a branch instruction is calculated based on how
++;; far away the branch target is.  Lengths of other insns default
++;; to 4.  set_attr is used in instruction templates to specify
++;; the length when it is known exactly.  When not sure, err on
++;; the high side to avoid compile errors.
++;;
++(define_attr "length" ""
++  (cond [
++    (eq_attr "type" "branch")
++    (if_then_else (lt (minus (match_dup 0) (pc))
++                      (const_int MIN_SHORT_BRANCH_OFFSET))
++      (const_int LONG_BRANCH_LENGTH)
++        (if_then_else (gt (minus (match_dup 0) (pc))
++                          (const_int MAX_SHORT_BRANCH_OFFSET))
++          (const_int LONG_BRANCH_LENGTH)
++          (const_int SHORT_BRANCH_LENGTH)))
++    (eq_attr "type" "cbranch")
++    (if_then_else (lt (minus (match_dup 0) (pc))
++                      (const_int MIN_SHORT_BRANCH_OFFSET))
++      (const_int LONG_CBRANCH_LENGTH)
++        (if_then_else (gt (minus (match_dup 0) (pc))
++                          (const_int MAX_SHORT_BRANCH_OFFSET))
++          (const_int LONG_CBRANCH_LENGTH)
++          (const_int SHORT_CBRANCH_LENGTH)))
++  ] (const_int DEFAULT_INSN_LENGTH)))
++
++
++;;
++;; The default attributes for 'asm' statements.
++;; The default length is the longest possible single 6809 instruction,
++;; which is 5 bytes.  GCC will automatically multiply this by the
++;; number of real insns contained in an asm statement.
++;;
++(define_asm_attributes
++  [(set_attr "length" "5")
++   (set_attr "type" "unknown")])
++
++;;
++;; An attribute for the number of cycles that it takes an instruction
++;; to execute.
++;;
++(define_attr "cycles" "" (const_int DEFAULT_INSN_CYCLES))
++
++
++;;--------------------------------------------------------------------
++;;- Instruction patterns.  When multiple patterns apply,
++;;- the first one in the file is chosen.
++;;-
++;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
++;;-
++;;- Note: NOTICE_UPDATE_CC in m6809.h handles condition code updates
++;;- for most instructions.
++;;--------------------------------------------------------------------
++
++;;--------------------------------------------------------------------
++;;-  Test
++;;--------------------------------------------------------------------
++
++;; cmpx is 3 bytes, not 4
++(define_insn "*tsthi_x"
++  [(set (cc0) (match_operand:HI 0 "register_operand_x" "v"))]
++  ""
++  "cmpx\t#0"
++  [(set_attr "length" "3")])
++
++;; subd #0 is 3 bytes, better than cmpd #0 which is 4 bytes
++(define_insn "*tsthi_d"
++  [(set (cc0) (match_operand:HI 0 "register_operand_d" "d"))]
++  ""
++  "subd\t#0"
++  [(set_attr "length" "3")])
++
++(define_insn "*tsthi"
++  [(set (cc0) (match_operand:HI 0 "register_operand" "a"))]
++  ""
++  "cmp%0\t#0"
++   [(set_attr "length" "4")])
++
++(define_insn "*bitqi3"
++  [(set (cc0)
++    (and:QI (match_operand:QI 0 "register_operand" "%q")
++      (match_operand:QI 1 "general_operand" "mi")))]
++  ""
++  "bit%0\t%1"
++  [(set_attr "length" "3")])
++
++
++(define_insn "tstqi"
++  [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" "q,mt"))]
++  ""
++  "@
++   tst%0
++   tst\t%0"
++   [(set_attr "length" "1,3")])
++
++;;--------------------------------------------------------------------
++;;- Compare instructions
++;;--------------------------------------------------------------------
++
++;; - cmphi for register to memory or register compares
++(define_insn "cmphi"
++  [(set (cc0)
++    (compare
++      (match_operand:HI 0 "general_operand" "da, mi, ??Ud")
++      (match_operand:HI 1 "general_operand" "mi, da,  dU")))]
++  ""
++{
++  if ((REG_P (operands[0])) && (REG_P (operands[1]))) {
++    output_asm_insn ("pshs\t%1\t;cmphi: R:%1 with R:%0", operands);
++    return "cmp%0\t,s++\t;cmphi:";
++  }
++  if (GET_CODE (operands[0]) == REG)
++    return "cmp%0\t%1\t;cmphi:";
++  else {
++    cc_status.flags |= CC_REVERSED;
++    return "cmp%1\t%0\t;cmphi:(R)";
++  }
++}
++  [(set_attr "length" "5,5,7")])
++
++
++(define_insn "cmpqi"
++  [(set (cc0)
++    (compare (match_operand:QI 0 "whole_general_operand" "q,q, q,O,mt,K")
++    (match_operand:QI 1 "whole_general_operand"          "O,mt,K,q,q, q")))]
++  ""
++{
++    if (REG_P (operands[0]) && !M_REG_P (operands[0]))
++    {
++      if (operands[1] == const0_rtx)
++        return "tst%0\t;cmpqi:(ZERO)";
++      else
++        return "cmp%0\t%1\t;cmpqi:";
++    }
++    else
++    {
++      cc_status.flags |= CC_REVERSED;
++
++      if (operands[0] == const0_rtx)
++        return "tst%1\t;cmpqi:(RZERO)";
++      else
++        return "cmp%1\t%0\t;cmpqi:(R)";
++    }
++}
++   [(set_attr "length" "1,3,2,1,3,2")])
++
++
++;;--------------------------------------------------------------------
++;;- Compare/branch pattern
++;;--------------------------------------------------------------------
++
++(define_expand "cbranchhi4"
++  [(set (cc0)
++    (compare
++      (match_operand:HI 1 "general_operand" "da, mi, ??Ud")
++      (match_operand:HI 2 "general_operand" "mi, da,  dU")))
++   (set (pc)
++     (if_then_else
++        (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)])
++        (label_ref (match_operand 3 "" ""))
++        (pc)))]
++   ""
++   ""
++)
++
++(define_expand "cbranchqi4"
++  [(set (cc0)
++    (compare
++      (match_operand:QI 1 "whole_general_operand" "q,q, q,O,mt,K")
++      (match_operand:QI 2 "whole_general_operand" "O,mt,K,q,q, q")))
++   (set (pc)
++     (if_then_else
++        (match_operator 0 "ordered_comparison_operator" [(cc0) (const_int 0)])
++        (label_ref (match_operand 3 "" ""))
++        (pc)))]
++   ""
++   ""
++)
++
++;;--------------------------------------------------------------------
++;;-  Move
++;;--------------------------------------------------------------------
++
++; this looks good (obviously not finished) but I still see 'movsi'
++; places in udivsi3 where it's broken
++; (define_insn "pushsi1"
++;   [(set (mem:SI (pre_dec (reg:HI HARD_S_REGNUM)))
++;         (match_operand:SI 0 "general_operand" "o"))
++;    (set (reg:HI HARD_S_REGNUM)
++;         (plus:HI (reg:HI HARD_S_REGNUM) (const_int -4))) ]
++;   ""
++;   "; pushsi %0"
++;    [(set_attr "length" "12")])
++;
++; (define_insn "popsi1"
++;   [(set (match_operand:SI 0 "general_operand" "=o")
++;         (mem:SI (post_inc (reg:HI HARD_S_REGNUM))))
++;    (set (reg:HI HARD_S_REGNUM)
++;         (plus:HI (reg:HI HARD_S_REGNUM) (const_int 4))) ]
++;   ""
++;   "; popsi %0"
++;    [(set_attr "length" "12")])
++
++; (define_insn "movsi"
++;   [(set (match_operand:SI 0 "nonimmediate_operand" "=o")
++;         (match_operand:SI 1 "general_operand"      " oi"))]
++;   ""
++;   "; movsi %0 <- %1"
++;    [(set_attr "length" "1")])
++
++; this doesn't work
++; (define_expand "movsi"
++;   [(parallel [
++;      (set (match_operand:SI 0 "nonimmediate_operand" "")
++;           (match_operand:SI 1 "general_operand" ""))
++;      (clobber (match_scratch:HI 2 ""))])]
++;   ""
++; {
++;   rtx insn;
++;   if (STACK_PUSH_P (operands[0]) || STACK_POP_P (operands[1]))
++;   {
++;     REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, stack_pointer_rtx, REG_NOTES (insn));
++;   }
++;   insn = emit_move_multi_word (SImode, operands[0], operands[1]);
++;   DONE;
++; })
++
++
++(define_expand "movhi"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++    (match_operand:HI 1 "general_operand" ""))]
++  ""
++{
++  /* One of the ops has to be in a register prior to reload */
++  if (!register_operand (operand0, HImode) &&
++      !register_operand (operand1, HImode))
++    operands[1] = copy_to_mode_reg (HImode, operand1);
++})
++
++;;; Try a splitter to handle failure cases where we try to move
++;;; an immediate constant (zero usually) directly to memory.
++;;; This absolutely requires an intermediate register.
++(define_split
++  [(set (match_operand:HI 0 "memory_operand" "")
++    (match_operand:HI 1 "immediate_operand"  ""))
++   (clobber (match_operand:HI 2 "register_operand" ""))]
++  ""
++  [(set (match_dup 2) (match_dup 1))
++   (set (match_dup 0) (match_dup 2))]
++  "")
++
++
++;;; This would be a nice method for loading from a word array,
++;;; but it is never generated because the combiner cannot merge
++;;; more than 3 instructions (there are four here).  This is
++;;; perhaps better done via a peephole.
++(define_insn "*movhi_array_load"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=da")
++    (mem:HI (plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%B")) (const_int 1))
++                     (match_operand:HI 2 "immediate_operand" "i"))))
++   (clobber (match_scratch:HI 3 "=X"))]
++  ""
++  "ldx\t%2\;abx\;abx\;ld%0\t,x"
++   [(set_attr "length" "7")])
++
++
++;;; Optimize the move of a byte to the stack using the pshs instruction
++;;; instead of a store with pre-increment.
++(define_insn "movhi_push"
++  [(set (match_operand:HI 0 "push_operand" "=m")
++    (match_operand:HI 1 "register_operand" "U"))]
++  ""
++  "pshs\t%1"
++  [(set_attr "length" "2")])
++
++
++(define_insn "*movhi_pic_symbolref"
++  [(set (match_operand:HI 0 "register_operand" "=a")
++    (match_operand:HI 1 "symbolic_operand" ""))]
++  "flag_pic"
++  "lea%0\t%c1,pcr"
++   [(set_attr "length" "4")])
++
++
++(define_insn "*movhi_1"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=a,d,a,ad,tmu")
++    (match_operand:HI 1 "general_operand"          " a,a,d,tmiu,ad"))]
++  ""
++  "@
++   lea%0\t,%1
++   tfr\t%1,%0
++   tfr\t%1,%0
++   ld%0\t%1
++   st%1\t%0"
++   [(set_attr "length" "2,2,2,*,*")])
++
++
++;;; Generated by the combiner to merge an address calculation with
++;;; a byte load.  We can use the 'abx' instruction here.
++(define_insn "*movqi_array_load"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=q")
++    (mem:QI (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%B"))
++                     (match_operand:HI 2 "immediate_operand" "i"))))
++   (clobber (match_scratch:HI 3 "=X"))]
++  ""
++  "ldx\t%2\;abx\;ld%0\t,x"
++   [(set_attr "length" "6")])
++
++
++;;; Optimize the move of a byte to the stack using the pshs instruction
++;;; instead of a store with pre-increment.
++(define_insn "movqi_push"
++  [(set (match_operand:QI 0 "push_operand" "=m")
++    (match_operand:QI 1 "register_operand" " q"))]
++  ""
++  "pshs\t%1"
++  [(set_attr "length" "2")])
++
++
++;;; Optimize the move of a byte from the stack using the puls instruction
++;;; instead of a store with post-decrement.
++(define_insn "movqi_pop"
++  [(set (match_operand:QI 0 "register_operand" "=q")
++    (match_operand:QI 1 "pop_operand" "m"))]
++  ""
++  "puls\t%0"
++  [(set_attr "length" "2")])
++
++
++;;- load low byte of 16-bit data into 8-bit register/memory
++(define_insn "*mov_lsb"
++  [(set (match_operand:QI 0 "nonimmediate_operand"    "=q,q,q,m,!q")
++      (subreg:QI (match_operand:HI 1 "general_operand" "d,m,a,d, U") 1))]
++  ""
++  "@
++   \t;movlsbqihi: D->B
++   ld%0\t%L1\t;movlsbqihi: msb:%1 -> R:%0
++   tfr\t%1,d\t;movlsbqihi: R:%1 -> R:%0
++   stb\t%0\t;movlsbqihi: R:%1 -> %0
++   pshs\t%1\t;movlsbqihi: R:%1 -> R:%0\;leas\t1,s\;puls\t%0"
++   [(set_attr "length" "0,*,2,*,6")])
++
++
++;;- load high byte of 16-bit data into 8-bit register/memory
++(define_insn "*mov_msb"
++  [(set (match_operand:QI 0 "nonimmediate_operand"    "=q,q,q,q,m,!q")
++      (subreg:QI (match_operand:HI 1 "general_operand" "d,O,a,m,d, U") 0))]
++  ""
++  "@
++   tfr\ta,b\t;movmsbqihi: D->B
++   clr%0\t\t;movmsbqihi: ZERO -> R:%0
++   tfr\t%1,d\t;movmsbqihi: R:%1 -> R:%0\;tfr\ta,b
++   ld%0\t%L1\t;movmsbqihi: lsb:%1 -> R:%0
++   sta\t%0\t;movmsbqihi: R:%1 -> %0
++   pshs\t%1\t;movmsbqihi: R:%1 -> R:%0\;puls\t%0\;leas\t1,s"
++  [(set_attr "length" "2,1,4,*,*,6")])
++
++
++(define_insn "*movqi_boolean"
++  [(set (reg:QI HARD_Z_REGNUM)
++    (match_operand:QI 0 "general_operand" "q,O,i,m"))]
++  ""
++  "@
++   tst%0
++   andcc\t#~4
++   orcc\t#4
++   tst\t%0")
++
++
++(define_insn "movqi"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q,tm,q,tm,q,z")
++    (match_operand:QI 1 "general_operand"          " q,O,O,tmi,q,z,q"))]
++  ""
++  "@
++   tfr\t%1,%0
++   clr%0
++   clr\t%0
++   ld%0\t%1
++   st%1\t%0
++   tfr\tcc,%0\;and%0\t#4
++   tst%0"
++   [(set_attr "length" "2,1,3,*,*,4,1")])
++
++
++;;--------------------------------------------------------------------
++;;-  Swap registers
++;;--------------------------------------------------------------------
++
++; Note: 8-bit swap is never needed so it is not defined.
++
++(define_insn "swaphi"
++  [(set (match_operand:HI 0 "register_operand" "+r")
++    (match_operand:HI 1 "register_operand" "+r"))
++   (set (match_dup 1) (match_dup 0))]
++  ""
++  "exg\t%1,%0"
++  [(set_attr "length" "2")
++   (set (attr "cycles") (const_int EXG_CYCLES))])
++
++
++(define_insn "bswaphi2"
++  [(set (match_operand:HI 0 "register_operand" "=d")
++    (bswap:HI (match_operand:HI 1 "register_operand" "0")))]
++  ""
++  "exg\ta,b"
++  [(set_attr "length" "2")])
++
++
++;;--------------------------------------------------------------------
++;;-  Extension and truncation insns.
++;;--------------------------------------------------------------------
++
++(define_insn "extendqihi2"
++  [(set (match_operand:HI 0 "register_operand" "=d")
++        (sign_extend:HI (match_operand:QI 1 "general_operand" "B")))]
++  ""
++  "sex\t\t;extendqihi2: R:%1 -> R:%0"
++  [(set_attr "length" "1")])
++
++
++(define_insn "zero_extendqihi2"
++  [(set (match_operand:HI 0 "register_operand" "=d")
++        (zero_extend:HI (match_operand:QI 1 "general_operand" "B")))]
++  ""
++  "clra\t\t;zero_extendqihi: R:%1 -> R:%0"
++  [(set_attr "length" "1")])
++
++
++;;--------------------------------------------------------------------
++;;- All kinds of add instructions.
++;;--------------------------------------------------------------------
++
++
++;;
++;; gcc's automatic version of addsi3 doesn't know about adcb,adca
++;; so it is MUCH less efficient.  Define this one ourselves.
++;;
++;; TODO - can't always get 'd' for the clobber... allow other registers
++;; as well and use exg d,R ... exg R,d around the code sequence to
++;; use others, at a price.  Also consider libcall for this when
++;; optimizing for size.
++;;
++(define_insn "addsi3"
++  [(set (match_operand:SI 0 "nonimmediate_operand"  "=o")
++     (plus:SI (match_operand:SI 1 "general_operand" "%o")
++        (match_operand:SI 2 "general_operand"       " oi")))
++   (clobber (match_scratch:HI 3 "=d"))]
++  ""
++{
++  m6809_output_addsi3 (PLUS, operands);
++  return "";
++}
++  [(set_attr "length" "21")])
++
++
++; Increment of a 16-bit MEM by 1 can be done without a register.
++(define_insn "*addhi_mem_1"
++  [(set (match_operand:HI 0 "memory_operand" "=m")
++        (plus:HI (match_operand:HI 1 "memory_operand" "0") (const_int 1)))]
++   "GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF"
++{
++  rtx xoperands[2];
++
++  xoperands[0] = operands[0];
++  xoperands[1] = adjust_address (operands[0], QImode, 1);
++
++  output_asm_insn ("inc\t%1", xoperands);
++  output_asm_insn ("bne\t__IL%=", xoperands);
++  output_asm_insn ("inc\t%0\;__IL%=:", xoperands);
++  return "";
++}
++  [(set_attr "length" "7")])
++
++
++; Decrement of a 16-bit MEM by 1 can be done without a register.
++(define_insn "*addhi_mem_minus1"
++  [(set (match_operand:HI 0 "memory_operand" "=m")
++        (plus:HI (match_operand:HI 1 "memory_operand" "0") (const_int -1)))]
++   "GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF"
++{
++  rtx xoperands[2];
++
++  xoperands[0] = operands[0];
++  xoperands[1] = adjust_address (operands[0], QImode, 1);
++
++  output_asm_insn ("tst\t%1", xoperands);
++  output_asm_insn ("bne\t__IL%=", xoperands);
++  output_asm_insn ("dec\t%0", xoperands);
++  output_asm_insn ("__IL%=:", xoperands);
++  output_asm_insn ("dec\t%1", xoperands);
++  return "";
++}
++  [(set_attr "length" "7")])
++
++
++; Allow the addition of an 8-bit quantity to a 16-bit quantity
++; using the LEAX B,Y addressing mode, where X and Y are both
++; index registers.  This will only get generated via the peephole
++; which removes a sign extension.
++(define_insn "*addhi_b"
++  [(set (match_operand:HI 0 "index_register_operand"       "=a")
++    (plus:HI(match_operand:HI 1 "index_register_operand"   "%a")
++    (match_operand:QI 2 "register_operand"                  "q")
++  ))]
++  ""
++  "lea%0\t%2,%1\t;addhi_b: R:%0 = R:%2 + R:%1"
++  [(set_attr "length" "*")])
++
++
++; Splitter for addhi pattern #5 below
++(define_split
++  [(set (match_operand:HI 0 "index_register_operand" "")
++    (plus:HI (match_dup 0) (match_operand:HI 1 "memory_operand" "")))]
++  "reload_completed"
++  [
++   (parallel [(set (match_dup 0) (reg:HI HARD_D_REGNUM))
++              (set (reg:HI HARD_D_REGNUM) (match_dup 0))])
++   (set (reg:HI HARD_D_REGNUM)
++        (plus:HI (reg:HI HARD_D_REGNUM) (match_dup 1)))
++   (parallel [(set (match_dup 0) (reg:HI HARD_D_REGNUM))
++              (set (reg:HI HARD_D_REGNUM) (match_dup 0))])
++   ]
++{
++})
++
++
++; Splitter for addhi pattern #7 below
++(define_split
++  [(set (match_operand:HI 0 "index_register_operand" "")
++    (plus:HI (match_dup 0) (match_operand:HI 1 "index_register_operand" "")))]
++  "reload_completed"
++  [
++   (parallel [(set (match_dup 1) (reg:HI HARD_D_REGNUM))
++              (set (reg:HI HARD_D_REGNUM) (match_dup 1))])
++   (set (match_dup 0)
++        (plus:HI (reg:HI HARD_D_REGNUM) (match_dup 0)))
++   (parallel [(set (match_dup 1) (reg:HI HARD_D_REGNUM))
++              (set (reg:HI HARD_D_REGNUM) (match_dup 1))])
++   ]
++{
++})
++
++
++; TODO - this is ugly.  During RTL generation, we don't know what registers
++; are available, so the multiple-insn sequences can only be solved
++; via 'define_split's during matching.  See andhi3 for an example.
++; Keep the constraints with ? modifiers to help reload pick the right
++; registers.
++;
++; The forms are:
++; 1. D += D, expand this into a shift instead. (rtx costs should be corrected
++; to avoid this even happening...)
++; 2. D += U, require U to be pushed to memory.  (Lots of patterns do this
++; now, is this a better way?)
++; 3. Best choice: 'addd'
++; 4. Next best choice: 'lea'
++; 5. Hybrid of 3 and 4
++; 6. Same as 4, not bad
++; 7. BAD, no D register at all
++; 8. 'lea', as good as 4.
++(define_insn "addhi3"
++  [(set (match_operand:HI 0 "nonimmediate_operand"      "=d, d,  d,  a,?a, a,???T,a")
++    (plus:HI(match_operand:HI 1 "add_general_operand"   "%0, 0,  0,  d, 0, a, 0, a")
++    (match_operand:HI 2 "general_operand"               " 0, !U, mi, a, m, d, T, i")
++  ))]
++  ""
++  "@
++   lslb\t\t;addhi: R:%0 += R:%2\;rola\t\t;also R:%0 *= 2
++   pshs\t%2\t;addhi: R:%0 += R:%2\;add%0\t,s++
++   add%0\t%2
++   lea%0\t%1,%2
++   #
++   lea%0\t%2,%1
++   #
++   lea%0\t%a2,%1"
++   [(set_attr "length" "2,6,*,*,7,*,7,*")])
++
++
++(define_insn "addqi3_carry"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=q")
++    (unspec:QI [
++      (match_operand:QI 1 "whole_general_operand" "%0")
++      (match_operand:QI 2 "whole_general_operand" "tmi")] UNSPEC_ADD_CARRY))]
++  ""
++  "adc%0\t%2\t;addqi_carry: R:%0 += %2"
++  [(set_attr "length" "*")])
++
++
++; TODO: specifying 'A' for the first constraint, to force into the A register
++; is not working because of the way registers are currently set up.  This will
++; take some work to get right.  Thus the second alternative as a backup.
++(define_insn "addqi3_decimal"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=A,?q")
++    (unspec:QI [
++      (match_operand:QI 1 "general_operand"        "%0,0")
++      (match_operand:QI 2 "general_operand"        "tmi,tmi")] UNSPEC_ADD_DECIMAL))]
++  ""
++  "@
++   adda\t%2\;daa
++   tfr\t%0,a\;adda\t%2\;daa\;tfr\ta,%0"
++  [(set_attr "length" "5,9")])
++
++
++(define_insn "addqi3"
++  [(set (match_operand:QI 0 "nonimmediate_operand"       "=q,q,q,tm,tm,q")
++    (plus:QI (match_operand:QI 1 "whole_general_operand" "%0,0,0,0,0,0")
++    (match_operand:QI 2 "whole_general_operand"          " 0,I,N,I,N,tmi")))]
++  ""
++  "@
++   asl%0\t\t;addqi: R:%0 = R:%0 + R:%0
++   inc%0
++   dec%0
++   inc\t%0
++   dec\t%0
++   add%0\t%2"
++  [(set_attr "length" "1,1,1,3,3,*")])
++
++
++;;--------------------------------------------------------------------
++;;- Subtract instructions.
++;;--------------------------------------------------------------------
++
++(define_insn "subsi3"
++  [(set (match_operand:SI 0 "nonimmediate_operand"  "=o")
++     (minus:SI (match_operand:SI 1 "general_operand" " o")
++        (match_operand:SI 2 "general_operand"       " oi")))
++   (clobber (match_scratch:HI 3 "=d"))]
++  ""
++{
++  m6809_output_addsi3 (MINUS, operands);
++  return "";
++}
++  [(set_attr "length" "21")])
++
++
++(define_insn "subhi3"
++  [(set (match_operand:HI 0 "register_operand"      "=d,  d, a")
++    (minus:HI (match_operand:HI 1 "register_operand" "0,  0, 0")
++    (match_operand:HI 2 "general_operand"            "mi, ?U,n")))]
++  ""
++  "@
++   sub%0\t%2\t;subhi: R:%0 -= %2
++   pshs\t%2\t;subhi: R:%0 -= R:%2\;sub%0\t,s++
++   lea%0\t%n2,%1\t;subhi: R:%0 = R:%1 + %n2"
++   [(set_attr "length" "*,5,3")])
++
++
++(define_insn "subqi3_carry"
++  [(set (match_operand:QI 0 "register_operand" "=q")
++    (unspec:QI [
++      (match_operand:QI 1 "whole_general_operand" "%0")
++      (match_operand:QI 2 "whole_general_operand" "tmi")] UNSPEC_SUB_CARRY))]
++  ""
++  "sbc%0\t%2\t;subqi_carry: R:%0 += %2"
++  [(set_attr "length" "*")])
++
++
++(define_insn "subqi3"
++  [(set (match_operand:QI 0 "register_operand"            "=q, q, !q, !q,   q")
++    (minus:QI (match_operand:QI 1 "whole_register_operand" "0, 0,  I,  tmn, 0")
++    (match_operand:QI 2 "whole_general_operand"            "I, mi, 0,  0,   t")))]
++  ""
++  "@
++   dec%0
++   sub%0\t%2
++   dec%0\;neg%0
++   sub%0\t%1\;neg%0
++   sub%0\t%2"
++   [(set_attr "length" "1,3,2,4,3")])
++
++
++;;--------------------------------------------------------------------
++;;- Multiply instructions.
++;;--------------------------------------------------------------------
++
++; TODO - merge these two instructions, using 'extend_operator' to match
++; either signed or zero extension.  Everything else is the same.
++(define_insn "mulqihi3"
++   [(set (match_operand:HI 0 "register_operand" "=d")
++      (mult:HI (sign_extend:HI (match_operand:QI 1 "general_operand" "%q"))
++      (match_operand:QI 2 "general_operand" "tmK")))]
++  ""
++  "lda\t%2\t;mulqihi3\;mul"
++  [(set_attr "length" "3")])
++
++
++(define_insn "umulqihi3"
++   [(set (match_operand:HI 0 "register_operand" "=d")
++    (mult:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "%q"))
++    (match_operand:QI 2 "general_operand" "tmK")))]
++  ""
++  "lda\t%2\t;umulqihi3\;mul"
++  [(set_attr "length" "3")])
++
++
++; Expand a 16x16 multiplication into either a libcall or a shift.
++; If the second operand is a small constant, use the above form.
++; Otherwise, do a libcall.
++(define_expand "mulhi3"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++    (mult:HI (match_operand:HI 1 "general_operand" "")
++    (match_operand:HI 2 "nonmemory_operand" "")))]
++  ""
++{
++  emit_libcall_insns (HImode, "mulhi3", operands, 2);
++  DONE;
++})
++
++
++;;--------------------------------------------------------------------
++;;- Divide instructions.
++;;--------------------------------------------------------------------
++
++(define_expand "divhi3"
++  [(set (match_operand:HI 0 "register_operand" "")
++    (div:HI (match_operand:HI 1 "register_operand" "")
++    (match_operand:HI 2 "register_operand" "")))]
++  ""
++{
++  emit_libcall_insns (HImode, "divhi3", operands, 2);
++  DONE;
++})
++
++
++(define_expand "divqi3"
++  [(set (match_operand:QI 0 "register_operand" "")
++    (div:QI (match_operand:QI 1 "register_operand" "")
++    (match_operand:QI 2 "register_operand" "")))]
++  ""
++{
++  emit_libcall_insns (QImode, "divqi3", operands, 2);
++  DONE;
++})
++
++
++(define_expand "udivhi3"
++  [(set (match_operand:HI 0 "register_operand" "")
++     (udiv:HI (match_operand:HI 1 "register_operand" "")
++              (match_operand:HI 2 "register_operand" "")))]
++  ""
++{
++  emit_libcall_insns (HImode, "udivhi3", operands, 2);
++  DONE;
++})
++
++
++;;--------------------------------------------------------------------
++;;- mod
++;;--------------------------------------------------------------------
++
++(define_expand "modhi3"
++  [(set (match_operand:HI 0 "register_operand" "")
++    (mod:HI (match_operand:HI 1 "register_operand" "")
++    (match_operand:HI 2 "register_operand" "")))]
++  ""
++{
++  emit_libcall_insns (HImode, "modhi3", operands, 2);
++  DONE;
++})
++
++
++(define_expand "modqi3"
++  [(set (match_operand:QI 0 "register_operand" "")
++    (mod:QI (match_operand:QI 1 "register_operand" "")
++    (match_operand:QI 2 "register_operand" "")))]
++  ""
++{
++  emit_libcall_insns (QImode, "modqi3", operands, 2);
++  DONE;
++})
++
++
++(define_expand "umodhi3"
++  [(set (match_operand:HI 0 "register_operand" "")
++    (umod:HI (match_operand:HI 1 "register_operand" "")
++    (match_operand:HI 2 "register_operand" "")))]
++  ""
++{
++  emit_libcall_insns (HImode, "umodhi3", operands, 2);
++  DONE;
++})
++
++
++
++;;--------------------------------------------------------------------
++;;- and, or, xor common patterns
++;;--------------------------------------------------------------------
++
++; Split a bitwise HImode into two QImode instructions, with one of
++; the sources in a pushable register.  The register is pushed onto
++; the stack and memory pop operands (,s+) are used in the QI forms.
++(define_split
++  [(set (match_operand:HI 0 "register_operand" "")
++    (match_operator:HI 3 "logical_bit_operator"
++      [(match_operand:HI 1 "register_operand" "")
++       (match_operand:HI 2 "register_operand" "")]))]
++  "reload_completed"
++  [(set (mem:HI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (match_dup 2))
++   (set (reg:QI HARD_A_REGNUM) (match_op_dup:QI 3
++         [(reg:QI HARD_A_REGNUM)
++          (mem:QI (post_inc:QI (reg:HI HARD_S_REGNUM)))]))
++   (set (reg:QI HARD_D_REGNUM) (match_op_dup:QI 3
++         [(reg:QI HARD_D_REGNUM)
++          (mem:QI (post_inc:QI (reg:HI HARD_S_REGNUM)))]))
++   (use (reg:QI HARD_A_REGNUM))]
++{
++})
++
++; Split a bitwise HImode into two QImode instructions, with one
++; of the sources being a (MEM (MEM (...)); i.e. an indirect memory
++; reference.  This requires dereferencing the pointer into a
++; temporary register (X), which must be saved/restored around the
++; compute instructions.
++(define_split 
++  [(set (match_operand:HI 0 "register_operand" "")
++    (match_operator:HI 3 "logical_bit_operator"
++      [(match_operand:HI 1 "register_operand" "")
++       (mem:HI (match_operand:HI 2 "memory_operand" ""))]))]
++  "reload_completed"
++  [
++   (set (mem:HI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (match_dup 4))
++   (set (match_dup 4) (match_dup 2))
++   (set (match_dup 4) (mem:HI (match_dup 4)))
++   (set (reg:QI HARD_A_REGNUM) (match_op_dup:QI 3
++         [(reg:QI HARD_A_REGNUM)
++          (mem:QI (post_inc:QI (match_dup 4)))]))
++   (set (reg:QI HARD_D_REGNUM) (match_op_dup:QI 3
++         [(reg:QI HARD_D_REGNUM)
++          (mem:QI (post_inc:QI (match_dup 4)))]))
++   (use (reg:QI HARD_A_REGNUM))
++   (set (match_dup 4) (mem:HI (post_inc:HI (reg:HI HARD_S_REGNUM))))
++   ]
++{
++  /* Use X for a temporary index register */
++  operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
++})
++
++
++; Split a bitwise HImode into two QImode instructions.  This is
++; the common case.  This handles splitting when neither of the
++; above two cases applies.
++(define_split 
++  [(set (match_operand:HI 0 "register_operand" "")
++    (match_operator:HI 3 "logical_bit_operator"
++      [(match_operand:HI 1 "register_operand" "")
++       (match_operand:HI 2 "general_operand" "")]))]
++  "reload_completed"
++  [(set (reg:QI HARD_A_REGNUM) (match_op_dup:QI 3
++      [(reg:QI HARD_A_REGNUM) (match_dup 4)]))
++   (set (reg:QI HARD_D_REGNUM) (match_op_dup:QI 3
++      [(reg:QI HARD_D_REGNUM) (match_dup 5)]))
++   (use (reg:QI HARD_A_REGNUM))]
++{
++  if (GET_CODE (operands[2]) == CONST_INT)
++  {
++    operands[4] = gen_rtx_const_high (operands[2]);
++    operands[5] = gen_rtx_const_low (operands[2]);
++  }
++  else if ((GET_CODE (operands[2]) == MEM)
++    && (GET_CODE (XEXP (operands[2], 0)) == MEM))
++  {
++    FAIL;
++  }
++  else
++  {
++    operands[4] = gen_highpart (QImode, operands[2]);
++    operands[5] = gen_lowpart (QImode, operands[2]);
++  }
++})
++
++; Below are the specific cases for each of the operators.
++; The QImode versions are the simplest and can be implemented
++; directly on the hardware.  The HImode cases are all output
++; using one of the above splitting techniques.
++
++;;--------------------------------------------------------------------
++;;- and
++;;--------------------------------------------------------------------
++
++(define_insn "andhi3"
++  [(set (match_operand:HI 0 "register_operand" "=d")
++    (and:HI (match_operand:HI 1 "register_operand" "%0")
++    (match_operand:HI 2 "general_operand" "mnU")))]
++  ""
++  "#")
++
++;; it is not clear that this is correct
++(define_insn "*andqi_2"
++  [(set
++   (match_operand:QI 0 "register_operand" "=q")
++   (and:QI (match_operand:QI 1 "register_operand" "q")
++     (match_operand 2 "const_int_operand" "i")))]
++  ""
++{
++  if (GET_CODE (operands[2]) == CONST_INT)
++  {
++    operands[3] = GEN_INT(INTVAL(operands[2]) & 0xff);
++    return "and%0 %3";
++  }
++
++  return "and%0 %2";
++}
++  [(set_attr "length" "2")])
++
++(define_insn "andqi3"
++  [(set (match_operand:QI 0 "register_operand"           "=q,q,q,qc")
++    (and:QI (match_operand:QI 1 "whole_register_operand" "%0,0,0,0")
++    (match_operand:QI 2 "whole_general_operand"          " O,N,tm,i")))]
++  ""
++  "@
++   clr%0\t;andqi(ZERO)
++   \t;andqi(-1)
++   and%0\t%2
++   and%0\t%2"
++   [(set_attr "length" "1,0,3,2")])
++
++
++;;--------------------------------------------------------------------
++;;- or
++;;--------------------------------------------------------------------
++
++(define_insn "iorhi3"
++  [(set (match_operand:HI 0 "register_operand" "=d")
++    (ior:HI (match_operand:HI 1 "register_operand" "%0")
++    (match_operand:HI 2 "general_operand" "mnU")))]
++  ""
++  "#")
++
++
++(define_insn "iorqi3"
++  [(set (match_operand:QI 0 "register_operand"           "=q,q, qc")
++    (ior:QI (match_operand:QI 1 "whole_register_operand" "%0,0, 0")
++    (match_operand:QI 2 "whole_general_operand"          " O,tm,i")))]
++  ""
++  "@
++   \t;iorqi(ZERO)
++   or%0\t%2
++   or%0\t%2"
++   [(set_attr "length" "0,3,2")])
++
++;;--------------------------------------------------------------------
++;;- xor
++;;--------------------------------------------------------------------
++
++(define_insn "xorhi3"
++  [(set (match_operand:HI 0 "register_operand" "=d")
++    (xor:HI (match_operand:HI 1 "register_operand" "%0")
++    (match_operand:HI 2 "general_operand" "mnU")))]
++  ""
++  "#")
++
++
++(define_insn "xorqi3"
++  [(set (match_operand:QI 0 "register_operand"           "=q,q,q,q")
++    (xor:QI (match_operand:QI 1 "whole_register_operand" "%0,0,0,0")
++    (match_operand:QI 2 "whole_general_operand"          " O,N,tm,i")))]
++  ""
++  "@
++   \t;xorqi(ZERO)
++   com%0\t;xorqi(-1)
++   eor%0\t%2
++   eor%0\t%2"
++   [(set_attr "length" "0,1,3,2")])
++
++;;--------------------------------------------------------------------
++;;-  Two's Complements
++;;--------------------------------------------------------------------
++
++(define_insn "neghi2"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,!a")
++    (neg:HI (match_operand:HI 1 "general_operand"   "0, 0")))]
++  ""
++  "@
++   nega\;negb\;sbca\t#0
++   exg\td,%0\;nega\;negb\;sbca\t#0\;exg\td,%0"
++  [(set_attr "length" "5,9")])
++
++
++(define_insn "negqi2"
++  [(set (match_operand:QI 0 "nonimmediate_operand"    "=q,m")
++    (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
++  ""
++  "@
++   neg%0
++   neg\t%0"
++  [(set_attr "length" "1,3")])
++
++
++;;--------------------------------------------------------------------
++;;-  One's Complements
++;;--------------------------------------------------------------------
++
++(define_insn "one_cmplhi2"
++  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,?tm,???a")
++    (not:HI (match_operand:HI 1 "general_operand"   "0,  0,   0")))]
++  ""
++  "@
++   coma\;comb
++   com\t%0\;com\t%L0
++   exg\td,%0\;coma\;comb\;exg\td,%0"
++  [(set_attr "length" "2,6,6")])
++
++
++(define_insn "one_cmplqi2"
++  [(set (match_operand:QI 0 "nonimmediate_operand"    "=q,tm")
++    (not:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
++  ""
++  "@
++   com%0
++   com\t%0"
++  [(set_attr "length" "1,3")])
++
++;;--------------------------------------------------------------------
++;;- Shifts/rotates
++;;--------------------------------------------------------------------
++
++(define_code_iterator bit_code [ashift ashiftrt lshiftrt])
++(define_code_attr bit_code_name [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr")])
++
++(define_mode_iterator bit_mode [QI HI])
++(define_mode_attr bit_mode_name [(QI "qi3") (HI "hi3")])
++
++;; Emit RTL for any shift (handles all 3 opcodes and 2 mode sizes)
++
++(define_expand "<bit_code:bit_code_name><bit_mode:bit_mode_name>"
++  [(set (match_operand:bit_mode 0 "nonimmediate_operand" "")
++    (bit_code:bit_mode (match_operand:bit_mode 1 "general_operand" "")
++    (match_operand:bit_mode 2 "nonmemory_operand" "")))]
++  ""
++{
++})
++
++; Individual instructions implemented in the CPU.
++
++
++(define_insn "*ashift1"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q")
++    (ashift:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))]
++  ""
++  "@
++   asl\t%0
++   asl%0"
++  [(set_attr "length" "3,1")])
++
++(define_insn "*lshiftrt1"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q")
++    (lshiftrt:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))]
++  ""
++  "@
++   lsr\t%0
++   lsr%0"
++  [(set_attr "length" "3,1")])
++
++(define_insn "*ashiftrt1"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q")
++    (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))]
++  ""
++  "@
++   asr\t%0
++   asr%0"
++  [(set_attr "length" "3,1")])
++
++(define_insn "*rotate1"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q")
++    (rotate:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))]
++  ""
++  "@
++   rol\t%0
++   rol%0"
++  [(set_attr "length" "3,1")])
++
++
++(define_insn "*rotatert1"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,q")
++    (rotatert:QI (match_operand:QI 1 "general_operand" "0,0") (const_int 1)))]
++  ""
++  "@
++   ror\t%0
++   ror%0"
++  [(set_attr "length" "3,1")])
++
++
++; A shift by 8 for D reg can be optimized by just moving
++; between the A/B halves, and then zero/sign extending or
++; filling in zeroes.
++; Because GCC does not understand that 'A' and 'D' refer to
++; the same storage location, we must use 'USE' throughout
++; to prevent deletion of 'unnecessary' instructions.
++; Similar optimization for MEM would require a scratch register
++; so is not done here.
++
++(define_split
++  [(set (reg:HI HARD_D_REGNUM) (ashift:HI (reg:HI HARD_D_REGNUM) (const_int 8)))]
++  "reload_completed"
++  [
++   (use (reg:HI HARD_D_REGNUM))
++   (set (reg:QI HARD_A_REGNUM) (reg:QI HARD_D_REGNUM))
++   (use (reg:QI HARD_A_REGNUM))
++   (set (reg:QI HARD_D_REGNUM) (const_int 0))
++   ]
++  "")
++
++(define_split
++  [(set (reg:HI HARD_D_REGNUM) (lshiftrt:HI (reg:HI HARD_D_REGNUM) (const_int 8)))]
++  "reload_completed"
++  [
++   (use (reg:HI HARD_D_REGNUM))
++   (set (reg:QI HARD_D_REGNUM) (reg:QI HARD_A_REGNUM))
++   (use (reg:QI HARD_D_REGNUM))
++   (set (reg:HI HARD_D_REGNUM) (zero_extend:HI (reg:QI HARD_D_REGNUM)))
++   ]
++  "")
++
++(define_split
++  [(set (reg:HI HARD_D_REGNUM) (ashiftrt:HI (reg:HI HARD_D_REGNUM) (const_int 8)))]
++  "reload_completed"
++  [
++   (use (reg:HI HARD_D_REGNUM))
++   (set (reg:QI HARD_D_REGNUM) (reg:QI HARD_A_REGNUM))
++   (use (reg:QI HARD_D_REGNUM))
++   (set (reg:HI HARD_D_REGNUM) (sign_extend:HI (reg:QI HARD_D_REGNUM)))
++   ]
++  "")
++
++
++; On the WPC hardware, there is a shift register that can be used
++; to compute (1<<n) efficiently in two instructions.  Note that this
++; form only works when using -mint8 though, because C will promote
++; to 'int' when doing this operation.  TODO : we need a 16-bit form too.
++(define_insn "ashlqi3_wpc"
++  [(set (match_operand:QI 0 "nonimmediate_operand" "=q")
++    (ashift:QI (match_operand:QI 1 "immediate_operand" "I")
++    (match_operand:QI 2 "general_operand" "q")))]
++  "TARGET_WPC"
++  "st%2\t0x3FF7\;ld%0\t0x3FF7"
++  [(set_attr "length" "6")])
++
++
++; Internal instructions for shifting by a constant.
++; Two forms are provided, one for QImode, one for HImode.
++; These are always split into the above instructions
++; (except for QImode forms that directly match one of the
++; above instructions, in which the condition will not
++; allow the splitter to match).
++
++(define_insn_and_split "<bit_code:bit_code_name>hi3_const"
++  [(set (match_operand:HI 0 "nonimmediate_operand"     "=dm")
++    (bit_code:HI (match_operand:HI 1 "general_operand" "0")
++    (match_operand:HI 2 "immediate_operand"            "n")))]
++  ""
++  "#"
++  "reload_completed"
++  [(const_int 0)]
++{
++  m6809_split_shift (<bit_code:CODE>, operands);
++  DONE;
++})
++
++
++(define_insn_and_split "<bit_code:bit_code_name>qi3_const"
++  [(set (match_operand:QI 0 "nonimmediate_operand"     "=qm")
++    (bit_code:QI (match_operand:QI 1 "general_operand" "0")
++    (match_operand:QI 2 "immediate_operand"            "n")))]
++  "INTVAL (operands[2]) > 1"
++  "#"
++  "&& reload_completed"
++  [(const_int 0)]
++{
++  m6809_split_shift (<bit_code:CODE>, operands);
++  DONE;
++})
++
++; Internal instructions for shifting by a nonconstant.
++; These expand into complex assembly.
++
++(define_insn "<bit_code:bit_code_name>hi3_reg"
++  [(set (match_operand:HI 0 "nonimmediate_operand"     "=d")
++    (bit_code:HI (match_operand:HI 1 "general_operand" "0")
++    (match_operand:HI 2 "nonimmediate_operand"         "v")))]
++  ""
++{
++  m6809_output_shift_insn (<bit_code:CODE>, operands);
++  return "";
++}
++  [(set_attr "length" "20")])
++
++
++(define_insn "<bit_code:bit_code_name>qi3_reg"
++  [(set (match_operand:QI 0 "nonimmediate_operand"    "=q")
++    (bit_code:QI (match_operand:QI 1 "general_operand" "0")
++    (match_operand:QI 2 "nonimmediate_operand"         "v")))]
++  ""
++{
++  m6809_output_shift_insn (<bit_code:CODE>, operands);
++  return "";
++}
++  [(set_attr "length" "16")])
++
++
++
++;;--------------------------------------------------------------------
++;;-  Jumps and transfers
++;;--------------------------------------------------------------------
++
++;;; The casesi pattern is normally *not* defined; see 'tablejump' instead.
++(define_expand "casesi"
++  [(match_operand:HI 0 "register_operand" "")   ; index to jump on
++   (match_operand:HI 1 "immediate_operand" "")   ; lower bound
++   (match_operand:HI 2 "immediate_operand" "")   ; total range
++   (match_operand 3 "" "")   ; table label
++   (match_operand 4 "" "")]  ; out of range label
++  "TARGET_BYTE_INT && TARGET_CASESI"
++{
++  m6809_do_casesi (operands[0], operands[1], operands[2],
++                   operands[3], operands[4]);
++  DONE;
++})
++
++(define_insn "tablejump_short_offset"
++  [(set (pc)
++       (mem:HI (plus:HI (match_operand:HI 1 "register_operand" "U")
++                (zero_extend:HI (match_operand:QI 0 "register_operand" "q")))))]
++  ""
++  "jmp\t[b,x]\t;tablejump_short_offset"
++  [(set_attr "length" "3")])
++
++(define_insn "tablejump_long_offset"
++  [(set (pc)
++       (mem:HI (plus:HI (match_operand:HI 1 "register_operand" "U")
++                (match_operand:HI 0 "register_operand" "d"))))]
++  ""
++  "jmp\t[d,x]\t;tablejump_long_offset"
++  [(set_attr "length" "3")])
++
++
++ ;; A tablejump operation gives the address in operand 0, with the
++ ;; CODE_LABEL for the table in operand 1.  The 'define_expand'
++ ;; shows the arguments as GCC presents them.  For a register
++ ;; operand, the assembly code is straightforward.  For a MEM,
++ ;; assumed to be a SYMBOL_REF, two forms are given, one normal
++ ;; and one for PIC mode.
++ (define_expand "tablejump"
++    [(parallel [
++     (set (pc) (match_operand:HI 0 "" ""))
++     (use (label_ref (match_operand 1 "" "")))
++     (clobber (match_scratch:HI 2 ""))
++     ])]
++    ""
++ {
++ })
++
++
++(define_insn "*tablejump_reg"
++   [(parallel [
++      (set (pc)
++         (match_operand:HI 0 "register_operand" "a"))
++      (use (label_ref (match_operand 1 "" "")))
++      (clobber (match_scratch:HI 2 ""))
++      ])]
++   ""
++   "jmp\t,%0"
++   [(set_attr "length" "3")])
++
++
++(define_insn "*tablejump_symbol"
++  [(parallel [
++     (set (pc)
++        (mem:HI
++           (plus:HI (match_operand:HI 0 "register_operand" "a")
++                    (label_ref (match_operand 1 "" "")))))
++     (use (label_ref (match_dup 1)))
++     (clobber (match_scratch:HI 2 ""))
++     ])]
++  "!flag_pic"
++{
++  output_asm_insn ("jmp\t[%a1,%0]", operands);
++  return "";
++}
++  [(set_attr "length" "4")])
++
++
++(define_insn "*tablejump_symbol_pic"
++  [(parallel [
++     (set (pc)
++        (mem:HI
++           (plus:HI (match_operand:HI 0 "register_operand" "d")
++                    (label_ref (match_operand 1 "" "")))))
++     (use (label_ref (match_dup 1)))
++     (clobber (match_scratch:HI 2 "=&a"))
++     ])]
++  "flag_pic"
++{
++  output_asm_insn ("lea%2\t%a1,pcr", operands);
++  output_asm_insn ("ld%0\t%0,%2", operands);
++  output_asm_insn ("jmp\t%0,%2", operands);
++  return "";
++}
++  [(set_attr "length" "8")])
++
++
++(define_insn "indirect_jump"
++  [(set (pc)
++    (match_operand:HI 0 "register_operand" "a"))]
++  ""
++  "jmp\t,%0"
++  [(set_attr "length" "3")])
++
++
++(define_insn "jump"
++  [(set (pc) (label_ref (match_operand 0 "" "")))]
++  ""
++{
++  return output_branch_insn ( LABEL_REF, operands, get_attr_length (insn));
++}
++  [(set (attr "type") (const_string "branch"))])
++
++; Output assembly for a condition branch instruction.
++(define_insn "*cond_branch"
++  [(set (pc)
++    (if_then_else
++      (match_operator 1 "comparison_operator" [(cc0) (const_int 0)])
++        (label_ref (match_operand 0 "" "")) (pc)))]
++  ""
++{
++  return output_branch_insn ( GET_CODE(operands[1]),
++    operands, get_attr_length (insn));
++}
++  [(set (attr "type") (const_string "cbranch"))])
++
++
++; Similar to above, but for a condition branch instruction that
++; had its operands reversed at some point.
++(define_insn "*cond_branch_reverse"
++  [(set (pc)
++    (if_then_else
++      (match_operator 1 "comparison_operator" [(cc0) (const_int 0)])
++      (pc) (label_ref (match_operand 0 "" ""))))]
++  ""
++{
++  return output_branch_insn ( reverse_condition (GET_CODE(operands[1])),
++    operands, get_attr_length (insn));
++}
++  [(set (attr "type") (const_string "cbranch"))])
++
++
++
++;;--------------------------------------------------------------------
++;;-  Calls
++;;--------------------------------------------------------------------
++
++;; Generate a call instruction for a function that does not
++;; return a value.  The expander is used during RTL generation.
++;; The instructions below are used during matching; only one
++;; of them will be used, depending on the type of function
++;; being called.  The different conditions are:
++;;
++;;    1) far_functionp - is this a far function?  Those need
++;;    to be output as indirect calls through a far-function
++;;    handler.
++;;
++;;    2) noreturn_functionp - if the function does not return,
++;;    we can use a 'jmp' instead of a 'jsr' to call it.
++;;
++;;    3) is PIC mode enabled?  If so, we'll always use
++;;    relative calls (lbsr or lbra).
++;;
++;; Note: not all combinations are fully supported, especially
++;; relating to PIC.
++;;
++;; The 'bsr' instruction is never generated.
++
++(define_expand "call"
++  [(call (match_operand:HI 0 "memory_operand" "")
++    (match_operand:HI 1 "general_operand" ""))]
++  ""
++  "")
++
++(define_insn "*call_nopic_far"
++  [(call (match_operand:HI 0 "memory_operand" "m")
++    (match_operand:HI 1 "general_operand" "g"))]
++  "far_functionp (operands[0])"
++{
++  output_far_call_insn (operands, 0);
++  return "";
++}
++  [(set_attr "length" "6")])
++
++
++; PIC forms come first, and should only match
++; (MEM (SYMBOL_REF)).  Other MEM forms are treated as usual.
++(define_insn "*call_pic"
++  [(call (mem:HI (match_operand:HI 0 "symbolic_operand" ""))
++    (match_operand:HI 1 "general_operand" "g"))]
++  "flag_pic && !noreturn_functionp (operands[0])"
++  "lbsr\t%C0"
++  [(set_attr "length" "4")])
++
++
++(define_insn "*call_nopic"
++  [(call (match_operand:HI 0 "memory_operand" "m")
++    (match_operand:HI 1 "general_operand" "g"))]
++  "!noreturn_functionp (operands[0])"
++  "jsr\t%0"
++  [(set_attr "length" "3")
++   (set (attr "cycles") (const_int JSR_EXTENDED_CYCLES))])
++
++
++(define_insn "*call_noreturn_pic"
++  [(call (mem:HI (match_operand:HI 0 "symbolic_operand" ""))
++    (match_operand:HI 1 "general_operand" "g"))]
++  "flag_pic && noreturn_functionp (operands[0])"
++  "lbra\t%C0"
++  [(set_attr "length" "4")])
++
++
++(define_insn "*call_noreturn_nopic"
++  [(call (match_operand:HI 0 "memory_operand" "m")
++    (match_operand:HI 1 "general_operand" "g"))]
++  "noreturn_functionp (operands[0])"
++  "jmp\t%0"
++  [(set_attr "length" "3")])
++
++
++;;
++;; Same as above, but for functions that do return a value.
++;;
++(define_expand "call_value"
++  [(set (match_operand 0 "" "")
++    (call (match_operand:HI 1 "memory_operand" "")
++    (match_operand:HI 2 "general_operand" "")))]
++  ""
++  "")
++
++
++(define_insn "*call_value_far"
++  [(set (match_operand 0 "" "=gz")
++    (call (match_operand:HI 1 "memory_operand" "m")
++    (match_operand:HI 2 "general_operand" "g")))]
++  "far_functionp (operands[1])"
++{
++  output_far_call_insn (operands, 1);
++  return "";
++}
++  [(set_attr "length" "6")])
++
++
++(define_insn "*call_value_pic"
++  [(set (match_operand 0 "" "=gz")
++    (call (mem:HI (match_operand:HI 1 "symbolic_operand" ""))
++    (match_operand:HI 2 "general_operand" "g")))]
++  "flag_pic"
++  "lbsr\t%C1"
++  [(set_attr "length" "4")])
++
++
++(define_insn "*call_value_nopic"
++  [(set (match_operand 0 "" "=gz")
++    (call (match_operand:HI 1 "memory_operand" "m")
++    (match_operand:HI 2 "general_operand" "g")))]
++  ""
++  "jsr\t%1"
++  [(set_attr "length" "3")
++   (set (attr "cycles") (const_int JSR_EXTENDED_CYCLES))])
++
++
++
++;;
++;; How to generate an untyped call.
++;;
++(define_expand "untyped_call"
++  [(parallel [(call (match_operand 0 "" "")
++        (const_int 0))
++      (match_operand 1 "" "")
++      (match_operand 2 "" "")])]
++  ""
++{
++  int i;
++
++  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
++  for (i=0; i < XVECLEN (operands[2], 0); i++)
++  {
++    rtx set = XVECEXP (operands[2], 0, i);
++    emit_move_insn (SET_DEST (set), SET_SRC (set));
++  }
++  emit_insn (gen_blockage ());
++  DONE;
++})
++
++
++(define_expand "sibcall"
++  [(parallel
++     [(call (match_operand:HI 0 "memory_operand" "")
++            (match_operand:HI 1 "immediate_operand" ""))
++      (use (reg:HI HARD_PC_REGNUM))])]
++  ""
++  "")
++
++(define_insn "*sibcall_1"
++  [(parallel
++     [(call (match_operand:HI 0 "memory_operand" "m")
++            (match_operand:HI 1 "immediate_operand" "i"))
++      (use (reg:HI HARD_PC_REGNUM))])]
++  "SIBLING_CALL_P(insn)"
++  "jmp\t%0"
++  [(set_attr "length" "4")])
++
++
++(define_expand "sibcall_value"
++  [(parallel
++     [(set (match_operand 0 "" "")
++         (call (match_operand:HI 1 "memory_operand" "")
++               (match_operand:HI 2 "immediate_operand" "")))
++      (use (reg:HI HARD_PC_REGNUM))])]
++  ""
++  "")
++
++(define_insn "*sibcall_value_1"
++  [(parallel
++     [(set (match_operand 0 "" "=gz")
++         (call (match_operand:HI 1 "memory_operand" "m")
++               (match_operand:HI 2 "immediate_operand" "i")))
++      (use (reg:HI HARD_PC_REGNUM))])]
++  "SIBLING_CALL_P(insn)"
++  "jmp\t%1"
++  [(set_attr "length" "4")])
++
++
++;;--------------------------------------------------------------------
++;;-  Function Entry and Exit
++;;--------------------------------------------------------------------
++
++;; On entry to a function, the stack frame looks as follows:
++;; - return address (pushed by the caller)
++;; - saved registers
++;; - local variable storage
++;;
++;; If the function does not modify the stack after that, then
++;; any of these can be accessed directly as an offset from
++;; STACK_POINTER_REGNUM.  Otherwise, a frame pointer is required.
++;; In that case, the prologue must also initialize HARD_FRAME_POINTER_REGNUM
++;; and all references to the stack frame will use that as a base instead.
++;;
++(define_expand "prologue"
++  [(const_int 0)]
++  "prologue_epilogue_required ()"
++{
++  emit_prologue_insns ();
++  DONE;
++})
++
++
++;; The function epilogue does exactly the reverse of the prologue,
++;; deallocating local variable space, restoring saved registers,
++;; and returning.
++;;
++;; For the 6809, the return may be 'rti' if the function was
++;; declared as an interrupt function, but is normally 'rts'.
++;;
++;; Also, as an optimization, the register restore and the 'rts'
++;; can be combined into a single instruction, by adding 'PC' to the
++;; list of registers to be restored.  This is only done if there are
++;; any saved registers, as 'rts' is more efficient by itself.
++;;
++(define_expand "epilogue"
++  [(const_int 0)]
++  "prologue_epilogue_required ()"
++{
++  emit_epilogue_insns (false);
++  DONE;
++})
++
++
++(define_expand "sibcall_epilogue"
++  [(const_int 0)]
++  "prologue_epilogue_required ()"
++{
++  emit_epilogue_insns (true);
++  DONE;
++})
++
++
++;; The RTS instruction
++(define_insn "return_rts"
++  [(return)
++   (use (reg:HI HARD_PC_REGNUM))]
++  "!m6809_current_function_has_type_attr_p (\"interrupt\")
++   && m6809_get_live_regs () == 0"
++  "rts"
++  [(set_attr "length" "1")
++   (set (attr "cycles") (const_int RTS_CYCLES))])
++
++(define_insn "return_puls_pc"
++  [(return)
++   (use (reg:HI HARD_PC_REGNUM))]
++  "!m6809_current_function_has_type_attr_p (\"interrupt\")
++   && m6809_get_live_regs () != 0"
++  ""
++  [(set_attr "length" "1")
++   (set (attr "cycles") (const_int RTS_CYCLES))])
++
++;; The RTI instruction
++(define_insn "return_rti"
++  [(return)
++   (use (reg:HI HARD_PC_REGNUM))]
++  "m6809_current_function_has_type_attr_p (\"interrupt\")"
++  "rti"
++  [(set_attr "length" "1")
++   (set (attr "cycles") (const_int RTI_CYCLES))])
++
++
++;;--------------------------------------------------------------------
++;;-  Unspecified instructions
++;;--------------------------------------------------------------------
++
++;; An instruction that has the effect of an unspec_volatile, but
++;; which doesn't require emitting any assembly code.
++(define_insn "blockage"
++  [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
++  ""
++  ""
++  [(set_attr "length" "0")
++   (set (attr "cycles") (const_int 0))])
++
++
++;; Say how to push multiple registers onto the stack, using
++;; the 6809 'pshs' instruction.  The operand is a regset
++;; specifying which registers to push.
++;;
++;; The operand mode is not given intentionally, so as to allow
++;; any possible integer mode for the regset.
++;;
++;; See below for a peephole that can combine consecutive push
++;; instructions that qualify for merging.
++(define_insn "register_push"
++  [(use (reg:HI HARD_S_REGNUM))
++    (unspec_volatile
++      [(match_operand 0 "immediate_operand" "")] UNSPEC_PUSH_RS)
++    (clobber (reg:HI HARD_S_REGNUM))]
++  ""
++  "pshs\t%R0"
++  [(set_attr "length" "2")
++   (set (attr "cycles") (const_int PSH_PUL_CYCLES))])
++
++
++;; Say how to pop multiple registers from the stack, using
++;; the 6809 'puls' instruction.  The operand is the register
++;; bitset value.
++(define_insn "register_pop"
++  [(use (reg:HI HARD_S_REGNUM))
++    (unspec_volatile
++      [(match_operand 0 "immediate_operand" "")] UNSPEC_POP_RS)
++    (clobber (reg:HI HARD_S_REGNUM))]
++  ""
++  "puls\t%R0"
++  [(set_attr "length" "2")
++   (set (attr "cycles") (const_int PSH_PUL_CYCLES))])
++
++
++(define_insn "m6809_swi"
++  [(unspec_volatile
++    [(match_operand:QI 0 "immediate_operand" "I,n")] UNSPEC_SWI)]
++  ""
++  "@
++   swi
++   swi%c0"
++  [(set_attr "length" "1,2")
++   (set (attr "cycles") (const_int SWI_CYCLES))])
++
++
++;; Generate the CWAI instruction
++(define_insn "m6809_cwai"
++  [(unspec_volatile
++    [(match_operand:QI 0 "immediate_operand" "")] UNSPEC_CWAI)]
++  ""
++  "cwai\t%0"
++  [(set_attr "length" "2")
++   (set (attr "cycles") (const_int CWAI_CYCLES))])
++
++
++;; Generate the SYNC instruction
++(define_insn "m6809_sync"
++  [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
++  ""
++  "sync"
++  [(set_attr "length" "1")
++   (set (attr "cycles") (const_int SYNC_CYCLES))])
++
++
++;; Generate the NOP instruction
++(define_insn "nop"
++  [(const_int 0)]
++  ""
++  "nop"
++   [(set_attr "length" "1")
++   (set (attr "cycles") (const_int NOP_CYCLES))])
++
++
++;;--------------------------------------------------------------------
++;;- Peepholes
++;;--------------------------------------------------------------------
++
++;;; Each peephole has an ID that is used for debugging.
++;;; Each peephole condition is bracketed by calls to
++;;; m6809_match_peephole2() also for debugging.
++(define_constants [
++  (PEEP_END 0)
++  (PEEP_COND 1)
++
++  (PEEP_STACK_STORE_INC 0)
++  (PEEP_STACK_CLEAR_INC 1)
++  (PEEP_LSRB_ADCB 2)
++  (PEEP_ABX 3)
++  (PEEP_ABX2 4)
++  (PEEP_INDEXED_INC 5)
++  (PEEP_MEM_DEC 6)
++  (PEEP_MEM_INC 7)
++  (PEEP_MEM_DEC_CMP 8)
++  (PEEP_PUSH2 9)
++  (PEEP_STORE_IMPLIES_CC 10)
++  (PEEP_DEC_IMPLIES_CC 11)
++  (PEEP_LEAB 12)
++  (PEEP_LDX_INDIRECT 13)
++  (PEEP_POP_JUNK 14)
++])
++
++
++;;; Optimize 'leas -1,s' followed by 'stb ,s'.  This can happen if the
++;;; function prologue needs to allocate stack space and 'b' is placed
++;;; into that local right away.  Combine the stack allocation with the
++;;; store using preincrement mode.
++(define_peephole2
++  [(set (reg:HI HARD_S_REGNUM)
++        (plus:HI (reg:HI HARD_S_REGNUM) (const_int -1)))
++   (set (mem:QI (reg:HI HARD_S_REGNUM))
++        (match_operand:QI 0 "register_operand" ""))]
++  "m6809_match_peephole2 (PEEP_STACK_STORE_INC, PEEP_END)"
++  [(set (mem:QI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (match_dup 0))]
++  "")
++
++
++;;; Same as above, but for a 'clr ,s' that follows the prologue.
++(define_peephole2
++  [(set (reg:HI HARD_S_REGNUM) (plus:HI (reg:HI HARD_S_REGNUM) (const_int -1)))
++   (set (mem:QI (reg:HI HARD_S_REGNUM)) (const_int 0))]
++  "m6809_match_peephole2 (PEEP_STACK_CLEAR_INC, PEEP_END)"
++  [(set (mem:QI (pre_dec:HI (reg:HI HARD_S_REGNUM))) (const_int 0))]
++  "")
++
++
++;;; Merge two consecutive push instructions into a single register_push.
++(define_peephole2
++  [(set (match_operand 0 "push_operand" "")
++    (match_operand 1 "register_operand" ""))
++   (set (match_operand 2 "push_operand" "")
++    (match_operand 3 "register_operand" ""))]
++  "m6809_match_peephole2 (PEEP_PUSH2, PEEP_COND)
++   && reload_completed
++   && GET_MODE (operands[1]) == GET_MODE (operands[3])
++   && m6809_can_merge_pushpop_p (UNSPEC_PUSH_RS, 1 << REGNO (operands[1]), 1 << REGNO (operands[3]))
++   && m6809_match_peephole2 (PEEP_PUSH2, PEEP_END)"
++  [(parallel [
++    (use (reg:HI HARD_S_REGNUM))
++    (unspec_volatile [(match_dup 4)] UNSPEC_PUSH_RS)
++    (clobber (reg:HI HARD_S_REGNUM))])
++   (use (match_dup 1))
++   (use (match_dup 3))]
++{
++  operands[4] = gen_rtx_CONST_INT (QImode,
++    (1 << REGNO (operands[1])) | (1 << REGNO (operands[3])));
++})
++
++
++;;; Convert 'stX ,--s' into a push instruction.  Use the regset
++;;; notation, so that it may be combined with an adjacent regset.
++;;; TBD - this doesn't compile some code cleanly.
++;(define_peephole2
++;  [(set (mem:HI (pre_dec:HI (reg:HI HARD_S_REGNUM)))
++;        (reg:HI HARD_X_REGNUM))]
++;  "reload_completed"
++;  [(parallel [
++;    (use (reg:HI HARD_S_REGNUM))
++;    (unspec_volatile [(match_dup 0)] UNSPEC_PUSH_RS)
++;    (clobber (reg:HI HARD_S_REGNUM))])]
++;{
++;  operands[0] = gen_rtx_CONST_INT (HImode, X_REGBIT);
++;})
++
++
++;;;
++;;; q = (q+1)/2 can be optimized as "lsrb; adcb".  This also
++;;; won't overflow when q=0xFF.
++;;; TODO : this form isn't accounting for promotion when
++;;; using 16-bit ints.
++;;;
++(define_peephole
++  [(set (reg:QI HARD_D_REGNUM)
++    (lshiftrt:QI (plus:HI (match_dup 0) (const_int 1)) (const_int 1)))]
++  "m6809_match_peephole2 (PEEP_LSRB_ADCB, PEEP_END)"
++  "lsrb\;adcb\t#0; peephole"
++  [(set_attr "length" "2")])
++
++
++;;
++;; Optimize the case of following a register store with a test
++;; of reg or mem just moved.
++;;
++(define_peephole
++  [(set (match_operand:HI 0 "memory_operand" "=m")
++  (match_operand:HI 1 "register_operand" "r"))
++   (set (cc0) (match_operand:HI 2 "general_operand" "g"))]
++  "m6809_match_peephole2 (PEEP_STORE_IMPLIES_CC, PEEP_COND)
++   && (operands[2] == operands[0] || operands[2] == operands[1])
++   && m6809_match_peephole2 (PEEP_STORE_IMPLIES_CC, PEEP_END)"
++  "st%1\t%0\t;movhi: R:%1 -> %0 w/ implied test of %2"
++  [(set_attr "length" "4")])
++
++
++;; Optimize a pair of SET instructions in which the second insn
++;; is the reverse of the first one.  I.e.
++;;
++;; A = B
++;;        ---->  A = B
++;; B = A
++;;
++;; The second insn is redundant.  Define two patterns, one for QI, one for HI.
++;; But don't do this if either is a VOLATILE MEM.
++(define_peephole2
++  [(set (match_operand:HI 0 "nonimmediate_operand" "")
++        (match_operand:HI 1 "nonimmediate_operand" ""))
++  (set (match_dup 1) (match_dup 0))]
++  "!MEM_P (operands[0]) || !MEM_P (operands[1]) || (!MEM_VOLATILE_P (operands[0]) && !MEM_VOLATILE_P (operands[1]))"
++  [(set (match_dup 0) (match_dup 1))]
++  "")
++
++(define_peephole2
++  [(set (match_operand:QI 0 "nonimmediate_operand" "")
++        (match_operand:QI 1 "nonimmediate_operand" ""))
++  (set (match_dup 1) (match_dup 0))]
++  "!MEM_P (operands[0]) || !MEM_P (operands[1]) || (!MEM_VOLATILE_P (operands[0]) && !MEM_VOLATILE_P (operands[1]))"
++  [(set (match_dup 0) (match_dup 1))]
++  "")
++
++
++;;
++;; Optimize the sum of an 8-bit and 16-bit using the 'abx' instruction
++;; if B and X can be used.  Two patterns are provided to catch both
++;; X=X+D and X=D+X.
++;;
++(define_peephole
++  [(set (reg:HI HARD_D_REGNUM)
++    (zero_extend:HI (match_operand:QI 0 "general_operand" "q")))
++   (set (reg:HI HARD_X_REGNUM)
++    (plus:HI (reg:HI HARD_D_REGNUM) (reg:HI HARD_X_REGNUM)))]
++  "m6809_match_peephole2 (PEEP_ABX, PEEP_END)"
++  "abx"
++  [(set_attr "length" "1")])
++
++(define_peephole
++  [(set (reg:HI HARD_D_REGNUM)
++    (zero_extend:HI (match_operand:QI 0 "general_operand" "q")))
++   (set (reg:HI HARD_X_REGNUM)
++    (plus:HI (reg:HI HARD_X_REGNUM) (reg:HI HARD_D_REGNUM)))]
++  "m6809_match_peephole2 (PEEP_ABX, PEEP_END)"
++  "abx"
++  [(set_attr "length" "1")])
++
++;;; Likewise, handle when B is scaled by 2 prior to the add.
++;;; Instead of shifting B in 4 cycles, just do the ABX a second
++;;; time, in only 3 cycles.
++
++(define_peephole
++  [(set (reg:HI HARD_D_REGNUM)
++    (zero_extend:HI (match_operand:QI 0 "general_operand" "q")))
++   (set (reg:HI HARD_D_REGNUM)
++    (ashift:HI (reg:HI HARD_D_REGNUM) (const_int 1)))
++   (set (reg:HI HARD_X_REGNUM)
++    (plus:HI (reg:HI HARD_D_REGNUM) (reg:HI HARD_X_REGNUM)))]
++  "m6809_match_peephole2 (PEEP_ABX2, PEEP_END)"
++  "abx\;abx"
++  [(set_attr "length" "2")])
++
++(define_peephole
++  [(set (reg:HI HARD_D_REGNUM)
++    (zero_extend:HI (match_operand:QI 0 "general_operand" "q")))
++   (set (reg:HI HARD_D_REGNUM)
++    (ashift:HI (reg:HI HARD_D_REGNUM) (const_int 1)))
++   (set (reg:HI HARD_X_REGNUM)
++    (plus:HI (reg:HI HARD_X_REGNUM) (reg:HI HARD_D_REGNUM)))]
++  "m6809_match_peephole2 (PEEP_ABX2, PEEP_END)"
++  "abx\;abx"
++  [(set_attr "length" "2")])
++
++
++;;
++;; Work around a compiler bug that generates bad code when copying
++;; between 32-bit memory addresses after a libcall.  The problem seen is
++;; that the source is MEM (REG X), but X is used as the reload register.
++;; The second half of the copy therefore fails.
++;;
++;; The solution is to switch the reload register to D, since that is guaranteed
++;; not to be in use right after a libcall.
++;;
++(define_peephole2
++  [(set (reg:HI HARD_X_REGNUM) (mem:HI (reg:HI HARD_X_REGNUM)))
++   (set (match_operand:HI 0 "nonimmediate_operand" "") (reg:HI HARD_X_REGNUM))
++   (set (reg:HI HARD_X_REGNUM)
++      (mem:HI (plus:HI (reg:HI HARD_X_REGNUM) (const_int 2))))
++   (set (match_operand:HI 1 "nonimmediate_operand" "") (reg:HI HARD_X_REGNUM))]
++  "reload_completed"
++  [(set (reg:HI HARD_D_REGNUM) (mem:HI (reg:HI HARD_X_REGNUM)))
++   (set (match_dup 0) (reg:HI HARD_D_REGNUM))
++   (set (reg:HI HARD_X_REGNUM)
++      (mem:HI (plus:HI (reg:HI HARD_X_REGNUM) (const_int 2))))
++   (set (match_dup 1) (reg:HI HARD_X_REGNUM))]
++  "")
++
++
++;; Turn "and then test" into a "bit test" operation.
++;; Provide variants for immediate and memory sources
++;; This is the most used peephople.
++; (define_peephole
++;   [(set (match_operand:QI 0 "register_operand" "=q")
++;     (and:QI (match_operand:QI 1 "register_operand" "0")
++;       (match_operand:QI 2 "immediate_operand" "i")))
++;    (set (cc0) (match_dup 0))]
++;   ""
++;   "bit%0\t%2"
++;   [(set_attr "length" "3")])
++; 
++; (define_peephole
++;   [(set (match_operand:QI 0 "register_operand" "=q")
++;     (and:QI (match_operand:QI 1 "register_operand" "0")
++;       (match_operand:QI 2 "memory_operand" "m")))
++;    (set (cc0) (match_dup 0))]
++;   ""
++;   "bit%0\t%2"
++;   [(set_attr "length" "4")])
++
++
++;; Turn a "decrement, then test" sequence into just a "decrement".
++;; The test can be omitted, since it is implicitly done.
++(define_peephole2
++  [(set (match_operand:QI 0 "nonimmediate_operand" "")
++    (plus:QI (match_operand:QI 1 "whole_general_operand" "")
++    (match_operand:QI 2 "immediate_operand" "")))
++   (set (cc0) (match_dup 0))]
++  "m6809_match_peephole2 (PEEP_DEC_IMPLIES_CC, PEEP_END)"
++  [(set (match_dup 0) (plus:QI (match_dup 1) (match_dup 2)))]
++  "")
++
++
++;; Merge an indexed register increment with a previous usage.
++;; This is usually done automatically, but not always
++;; The 'use' should be optional; in all cases where this has been
++;; seen, it is required though.
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++     (mem:QI (match_operand:HI 1 "index_register_operand" "")))
++   (use (match_dup 0))
++   (set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))]
++  "m6809_match_peephole2 (PEEP_INDEXED_INC, PEEP_END)"
++  [(set (match_dup 0) (mem:QI (post_inc:HI (match_dup 1))))
++   (use (match_dup 0))]
++  "")
++
++
++;;; Merge "ldX MEM; ldX ,X" into a single instruction using
++;;; the indirect mode.
++(define_peephole2
++  [(set (reg:HI HARD_X_REGNUM)
++    (mem:HI (match_operand:HI 0 "general_operand" "")))
++   (set (reg:HI HARD_X_REGNUM) (mem:HI (reg:HI HARD_X_REGNUM)))]
++  "reload_completed && m6809_match_peephole2 (PEEP_LDX_INDIRECT, PEEP_END)"
++  [(set (reg:HI HARD_X_REGNUM)
++    (mem:HI (mem:HI (match_dup 0))))]
++  "")
++
++
++;;; Reorder a store followed by a unary operation on that memory
++;;; so that the unary is performed and then the store.  Consider
++;;; a binary shift operation, which will be decomposed into
++;;; identical single shifts, also.
++;;; TODO - recognize more than just 'ashift' here.
++(define_peephole2
++  [(set (match_operand:QI 0 "memory_operand" "")
++        (match_operand:QI 1 "register_operand" ""))
++   (set (match_dup 0)
++        (ashift:QI (match_dup 0) (match_operand:QI 2 "immediate_operand")))]
++  "reload_completed"
++  [(set (match_dup 1)
++        (ashift:QI (match_dup 1) (match_operand:QI 2 "immediate_operand")))
++   (set (match_dup 0) (match_dup 1))]
++  "")
++
++;;; Likewise, reorder a unary MEM followed by a load, so that the load
++;;; is done first, then use the REG instead of the MEM.
++;;;(define_peephole2
++;;;  [(set (match_dup 0)
++;;;        (ashift:QI (match_dup 0) (match_operand:QI 2 "immediate_operand")))
++;;;   (set (match_operand:QI 0 "register_operand" "")
++;;;        (match_operand:QI 1 "memory_operand" ""))]
++;;;  "reload_completed"
++;;;  [(set (match_dup 0) (match_dup 1))
++;;;   (set (match_dup 0)
++;;;        (ashift:QI (match_dup 0) (match_operand:QI 2 "immediate_operand")))]
++;;;  "")
++
++
++;;; Replace sex; leaX d,Y with leaX b,Y.
++;;;
++(define_peephole2
++  [(set (reg:HI HARD_D_REGNUM) (sign_extend:HI (reg:QI HARD_D_REGNUM)))
++   (set (match_operand:HI 0 "index_register_operand" "")
++        (plus:HI (match_operand:HI 1 "index_register_operand" "")
++                 (reg:HI HARD_D_REGNUM)))]
++  "reload_completed && m6809_match_peephole2 (PEEP_LEAB, PEEP_END)"
++  [(set (match_dup 0)
++        (plus:HI (match_dup 1) (reg:QI HARD_D_REGNUM)))]
++  "")
++
++(define_peephole2
++  [(set (reg:HI HARD_D_REGNUM) (sign_extend:HI (reg:QI HARD_D_REGNUM)))
++   (set (match_operand:HI 0 "index_register_operand" "")
++        (plus:HI (reg:HI HARD_D_REGNUM)
++          (match_operand:HI 1 "index_register_operand" "")))]
++  "reload_completed && m6809_match_peephole2 (PEEP_LEAB, PEEP_END)"
++  [(set (match_dup 0)
++        (plus:HI (match_dup 1) (reg:QI HARD_D_REGNUM)))]
++  "")
++
++
++;;; Replace ldb; decb; stb; tstb with dec(mem).  If the
++;;; register is not needed, then the load will get deleted
++;;; automatically, but it may be needed for comparisons.
++;;; Same for incb/inc.
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++        (match_operand:QI 1 "nonimmediate_operand" ""))
++   (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1)))
++   (set (match_dup 1) (match_dup 0))
++   (set (cc0) (match_dup 0))]
++  "m6809_match_peephole2 (PEEP_MEM_DEC_CMP, PEEP_END)"
++  [(set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))]
++  "")
++
++
++;;; Replace ldb; decb; stb with dec(mem); ldb.  If the
++;;; register is not needed, then the load will get deleted
++;;; automatically, but it may be needed for comparisons.
++;;; Same for incb/inc.
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++        (match_operand:QI 1 "nonimmediate_operand" ""))
++   (set (match_dup 0) (plus:QI (match_dup 0) (const_int -1)))
++   (set (match_dup 1) (match_dup 0))]
++  "m6809_match_peephole2 (PEEP_MEM_DEC, PEEP_END)"
++  [(set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))
++   (set (match_dup 0) (match_dup 1))]
++  "")
++
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++        (match_operand:QI 1 "nonimmediate_operand" ""))
++   (set (match_dup 0) (plus:QI (match_dup 0) (const_int 1)))
++   (set (match_dup 1) (match_dup 0))]
++  "m6809_match_peephole2 (PEEP_MEM_INC, PEEP_END)"
++  [(set (match_dup 1) (plus:QI (match_dup 1) (const_int 1)))
++   (set (match_dup 0) (match_dup 1))]
++  "")
++
++
++;;; Replace "andb #N; cmpb #N; bhi" with "andb #N", if it can be proven
++;;; that the branch can never occur because of the limited range of B.
++;;; N must be a power of two for this to make sense.  This helps with
++;;; the default cases of switch statements on a value (x & N).
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++    (and:QI (match_dup 0) (match_operand:QI 1 "immediate_operand" "")))
++   (set (cc0)
++    (compare (match_dup 0) (match_dup 1)))
++   (set (pc) (if_then_else (gtu (cc0) (const_int 0)) (match_operand 2 "" "") (match_operand 3 "" "")))
++   ]
++  "reload_completed && power_of_two_p (INTVAL (operands[1]) + 1)"
++  [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
++  "")
++
++;;; Replace ldd <mem>; addd #1; std <mem> with 16-bit increment
++;;; of the mem, but only if D is dead.  Same for 16-bit decrement.
++;;; <mem> must be offsettable for the instruction to match.
++(define_peephole2
++  [(set (match_operand:HI 0 "register_operand" "") (match_operand:HI 1 "memory_operand" ""))
++   (set (match_dup 0) (plus:HI (match_dup 0) (const_int 1)))
++   (set (match_dup 1) (match_dup 0))]
++   "reload_completed
++    && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
++    && peep2_reg_dead_p (3, operands[0])"
++  [(set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))]
++  "")
++
++(define_peephole2
++  [(set (match_operand:HI 0 "register_operand" "") (match_operand:HI 1 "memory_operand" ""))
++   (set (match_dup 0) (plus:HI (match_dup 0) (const_int -1)))
++   (set (match_dup 1) (match_dup 0))]
++   "reload_completed
++    && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
++    && peep2_reg_dead_p (3, operands[0])"
++  [(set (match_dup 1) (plus:HI (match_dup 1) (const_int -1)))]
++  "")
++
++
++;;; Replace a load or store using an indexed register, followed by an increment of that
++;;; register, with the combined form using autoincrement.
++(define_peephole2
++  [(set (match_operand:QI 0 "register_operand" "")
++        (mem:QI (match_operand:HI 1 "index_register_operand" "")))
++   (set (match_dup 1) (plus:HI (match_dup 1) (const_int 1)))]
++   "reload_completed"
++  [(set (match_dup 0) (mem:QI (post_inc (match_dup 1))))]
++  "")
++
++
++;;- mode:emacs-lisp
++;;- comment-start: ";;- "
++;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
++;;- eval: (modify-syntax-entry ?[ "(]")
++;;- eval: (modify-syntax-entry ?] ")[")
++;;- eval: (modify-syntax-entry ?{ "(}")
++;;- eval: (modify-syntax-entry ?} "){")
++;-; vim: set ts=2:
++;-; vim: set expandtab:
++;-; vim: set filetype=lisp:
++;;- End:
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809.opt gcc-4.6.1/gcc/config/m6809/m6809.opt
+--- gcc-4.6.1-orig/gcc/config/m6809/m6809.opt	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/m6809.opt	2011-09-17 14:06:01.227643616 -0600
+@@ -0,0 +1,98 @@
++; Options for the M6809 port of the compiler
++;
++; Copyright (C) 2005 Free Software Foundation, Inc.
++;
++; This file is part of GCC.
++;
++; GCC is free software; you can redistribute it and/or modify it under
++; the terms of the GNU General Public License as published by the Free
++; Software Foundation; either version 2, or (at your option) any later
++; version.
++;
++; GCC is distributed in the hope that it will be useful, but WITHOUT
++; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++; License for more details.
++;
++; You should have received a copy of the GNU General Public License
++; along with GCC; see the file COPYING.  If not, write to the Free
++; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
++; 02110-1301, USA.
++
++margcount
++Target Mask(ARGCOUNT)
++Push argument count
++
++mint8
++Target RejectNegative Mask(BYTE_INT)
++Use 8-bit integers
++
++mint16
++Target RejectNegative
++Use 16-bit integers InverseMask(BYTE_INT)
++
++mreg-args
++Target Mask(REG_ARGS)
++Use registers for function arguments
++
++mshort_size 
++Target RejectNegative Mask(SMALL_SIZE_T)
++Use 8-bit size_t
++
++mlong_size
++Target RejectNegative InverseMask(SMALL_SIZE_T)
++Use 16-bit size_t
++
++mdirect
++Target Mask(DIRECT)
++Enable direct addressing
++
++mwpc
++Target RejectNegative Mask(WPC)
++Enable WPC platform extensions
++
++mexperiment
++Target RejectNegative Mask(EXPERIMENT)
++Enable current experimental feature
++
++m6309
++Target RejectNegative Mask(6309)
++Enable Hitachi 6309 extensions
++
++mcasesi
++Target RejectNegative Mask(CASESI)
++Enable the casesi pattern
++
++mfar-code-page=
++Target RejectNegative Joined Var(far_code_page_option)
++Sets the far code page value for this compilation unit
++
++mcode-section=
++Target RejectNegative Joined Var(code_section_ptr)
++Sets the name of the section for code
++
++mdata-section=
++Target RejectNegative Joined Var(data_section_ptr)
++Sets the name of the section for initialized data
++
++mbss-section=
++Target RejectNegative Joined Var(bss_section_ptr)
++Sets the name of the section for uninitialized data
++
++mabi_version=
++Target RejectNegative Joined Var(m6809_abi_version_ptr)
++Sets the calling convention
++
++msoft-reg-count=
++Target RejectNegative Joined Var(m6809_soft_reg_count)
++Sets the number of soft registers that can be used
++
++mdret
++Target RejectNegative Mask(DRET)
++Put function call results in D, not X
++
++mfar-stack-param
++Target Mask(FAR_STACK_PARAM)
++Enable stack parameters to a farcall
++
++
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/m6809-protos.h gcc-4.6.1/gcc/config/m6809/m6809-protos.h
+--- gcc-4.6.1-orig/gcc/config/m6809/m6809-protos.h	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/m6809-protos.h	2011-09-17 17:26:19.227644879 -0600
+@@ -0,0 +1,94 @@
++/* GCC for 6809 : machine-specific function prototypes
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++#ifndef __M6809_PROTOS_H__
++#define __M6809_PROTOS_H__
++
++void 					print_options (FILE *file);
++void 					m6809_cpu_cpp_builtins (void);
++void 					m6809_override_options (void);
++void 					m6809_init_builtins (void);
++unsigned int 		m6809_get_live_regs (void);
++const char * 		m6809_get_regs_printable (unsigned int regs);
++unsigned int 		m6809_get_regs_size (unsigned int regs);
++int 					m6809_function_has_type_attr_p (tree decl, const char *);
++int 					m6809_current_function_has_type_attr_p (const char *);
++int 					prologue_epilogue_required (void);
++int 					noreturn_functionp (rtx x);
++void 					output_function_prologue (FILE *file, int size);
++void 					output_function_epilogue (FILE *file, int size);
++int 					check_float_value (enum machine_mode mode, double *d, int overflow);
++void 					m6809_asm_named_section (const char *name, unsigned int flags, tree decl);
++void 					m6809_asm_file_start (void);
++void              m6809_output_ascii (FILE *fp, const char *str, unsigned long size);
++void              m6809_declare_function_name (FILE *asm_out_file, const char *name, tree decl);
++void              m6809_reorg (void);
++int               m6809_current_function_is_void (void);
++int               m6809_can_merge_pushpop_p (int op, int regs1, int regs2);
++int               m6809_function_value_regno_p (unsigned int regno);
++void              emit_prologue_insns (void);
++void              emit_epilogue_insns (bool);
++void              m6809_conditional_register_usage (void);
++void              m6809_output_quoted_string (FILE *asm_file, const char *string);
++int               m6809_match_peephole2 (unsigned int peephole_id, unsigned int stage);
++int               m6809_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode);
++int               power_of_two_p (unsigned int n);
++void              m6809_do_casesi (rtx index, rtx lower_bound, rtx range, rtx table_label, rtx default_label);
++void              m6809_output_addsi3 (int rtx_code, rtx *operands);
++rtx               m6809_function_arg_on_stack (CUMULATIVE_ARGS *cump);
++void              expand_constant_shift (int code, rtx dst, rtx src, rtx count);
++int               m6809_single_operand_operator (rtx exp);
++
++#ifdef TREE_CODE
++int m6809_init_cumulative_args (CUMULATIVE_ARGS cum, tree fntype, rtx libname);
++#endif /* TREE_CODE */
++
++#ifdef RTX_CODE
++void 					print_direct_prefix (FILE *file, rtx addr);
++void 					print_operand (FILE *file, rtx x, int code);
++void 					print_operand_address (FILE *file, rtx addr);
++void 					notice_update_cc (rtx exp, rtx insn);
++enum 					reg_class m6809_preferred_reload_class (rtx x, enum reg_class regclass);
++rtx 					gen_rtx_const_high (rtx r);
++rtx 					gen_rtx_const_low (rtx r);
++rtx 					gen_rtx_register_pushpop (int pop_flag, int regs);
++void 					emit_libcall_insns (enum machine_mode mode, const char *name, rtx *operands, int count);
++const char *		output_branch_insn (enum rtx_code code, rtx *operands, int length);
++void 					output_far_call_insn (rtx *operands, int has_return);
++void 					m6809_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt);
++rtx 					m6809_expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, int ignore);
++const char *      far_functionp (rtx x);
++rtx               m6809_function_value (const tree valtype, const tree func);
++void              m6809_output_shift_insn (int rtx_code, rtx *operands);
++
++const char * m6809_get_decl_bank (tree decl);
++void output_branch_insn1 (const char *opcode, rtx *operands, int long_p);
++rtx m6809_builtin_operand (tree arglist, enum machine_mode mode, int opnum);
++const char * far_function_type_p (tree type);
++void m6809_asm_trampoline_template(FILE *f);
++bool m6809_frame_pointer_required (void);
++int m6809_can_eliminate (int from, int to);
++int m6809_initial_elimination_offset (int from, int to);
++void m6809_emit_move_insn (rtx dst, rtx src);
++void m6809_split_shift (enum rtx_code code, rtx *operands);
++bool m6809_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED);
++
++
++#endif /* RTX_CODE */
++
++#endif /* __M6809_PROTOS_H__ */
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/predicates.md gcc-4.6.1/gcc/config/m6809/predicates.md
+--- gcc-4.6.1-orig/gcc/config/m6809/predicates.md	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/predicates.md	2011-09-18 15:09:37.057653095 -0600
+@@ -0,0 +1,78 @@
++;; Predicate definitions for Motorola 6809
++;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
++;;
++;; This file is part of GCC.
++;;
++;; GCC is free software; you can redistribute it and/or modify
++;; it under the terms of the GNU General Public License as published by
++;; the Free Software Foundation; either version 3, or (at your option)
++;; any later version.
++;;
++;; GCC is distributed in the hope that it will be useful,
++;; but WITHOUT ANY WARRANTY; without even the implied warranty of
++;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++;; GNU General Public License for more details.
++;;
++;; You should have received a copy of the GNU General Public License
++;; along with GCC; see the file COPYING3.  If not see
++;; <http://www.gnu.org/licenses/>.
++
++;; whole_register_operand is like register_operand, but it
++;; does not allow SUBREGs.
++(define_predicate "whole_register_operand"
++  (and (match_code "reg")
++       (match_operand 0 "register_operand")))
++
++
++;; A predicate that matches any index register.  This can be used in nameless
++;; patterns and peepholes which need a 16-bit reg, but not D.
++(define_predicate "index_register_operand"
++  (and (match_code "reg")
++       (match_test "REGNO (op) == HARD_X_REGNUM || REGNO (op) == HARD_Y_REGNUM || REGNO (op) == HARD_U_REGNUM")))
++
++
++;; match only X
++(define_predicate "register_operand_x"
++  (and (match_code "reg")
++       (match_test "REGNO (op) == HARD_X_REGNUM")))
++
++;; match only D
++(define_predicate "register_operand_d"
++  (and (match_code "reg")
++       (match_test "REGNO (op) == HARD_D_REGNUM")))
++
++
++;; Likwise, a replacement for general_operand which excludes
++;; SUBREGs.
++(define_predicate "whole_general_operand"
++  (and (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem")
++       (match_operand 0 "general_operand")))
++
++
++(define_predicate "add_general_operand"
++  (and (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem")
++       (match_operand 0 "general_operand")
++		 (match_test "REGNO (op) != SOFT_AP_REGNUM")))
++
++
++(define_predicate "shift_count_operand"
++  (and (match_code "const_int")
++     (and (match_operand 0 "const_int_operand")
++       (match_test "INTVAL (op) == 1 || INTVAL (op) == 8"))))
++
++
++;; A predicate that matches any bitwise logical operator.  This
++;; allows for a single RTL pattern to be used for multiple operations.
++(define_predicate "logical_bit_operator"
++	(ior (match_code "and") (match_code "ior") (match_code "xor")))
++
++
++;; A predicate that matches any shift or rotate operator.  This
++;; allows for a single RTL pattern to be used for multiple operations.
++(define_predicate "shift_rotate_operator"
++	(ior (match_code "ashift") (match_code "ashiftrt") (match_code "lshiftrt")
++	     (match_code "rotate") (match_code "rotatert")))
++
++
++(define_predicate "symbolic_operand" (match_code "symbol_ref"))
++
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/t-coco gcc-4.6.1/gcc/config/m6809/t-coco
+--- gcc-4.6.1-orig/gcc/config/m6809/t-coco	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/t-coco	2011-09-17 14:06:01.227643616 -0600
+@@ -0,0 +1,6 @@
++# For a few minor differences in code generation on the CoCo...
++T_CFLAGS = -DTARGET_COCO
++
++# For doing the startup differently on the CoCo...
++CRT0STUFF_T_CFLAGS += -Wa,--globalize-symbols -DTARGET_COCO
++# vim: set filetype=make:
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/t-m6809 gcc-4.6.1/gcc/config/m6809/t-m6809
+--- gcc-4.6.1-orig/gcc/config/m6809/t-m6809	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/t-m6809	2011-09-17 21:38:35.437646470 -0600
+@@ -0,0 +1,64 @@
++
++# ranlib doesn't exist, so define it to 'true' to make it a no-op
++RANLIB_FOR_TARGET = true
++
++# Stubs for libgcc defined by m6809 are here
++LIB1ASMSRC = m6809/libgcc1.s
++
++# Here are the functions that are implemented within libgcc1.s
++LIB1ASMFUNCS = _mulhi3 _divhi3 _modhi3 _udivhi3 _umodhi3 \
++	_euclid _seuclid _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _softregs \
++	_ashlhi3 _ashrhi3 _lshrhi3
++
++# Flags to use when building libgcc.  IN_GCC does not seem necessary,
++# although the compile breaks without it.  -DDF=SF is required to set
++# the size of "double" to the same as the size of a "float".
++TARGET_LIBGCC2_CFLAGS =-DIN_GCC -Dinhibit_libc -DDF=SF -DLIBGCC2_HAS_SF_MODE=0 -DLIBGCC2_HAS_DF_MODE=0
++
++LIB2ADDEH =
++LIB2ADDEHSTATIC =
++LIB2ADDEHSHARED =
++
++LIBGCC2_DEBUG_CFLAGS =
++LIBGCC2_CFLAGS = -Os $(LIBGCC2_INCLUDES) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2
++
++# Multilib information
++# This creates multiple versions of libgcc.a for each set of incompatible
++# -mxxx options.
++MULTILIB_OPTIONS  = fpic mdret
++MULTILIB_DIRNAMES =
++MULTILIB_MATCHES  =
++MULTILIB_EXCEPTIONS =
++EXTRA_MULTILIB_PARTS = crt0.o
++
++LIBGCC = stmp-multilib
++INSTALL_LIBGCC = install-multilib
++
++# We want fine grained libraries, so use the new code to build the
++# floating point emulation libraries.
++FPBIT = fp-bit.c
++
++fp-bit.c: $(srcdir)/config/fp-bit.c
++	echo '#define FLOAT' > fp-bit.c
++	echo '#define FLOAT_ONLY' >> fp-bit.c
++	echo '#define CMPtype HItype' >> fp-bit.c
++	echo '#define SMALL_MACHINE' >> fp-bit.c
++	echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c
++	echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c
++	echo '#endif' 		>> fp-bit.c
++	echo '#define DI SI'	>> fp-bit.c
++	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
++
++# crt0.o is built from the following source file
++CRT0_S = $(srcdir)/config/m6809/crt0.S
++MCRT0_S = $(srcdir)/config/m6809/crt0.S
++
++# Flags to use when building crt0.o
++CRT0STUFF_T_CFLAGS += -fno-builtin -nostartfiles -nostdlib
++
++# Assemble startup files.
++$(T)crt0.o: $(CRT0_S) $(GCC_PASSES)
++	$(GCC_FOR_TARGET) $(CRT0STUFF_T_CFLAGS) $(MULTILIB_CFLAGS) -c -o $(T)crt0.o -x assembler-with-cpp $(CRT0_S)
++
++$(T)mcrt0.o: $(MCRT0_S) $(GCC_PASSES)
++	$(GCC_FOR_TARGET) $(CRT0STUFF_T_CFLAGS) $(MULTILIB_CFLAGS) -c -o $(T)mcrt0.o -x assembler-with-cpp $(MCRT0_S)
+diff -urN gcc-4.6.1-orig/gcc/config/m6809/t-sim gcc-4.6.1/gcc/config/m6809/t-sim
+--- gcc-4.6.1-orig/gcc/config/m6809/t-sim	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/gcc/config/m6809/t-sim	2011-09-17 14:06:01.227643616 -0600
+@@ -0,0 +1 @@
++CRT0STUFF_T_CFLAGS += -DTARGET_SIM
+diff -urN gcc-4.6.1-orig/gcc/config.gcc gcc-4.6.1/gcc/config.gcc
+--- gcc-4.6.1-orig/gcc/config.gcc	2011-05-22 14:03:43.000000000 -0600
++++ gcc-4.6.1/gcc/config.gcc	2011-09-17 14:08:56.257643636 -0600
+@@ -374,6 +374,9 @@
+         cpu_type=m32r
+ 	extra_options="${extra_options} g.opt"
+         ;;
++m6809-*-*)
++        cpu_type=m6809
++        ;;
+ m68k-*-*)
+ 	extra_headers=math-68881.h
+ 	;;
+@@ -1689,6 +1692,12 @@
+ 		thread_file='posix'
+ 	fi
+ 	;;
++m6809-coco-*)
++	tmake_file="${tmake_file} m6809/t-m6809 m6809/t-coco"
++	;;
++m6809-*-*)
++	tmake_file="${tmake_file} m6809/t-m6809 m6809/t-sim"
++	;;
+ # m68hc11 and m68hc12 share the same machine description.
+ m68hc11-*-*|m6811-*-*)
+ 	tm_file="dbxelf.h elfos.h usegas.h newlib-stdint.h m68hc11/m68hc11.h"
+diff -urN gcc-4.6.1-orig/gcc/gcse.c gcc-4.6.1/gcc/gcse.c
+--- gcc-4.6.1-orig/gcc/gcse.c	2011-02-02 23:04:04.000000000 -0700
++++ gcc-4.6.1/gcc/gcse.c	2011-09-18 17:25:17.527653952 -0600
+@@ -833,7 +833,6 @@
+ 	      max_distance = (GCSE_COST_DISTANCE_RATIO * cost) / 10;
+ 	      if (max_distance == 0)
+ 		return 0;
+-
+ 	      gcc_assert (max_distance > 0);
+ 	    }
+ 	  else
+diff -urN gcc-4.6.1-orig/gcc/libgcc2.c gcc-4.6.1/gcc/libgcc2.c
+--- gcc-4.6.1-orig/gcc/libgcc2.c	2011-01-03 13:52:22.000000000 -0700
++++ gcc-4.6.1/gcc/libgcc2.c	2011-09-17 14:06:01.227643616 -0600
+@@ -485,6 +485,7 @@
+ #endif
+ 
+ #ifdef L_bswapsi2
++#if MIN_UNITS_PER_WORD > 1
+ SItype
+ __bswapsi2 (SItype u)
+ {
+@@ -494,7 +495,9 @@
+ 	  | (((u) & 0x000000ff) << 24));
+ }
+ #endif
++#endif
+ #ifdef L_bswapdi2
++#if LONG_LONG_TYPE_SIZE > 32
+ DItype
+ __bswapdi2 (DItype u)
+ {
+@@ -508,6 +511,7 @@
+ 	  | (((u) & 0x00000000000000ffull) << 56));
+ }
+ #endif
++#endif
+ #ifdef L_ffssi2
+ #undef int
+ int
+@@ -1280,7 +1284,7 @@
+ UDWtype
+ __fixunssfDI (SFtype a)
+ {
+-#if LIBGCC2_HAS_DF_MODE
++#if LIBGCC2_HAS_DF_MODE || (FLT_MANT_DIG >= W_TYPE_SIZE)
+   /* Convert the SFtype to a DFtype, because that is surely not going
+      to lose any bits.  Some day someone else can write a faster version
+      that avoids converting to DFtype, and verify it really works right.  */
+@@ -1298,7 +1302,7 @@
+ 
+   /* Assemble result from the two parts.  */
+   return ((UDWtype) hi << W_TYPE_SIZE) | lo;
+-#elif FLT_MANT_DIG < W_TYPE_SIZE
++#else
+   if (a < 1)
+     return 0;
+   if (a < Wtype_MAXp1_F)
+@@ -1334,8 +1338,6 @@
+       return (DWtype)counter << shift;
+     }
+   return -1;
+-#else
+-# error
+ #endif
+ }
+ #endif
+diff -urN gcc-4.6.1-orig/gcc/longlong.h gcc-4.6.1/gcc/longlong.h
+--- gcc-4.6.1-orig/gcc/longlong.h	2011-06-06 08:34:54.000000000 -0600
++++ gcc-4.6.1/gcc/longlong.h	2011-09-17 14:06:01.227643616 -0600
+@@ -527,6 +527,11 @@
+ 	   : "cbit")
+ #endif /* __M32R__ */
+ 
++#if defined (__m6309__) || defined (__m6809__)
++#define count_leading_zeros(COUNT,X)	((COUNT) = __builtin_clz (X))
++#define count_trailing_zeros(COUNT,X)	((COUNT) = __builtin_ctz (X))
++#endif
++
+ #if defined (__mc68000__) && W_TYPE_SIZE == 32
+ #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+   __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0"				\
+diff -urN gcc-4.6.1-orig/gcc/Makefile.in gcc-4.6.1/gcc/Makefile.in
+--- gcc-4.6.1-orig/gcc/Makefile.in	2011-05-23 12:12:34.000000000 -0600
++++ gcc-4.6.1/gcc/Makefile.in	2011-09-17 14:06:01.197643616 -0600
+@@ -1987,14 +1987,14 @@
+ 
+ # Compile the start modules crt0.o and mcrt0.o that are linked with
+ # every program
+-$(T)crt0.o: s-crt0 ; @true
+-$(T)mcrt0.o: s-crt0; @true
++crt0.o: s-crt0 ; @true
++mcrt0.o: s-crt0; @true
+ 
+ s-crt0:	$(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H)
+ 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \
+-	  -o $(T)crt0.o -c $(CRT0_S)
++	  -o crt0.o -c $(CRT0_S)
+ 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \
+-	  -o $(T)mcrt0.o -c $(MCRT0_S)
++	  -o mcrt0.o -c $(MCRT0_S)
+ 	$(STAMP) s-crt0
+ #
+ # Compiling object files from source files.
+diff -urN gcc-4.6.1-orig/gcc/opth-gen.awk gcc-4.6.1/gcc/opth-gen.awk
+--- gcc-4.6.1-orig/gcc/opth-gen.awk	2011-02-08 10:41:00.000000000 -0700
++++ gcc-4.6.1/gcc/opth-gen.awk	2011-09-17 14:06:01.227643616 -0600
+@@ -121,7 +121,7 @@
+ END {
+ print "/* This file is auto-generated by opth-gen.awk.  */"
+ print ""
+-print "#ifndef OPTIONS_H"
++print "#if !defined(OPTIONS_H) && !defined(IN_LIBGCC2)"
+ print "#define OPTIONS_H"
+ print ""
+ print "#include \"flag-types.h\""
+@@ -432,18 +432,9 @@
+ 
+ for (i = 0; i < n_opts; i++) {
+ 	opt = opt_args("InverseMask", flags[i])
+-	if (opt ~ ",") {
+-		vname = var_name(flags[i])
+-		macro = "OPTION_"
+-		mask = "OPTION_MASK_"
+-		if (vname == "") {
+-			vname = "target_flags"
+-			macro = "TARGET_"
+-			mask = "MASK_"
+-		}
+-		print "#define " macro nth_arg(1, opt) \
+-		      " ((" vname " & " mask nth_arg(0, opt) ") == 0)"
+-	}
++	if (opt ~ ",")
++		print "#define TARGET_" nth_arg(1, opt) \
++		      " ((target_flags & MASK_" nth_arg(0, opt) ") == 0)"
+ }
+ print ""
+ 
+diff -urN gcc-4.6.1-orig/gcc/tree.h gcc-4.6.1/gcc/tree.h
+--- gcc-4.6.1-orig/gcc/tree.h	2011-06-14 09:28:21.000000000 -0600
++++ gcc-4.6.1/gcc/tree.h	2011-09-17 20:28:05.987646026 -0600
+@@ -3563,6 +3563,8 @@
+   TI_UINTDI_TYPE,
+   TI_UINTTI_TYPE,
+ 
++  TI_UINT8_TYPE,
++  TI_UINT16_TYPE,
+   TI_UINT32_TYPE,
+   TI_UINT64_TYPE,
+ 
+diff -urN gcc-4.6.1-orig/gcc/version.c gcc-4.6.1/gcc/version.c
+--- gcc-4.6.1-orig/gcc/version.c	2009-04-21 13:03:23.000000000 -0600
++++ gcc-4.6.1/gcc/version.c	2011-09-18 19:49:48.437654863 -0600
+@@ -21,16 +21,16 @@
+ 
+ /* This is the location of the online document giving instructions for
+    reporting bugs.  If you distribute a modified version of GCC,
+-   please configure with --with-bugurl pointing to a document giving
+-   instructions for reporting bugs to you, not us.  (You are of course
+-   welcome to forward us bugs reported to you, if you determine that
+-   they are not bugs in your modifications.)  */
++   please change this to refer to a document giving instructions for
++   reporting bugs to you, not us.  (You are of course welcome to
++   forward us bugs reported to you, if you determine that they are
++   not bugs in your modifications.)  */
+ 
+-const char bug_report_url[] = BUGURL;
++const char bug_report_url[] = "<URL:http://lost.l-w.ca/coco/lwtools/>";
+ 
+ /* The complete version string, assembled from several pieces.
+    BASEVER, DATESTAMP, DEVPHASE, and REVISION are defined by the
+    Makefile.  */
+ 
+-const char version_string[] = BASEVER DATESTAMP DEVPHASE REVISION;
++const char version_string[] = BASEVER DATESTAMP DEVPHASE REVISION " (gcc6809lw)";
+ const char pkgversion_string[] = PKGVERSION;
+diff -urN gcc-4.6.1-orig/libgcc/config.host gcc-4.6.1/libgcc/config.host
+--- gcc-4.6.1-orig/libgcc/config.host	2011-03-14 00:06:23.000000000 -0600
++++ gcc-4.6.1/libgcc/config.host	2011-09-17 14:06:01.257643616 -0600
+@@ -380,6 +380,8 @@
+  	;;
+ m32rle-*-linux*)
+ 	;;
++m6809*)
++	;;
+ m68hc11-*-*|m6811-*-*)
+         ;;
+ m68hc12-*-*|m6812-*-*)
+diff -urN gcc-4.6.1-orig/libgcc/fixed-obj.mk gcc-4.6.1/libgcc/fixed-obj.mk
+--- gcc-4.6.1-orig/libgcc/fixed-obj.mk	2007-09-17 16:18:13.000000000 -0600
++++ gcc-4.6.1/libgcc/fixed-obj.mk	2011-09-17 14:06:01.257643616 -0600
+@@ -23,7 +23,7 @@
+ #$(info $o$(objext): -DL$($o-label) $($o-opt))
+ 
+ $o$(objext): %$(objext): $(gcc_srcdir)/config/fixed-bit.c
+-	$(gcc_compile) -DL$($*-label) $($*-opt) -c $(gcc_srcdir)/config/fixed-bit.c $(vis_hide)
++	$(gcc_compile) -DL$($*-label) $($*-opt) -c $(gcc_srcdir)/config/fixed-bit.c $(vis_hide) -save-temps
+ 
+ ifeq ($(enable_shared),yes)
+ $(o)_s$(objext): %_s$(objext): $(gcc_srcdir)/config/fixed-bit.c
+diff -urN gcc-4.6.1-orig/libgcc/Makefile.in gcc-4.6.1/libgcc/Makefile.in
+--- gcc-4.6.1-orig/libgcc/Makefile.in	2011-01-25 21:19:58.000000000 -0700
++++ gcc-4.6.1/libgcc/Makefile.in	2011-09-17 14:06:01.257643616 -0600
+@@ -374,8 +374,8 @@
+ # Build lib2funcs.  For the static library also include LIB2FUNCS_ST.
+ lib2funcs-o = $(patsubst %,%$(objext),$(lib2funcs) $(LIB2FUNCS_ST))
+ $(lib2funcs-o): %$(objext): $(gcc_srcdir)/libgcc2.c
+-	$(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \
+-	  $(vis_hide)
++	ln -sf $(gcc_srcdir)/libgcc2.c $*.c && \
++	$(gcc_compile) -DL$* -c $*.c $(vis_hide) -save-temps
+ libgcc-objects += $(lib2funcs-o)
+ 
+ ifeq ($(enable_shared),yes)
+@@ -410,8 +410,9 @@
+ # Build LIB2_DIVMOD_FUNCS.
+ lib2-divmod-o = $(patsubst %,%$(objext),$(LIB2_DIVMOD_FUNCS))
+ $(lib2-divmod-o): %$(objext): $(gcc_srcdir)/libgcc2.c
+-	$(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \
+-	  -fexceptions -fnon-call-exceptions $(vis_hide)
++	ln -sf $(gcc_srcdir)/libgcc2.c $*.c && \
++	$(gcc_compile) -DL$* -c $*.c \
++	  -fexceptions -fnon-call-exceptions $(vis_hide) -save-temps
+ libgcc-objects += $(lib2-divmod-o)
+ 
+ ifeq ($(enable_shared),yes)
+@@ -443,7 +444,8 @@
+ ifneq ($(FPBIT),)
+ fpbit-o = $(patsubst %,%$(objext),$(FPBIT_FUNCS))
+ $(fpbit-o): %$(objext): $(FPBIT)
+-	$(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(FPBIT) $(vis_hide)
++	ln -sf $(FPBIT) $*.c && \
++	$(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $*.c $(vis_hide) -save-temps
+ libgcc-objects += $(fpbit-o)
+ 
+ ifeq ($(enable_shared),yes)
+@@ -458,7 +460,8 @@
+ ifneq ($(DPBIT),)
+ dpbit-o = $(patsubst %,%$(objext),$(DPBIT_FUNCS))
+ $(dpbit-o): %$(objext): $(DPBIT)
+-	$(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $(DPBIT) $(vis_hide)
++	ln -sf $(DPBIT) $*.c && \
++	$(gcc_compile) -DFINE_GRAINED_LIBRARIES -DL$* -c $*.c $(vis_hide) -save-temps
+ libgcc-objects += $(dpbit-o)
+ 
+ ifeq ($(enable_shared),yes)
+diff -urN gcc-4.6.1-orig/README.LW gcc-4.6.1/README.LW
+--- gcc-4.6.1-orig/README.LW	1969-12-31 17:00:00.000000000 -0700
++++ gcc-4.6.1/README.LW	2011-09-18 19:44:52.457654831 -0600
+@@ -0,0 +1,14 @@
++This is a port of gcc6809 which is designed to work with the lwtools
++cross-assembler and linker package.  You will need several scripts from that
++package, available at http://lost.l-w.ca/coco/lwtools/, in order to use
++this.  Instructions for building are present in the lwtools package.
++
++This work is based extensively on the gcc6809 4.3.4-3 release by Brian
++Dominy (brian@oddchange.com) with some significant renovations to make it
++work with gcc 4.6.1.
++
++There is no guarantee that it will work for any particular purpose you
++choose to put it to.
++
++If you run into any problems, contact William Astle (lost@l-w.ca). DO NOT
++contact the main GCC developers!