From: luik@isa.DE (Andreas Luik)
Subject: jump optimization may create insns with virtual_regs
Organization: GNUs Not Usenet
Distribution: gnu
Date: Tue, 22 Dec 1992 19:48:52 GMT

Program:	gcc
Version:	2.3.2

Host:		sparc-sun-sunos4.1.3
Target:		own (all that meet some conditions)
Area:		cc1/jump-optimization

Input file: 	cc.c

int compare (int a, int b)
{
    if (a >= b)
	if (a == b)
	    return (0);
	else
	    return (1);
    else
	return (-1);
}

gcc command:	gcc -S -O cc.c

Synopsis:	jump optimization may create insns with virtual_regs

Description:

    Suppose a target description with the following properties:
    
    1. no setcc insns
    2. PUSH_ROUNDING undefined
    3. BRANCH_COST 1
    4. no ashiftrt or lshiftrt insn defined, so libcall must be used
    
    Then jump_optimize will convert the insns as follows:
    
    before jump optimization: (file cc.c.rtl):
    
	;; Function compare
	
	(note 2 0 3 "" NOTE_INSN_DELETED)
	
	(insn 3 2 4 (set (reg/v:SI 20)
		(mem:SI (reg:SI 16))) -1 (nil)
	    (expr_list:REG_EQUIV (mem:SI (reg:SI 16))
		(nil)))
	
	(insn 4 3 5 (set (reg/v:SI 21)
		(mem:SI (plus:SI (reg:SI 16)
			(const_int 4)))) -1 (nil)
	    (expr_list:REG_EQUIV (mem:SI (plus:SI (reg:SI 16)
			(const_int 4)))
		(nil)))
	
	(note 5 4 6 "" NOTE_INSN_FUNCTION_BEG)
	
	(note 6 5 8 "" NOTE_INSN_DELETED)
	
	(note 8 6 9 "" NOTE_INSN_DELETED)
	
	(insn 9 8 10 (set (cc0)
		(compare (reg/v:SI 20)
		    (reg/v:SI 21))) -1 (nil)
	    (nil))
	
	(jump_insn 10 9 12 (set (pc)
		(if_then_else (lt (cc0)
			(const_int 0))
		    (label_ref 30)
		    (pc))) 12 {blt} (nil)
	    (nil))
	
	(insn 12 10 13 (set (cc0)
		(compare (reg/v:SI 20)
		    (reg/v:SI 21))) -1 (nil)
	    (nil))
	
	(jump_insn 13 12 15 (set (pc)
		(if_then_else (ne (cc0)
			(const_int 0))
		    (label_ref 21)
		    (pc))) 9 {bne} (nil)
	    (nil))
	
	(insn 15 13 16 (set (reg/i:SI 1 R1)
		(const_int 0)) -1 (nil)
	    (nil))
	
	(insn 16 15 17 (use (reg/i:SI 1 R1)) -1 (nil)
	    (nil))
	
	(jump_insn 17 16 18 (set (pc)
		(label_ref 40)) -1 (nil)
	    (nil))
	
	(barrier 18 17 19)
	
	(jump_insn 19 18 20 (set (pc)
		(label_ref 27)) -1 (nil)
	    (nil))
	
	(barrier 20 19 21)
	
	(code_label 21 20 23 3 "")
	
	(insn 23 21 24 (set (reg/i:SI 1 R1)
		(const_int 1)) -1 (nil)
	    (nil))
	
	(insn 24 23 25 (use (reg/i:SI 1 R1)) -1 (nil)
	    (nil))
	
	(jump_insn 25 24 26 (set (pc)
		(label_ref 40)) -1 (nil)
	    (nil))
	
	(barrier 26 25 27)
	
	(code_label 27 26 28 4 "")
	
	(jump_insn 28 27 29 (set (pc)
		(label_ref 36)) -1 (nil)
	    (nil))
	
	(barrier 29 28 30)
	
	(code_label 30 29 32 2 "")
	
	(insn 32 30 33 (set (reg/i:SI 1 R1)
		(const_int -1)) -1 (nil)
	    (nil))
	
	(insn 33 32 34 (use (reg/i:SI 1 R1)) -1 (nil)
	    (nil))
	
	(jump_insn 34 33 35 (set (pc)
		(label_ref 40)) -1 (nil)
	    (nil))
	
	(barrier 35 34 36)
	
	(code_label 36 35 38 5 "")
	
	(note 38 36 40 "" NOTE_INSN_FUNCTION_END)
	
	(code_label 40 38 0 1 "")
    
    after jump optimization (file cc.c.jump):
    
	;; Function compare
	
	(note 2 0 3 "" NOTE_INSN_DELETED)
	
	(insn 3 2 4 (set (reg/v:SI 20)
		(mem:SI (reg:SI 14 R14))) -1 (nil)
	    (expr_list:REG_EQUIV (mem:SI (reg:SI 14 R14))
		(nil)))
	
	(insn 4 3 5 (set (reg/v:SI 21)
		(mem:SI (plus:SI (reg:SI 14 R14)
			(const_int 4)))) -1 (nil)
	    (expr_list:REG_EQUIV (mem:SI (plus:SI (reg:SI 14 R14)
			(const_int 4)))
		(nil)))
	
	(note 5 4 6 "" NOTE_INSN_FUNCTION_BEG)
	
	(note 6 5 8 "" NOTE_INSN_DELETED)
	
	(note 8 6 9 "" NOTE_INSN_DELETED)
	
	(insn 9 8 10 (set (cc0)
		(compare (reg/v:SI 20)
		    (reg/v:SI 21))) -1 (nil)
	    (nil))
	
	(jump_insn 10 9 43 (set (pc)
		(if_then_else (lt (cc0)
			(const_int 0))
		    (label_ref 30)
		    (pc))) 12 {blt} (nil)
	    (nil))
	
	(insn 43 10 44 (set (reg/i:SI 1 R1)
		(const_int 1)) -1 (nil)
	    (nil))
	
	(insn 44 43 45 (set (reg:SI 22)
		(xor:SI (reg/v:SI 20)
		    (reg/v:SI 21))) -1 (nil)
	    (nil))
	
	(insn 45 44 46 (set (reg:SI 23)
		(neg:SI (reg:SI 22))) -1 (nil)
	    (nil))
	
	(insn 46 45 47 (set (reg:SI 24)
		(ior:SI (reg:SI 23)
		    (reg:SI 22))) -1 (nil)
	    (nil))
	
	(insn 47 46 48 (set (reg:SI 15 R15)
		(plus:SI (reg:SI 15 R15)
		    (const_int -8))) -1 (nil)
	    (insn_list:REG_LIBCALL 53 (nil)))
	
	(insn 48 47 49 (set (mem:SI (reg:SI 19))
		(reg:SI 24)) -1 (nil)
	    (nil))
	
	(insn 49 48 51 (set (mem:SI (plus:SI (reg:SI 19)
			(const_int 4)))
		(const_int 31)) -1 (nil)
	    (nil))
	
	(call_insn/u 51 49 52 (set (reg:SI 1 R1)
		(call (mem:SI (symbol_ref:SI ("__lshrsi3")))
		    (const_int 8))) -1 (nil)
	    (nil))
	
	(insn 52 51 53 (set (reg:SI 15 R15)
		(plus:SI (reg:SI 15 R15)
		    (const_int 8))) -1 (nil)
	    (nil))
	
	(insn 53 52 54 (set (reg:SI 25)
		(reg:SI 1 R1)) -1 (nil)
	    (insn_list:REG_RETVAL 47 (expr_list:REG_EQUAL (lshiftrt:SI (reg:SI 24)
			(const_int 31))
		    (nil))))
	
	(insn 54 53 25 (set (reg/i:SI 1 R1)
		(reg:SI 25)) -1 (nil)
	    (nil))
	
	(jump_insn 25 54 26 (set (pc)
		(label_ref 42)) -1 (nil)
	    (nil))
	
	(barrier 26 25 30)
	
	(code_label 30 26 32 2 "")
	
	(insn 32 30 42 (set (reg/i:SI 1 R1)
		(const_int -1)) -1 (nil)
	    (nil))
	
	(code_label 42 32 41 6 "")
	
	(insn 41 42 0 (use (reg/i:SI 1 R1)) -1 (nil)
	    (nil))
    
    Please note, that insns 48 and 49 use pseudo register 19, that is the
    VIRTUAL_OUTGOING_ARGS_REGNUM (virtual_outgoing_args_rtx) returned by
    push_block() and used by emit_library_call(). As these virtual
    registers are resolved before jump optimization but never afterwards,
    the compiler will crash in the reload phase.
    
    The following traceback shows the function calls down to the
    push_block call returning the virtual registers:
    
    #0  push_block (size=0x16acc0, extra=0, below=0) at expr.c:1557
    #1  0x6e3e0 in emit_library_call (__builtin_va_alist=1521800) at expr.c:2089
    #2  0x8affc in expand_binop (mode=SImode, binoptab=0x174910, op0=0x16be38, 
	op1=0x16ad78, target=0x16be38, unsignedp=1, methods=OPTAB_LIB_WIDEN)
	at optabs.c:1078
    #3  0x82920 in expand_shift (code=RSHIFT_EXPR, mode=SImode, shifted=0x16be38, 
	amount=0x177148, target=0x16be38, unsignedp=1) at expmed.c:1540
    #4  0x86514 in emit_store_flag (target=0x16bdb0, code=NE, op0=0x16bdb0, 
	op1=0x16ac80, mode=SImode, unsignedp=0, normalizep=1) at expmed.c:3027
    #5  0x85fb4 in emit_store_flag (target=0x16bdb0, code=NE, op0=0x16d8c0, 
	op1=0x16d920, mode=SImode, unsignedp=0, normalizep=1) at expmed.c:2904
    #6  0xafa94 in jump_optimize (f=0x16d748, cross_jump=0, noop_moves=0, 
	after_regscan=1) at jump.c:1095
    #7  0x3a938 in rest_of_compilation (decl=0x177060) at toplev.c:2288
    #8  0x20f88 in finish_function (nested=0) at c-decl.c:6088
    #9  0x896c in yyparse () at c-parse.y:269
    #10 0x39790 in compile_file (name=0xf7fffac2 "../test/cc.c") at toplev.c:1803
    #11 0x3d808 in main (argc=5, argv=0xf7fff9ec, envp=0xf7fffa04) at toplev.c:3285

Reproduce with:

    Unshar the following SHAR-file. It contains the following files:
    	risc32.md
    	risc32.c
    	risc32.h
    	xm-risc32.h
    	cc.c (the test program)

    Configure gcc as a cross-compiler with the appropriate links:
    	tm.h -> risc32.h
    	config.h -> <config file of host> e.g. config/xm-sparc.h
    	md -> risc32.md
    	tconfig.h -> xm-risc32.h
    	aux-output.c -> risc32.c
    	hconfig.h -> <config file of host> e.g. config/xm-sparc.h

    Build cc1 using "make"
    Try gcc with call.c: "./gcc -B./ -O2 -da -S cc.c"
    Check the dumped insn information.

Fix:

    Either the virtual registers must get instantiated again after
    jump optimization using another call to
    instantiate_virtual_regs(current_function_decl, get_insns ()) in
    toplev.c (I tried that, it seems to work), or jump optimization
    should not create library calls (which seems to make sense but may
    need some additional conditions at different places, so I didn't try
    that). Maybe instantiate_virtual_regs() may be called on the
    sequence of insns created by jump_optimize() only.

    I finally aviod the problem by defining BRANCH_COST as 0 because then
    jump optimization will not try to replace the jumps with arithmetic
    computations. If you think this is the correct way to avoid the problem,
    the documentation of BRANCH_COST should get updated to describe that.

#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 12/21/1992 19:17 UTC by luik@ramses
# Source directory /tmp/shar
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#    123 -rw-rw-r-- cc.c
#  14894 -rw-rw-r-- risc32.c
#  20416 -rw-rw-r-- risc32.h
#  13802 -rw-rw-r-- risc32.md
#   1657 -rw-rw-r-- xm-risc32.h
#
# ============= cc.c ==============
if test -f 'cc.c' -a X"$1" != X"-c"; then
	echo 'x - skipping cc.c (File already exists)'
else
echo 'x - extracting cc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'cc.c' &&
int compare (int a, int b)
{
X    if (a >= b)
X	if (a == b)
X	    return (0);
X	else
X	    return (1);
X    else
X	return (-1);
}
SHAR_EOF
chmod 0664 cc.c ||
echo 'restore of cc.c failed'
Wc_c="`wc -c < 'cc.c'`"
test 123 -eq "$Wc_c" ||
	echo 'cc.c: original size 123, current size' "$Wc_c"
fi
# ============= risc32.c ==============
if test -f 'risc32.c' -a X"$1" != X"-c"; then
	echo 'x - skipping risc32.c (File already exists)'
else
echo 'x - extracting risc32.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'risc32.c' &&
/* Subroutines for insn-output.c for IMS RISC32 controller.
X   Copyright (C) 1992 Andreas Luik <luik@isa.de>.
X
This file is part of GNU CC.
X
GNU CC 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.
X
GNU CC 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.
X
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
X
#include <assert.h>
#include <stdio.h>
#include "config.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "conditions.h"
#include "output.h"
#include "flags.h"
X
X
char *risc32_inline_shift_limit_cp;
int risc32_inline_shift_limit = 6;
X
extern char call_used_regs[];
X
X
X
/*
**  const_to_logical_const computes an immediate operand for any of the logical
**  operations (XOR, OR, AND) of the RISC32. The constant used in the instruction
**  specifies the number of the bit to be manipulated (the bit is either set
**  or cleared). The functions returns 0 if the bit_value does not match.
*/
X
int const_to_logical_const (bit_value, inst_value)
int bit_value;			/* constant to be checked */
int *inst_value;		/* RETURN: constant to be used in assembler */
{
X    register int i;
X    register int b;
X    int dummy;
X
X    if (inst_value == NULL)
X	inst_value = &dummy;
X
X    for (i = 0, b = 1; i < BITS_PER_WORD; i++, b <<= 1) {
X	if (bit_value == b) {
X	    *inst_value = i;
X	    return (1);
X	}
X	if (~bit_value == b) {
X	    *inst_value = i | (1 << 4);
X	    return (1);
X	}
X    }
X    return (0);
}
X
X
/*
**  operand_to_logical_operand returns the CONST_INT rtx with the value
**  const_to_logical_const() of the parameter op if its mode is CONST_INT.
*/
X
rtx operand_to_logical_operand (op)
rtx op;
{
X    if (GET_CODE (op) == CONST_INT) {
X	int immediate;
X    	if (const_to_logical_const (INTVAL (op), &immediate))
X    	    return (GEN_INT (immediate));
X	abort ();
X	/*NOTREACHED*/
X    }
X    return op;
}
X
X
X
/*
**  notice_update_cc is called by the final phase for each insn (exp is the
**  insn pattern). It is used to eliminate spurious test and compare insns.
**  It must set the value1 and value2 fields in cc_status to the rtls
**  representing the current condition codes settings as well as the flags
**  field (the flags and cc_status is defined in conditions.h).
**
**  Currently only some easy cases are handled: 
**  1. none of the jump insn change the condition codes
**  2. insns that explicitly set CC0 (test and compare) are handled properly
**  3. all other insn initialize cc_status.
**
**  These cases at least optimize the code generated for case statements.
*/
X
void notice_update_cc (exp, insn)
rtx exp;
rtx insn;
{
X    if (GET_CODE (insn) == JUMP_INSN)
X	return;
X
X    if ((GET_CODE (exp) == SET
X	 && GET_CODE (SET_DEST (exp)) == CC0)) {
X	cc_status.flags = 0;
X	cc_status.value1 = XEXP (exp, 0);
X	cc_status.value2 = XEXP (exp, 1);
X	return;
X    }
X
X    if ((GET_CODE (exp) == PARALLEL
X	 && GET_CODE (XVECEXP (exp, 0, 0)) == SET
X	 && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 0)) == CC0)) {
X	cc_status.flags = 0;
X	cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
X	cc_status.value2 = XEXP (XVECEXP (exp, 0, 0), 1);
X	return;
X    }
X
X    CC_STATUS_INIT;
}
X
X
X
/*
**  initial_frame_pointer_offset computes the offset between the frame pointer
**  and the stack pointer immediately after the function prologue. It must
**  add the frame size and the sizes of the registers that must be saved on
**  the stack.
*/
X
int
initial_frame_pointer_offset ()
{
X    int regno;
X    int offset = get_frame_size() ;
X
X    for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
X	if (regs_ever_live[regno] && !call_used_regs[regno])
X	    if (!(frame_pointer_needed && regno == FRAME_POINTER_REGNUM))
X		offset += UNITS_PER_WORD;
X
X    return (offset);
}
X
X
X
/*
**  output_function_prologue writes to the file f the assembler statements
**  for the start of an assembler procedure. It sets up the stack frame,
**  initializes the frame pointer, saves registers used in the function
**  and allocates size additional bytes on the stack.
*/
X
void
output_function_prologue (f, size)
FILE *f;
int size;			/* bytes to allocate on stack */
{
X    register int regno;
X    int num_saved_regs;
X
X    assert (size >= 0);
X    if (frame_pointer_needed) {
X	asm_fprintf (f, "\tPUSH\t%0R%s\n", reg_names[FRAME_POINTER_REGNUM]);
X	asm_fprintf (f, "\tMOV\t%0R%s,%0R%s\n",
X		     reg_names[FRAME_POINTER_REGNUM],
X		     reg_names[STACK_POINTER_REGNUM]);
X    }
X    else {
X	if (size > 16)		/* push SP (restore would be too expensive) */
X	    asm_fprintf (f, "\tPUSH\t%0R%s\n", reg_names[STACK_POINTER_REGNUM]);
X    }
X
X    if (size) {
X	if (size <= 16) {
X	    asm_fprintf (f, "\tADD\t%0R%s,%0R%s,%0I%d\n",
X			 reg_names[STACK_POINTER_REGNUM],
X			 reg_names[STACK_POINTER_REGNUM],
X			 -size);
X	}
X	else if (size <= 0x8000) {
X	    asm_fprintf (f, "\tLDI\t%0R%s,%0I%d\n",
X			 reg_names[FUNCTION_VALUE_REGNUM],
X			 -size);
X	    asm_fprintf (f, "\tADD\t%0R%s,%0R%s,%0R%s\n",
X			 reg_names[STACK_POINTER_REGNUM],
X			 reg_names[STACK_POINTER_REGNUM],
X			 reg_names[FUNCTION_VALUE_REGNUM]);
X	}
X	else
X	    error ("too many local variables");
X    }
X
X    if (TARGET_STACK_CHECK) {
X	/* XXX to be written */
X    }
X
X    /*
X    **  Save all used registers. Note that the frame pointer register needs
X    **  not to be saved if it is used as a frame pointer.
X    */
X
X    num_saved_regs = 0;
X    for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
X	if (regs_ever_live[regno] && !call_used_regs[regno])
X	    if (!(frame_pointer_needed && regno == FRAME_POINTER_REGNUM)) {
X		num_saved_regs++;
X		asm_fprintf (f, "\tST\t%0R%s,%0R%s,%0I%d\n",
X			     reg_names[regno],
X			     reg_names[STACK_POINTER_REGNUM],
X			     -num_saved_regs);
X	    }
X
X    if (num_saved_regs)		/* maximum value = 16 (FIRST_PSEUDO_REGISTER) */
X	asm_fprintf (f, "\tADD\t%0R%s,%0R%s,%0I%d\n",
X		     reg_names[STACK_POINTER_REGNUM],
X		     reg_names[STACK_POINTER_REGNUM],
X		     -num_saved_regs);
}
X
X
/*
**  output_function_epilogue writes the asse,bler code to exit from a function
**  the the assembler file f. It must restore the register values and the
**  stack pointer to their values when the function was called.
**  For documentation purposes, this function outputs a comment with "RET".
**  The "ENDPROC" assembler directive is written by ASM_DECLARE_FUNCTION_SIZE
**  because there it is easier to get the function name.
**  Note that this function should not depend on the value of the stack pointer
**  register (see documentation of EXIT_IGNORE_STACK).
*/
X
void
output_function_epilogue (f, size)
FILE *f;
int size;			/* same as for output_function_prologue */
{
X    register int regno;
X    register int nregs;		/* number of registers saved on stack */
X    int offset;			/* max offset from FP/SP to saved registers */
X    int inc;
X    rtx insn;
X
X    /*
X    **  If the last insn was a BARRIER, we don't have to write any code. But
X    **  lets output a no-op so that debuggers don't get confused about which
X    **  function the pc is in at this address.
X    */
X
X    insn = get_last_insn ();
X    if (GET_CODE (insn) == NOTE)
X	insn = prev_nonnote_insn (insn);
X    if (insn && GET_CODE (insn) == BARRIER) {
X	asm_fprintf (f, "\tNOP\n");
X	return;
X    }
X
X    assert (current_function_pops_args == 0);
X    assert (size >= 0);
X
#ifdef FUNCTION_EXTRA_EPILOGUE
X    FUNCTION_EXTRA_EPILOGUE (f, size);
#endif
X
X    if (frame_pointer_needed) {
X	nregs = 0;		/* get number of saved registers on stack */
X	for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
X	    if (regs_ever_live[regno] && !call_used_regs[regno])
X		if (!(frame_pointer_needed && regno == FRAME_POINTER_REGNUM))
X		    nregs++;
X
X	offset = nregs + size;
X
X	for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
X	    if (regs_ever_live[regno] && !call_used_regs[regno])
X		if (!(regno == FRAME_POINTER_REGNUM)) {
X		    if (offset <= 16) {	/* may address saved value directly */
X			asm_fprintf (f, "\tLD\t%0R%s,%0R%s,%0I%d\n",
X				     reg_names[regno],
X				     reg_names[FRAME_POINTER_REGNUM],
X				     -offset);
X		    }
X		    else {	/* need to address using index register */
X			assert (offset <= 0x8000);
X			asm_fprintf (f, "\tLDI\t%0R%s,%0I%d\n",
X				     reg_names[regno],
X				     -offset);
X			asm_fprintf (f, "\tLD\t%0R%s,%0R%s,%0R%s\n",
X				     reg_names[regno],
X				     reg_names[FRAME_POINTER_REGNUM],
X				     reg_names[regno]);
X		    }
X		    offset--;
X		}
X
X	asm_fprintf (f, "\tMOV\t%0R%s,%0R%s\n", /* restore stack pointer */
X		     reg_names[STACK_POINTER_REGNUM],
X		     reg_names[FRAME_POINTER_REGNUM]);
X	asm_fprintf (f, "\tPOP\t%0R%s\n", /* restore frame pointer */
X		     reg_names[FRAME_POINTER_REGNUM]);
X    }
X    else {
X	nregs = 0;
X	for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
X	    if (regs_ever_live[regno] && !call_used_regs[regno]) {
X		asm_fprintf (f, "\tLD\t%0R%s,%0R%s,%0I%d\n",
X			     reg_names[regno],
X			     reg_names[STACK_POINTER_REGNUM],
X			     nregs);
X		nregs++;
X	    }
X
X	if (size <= 16) {	/* restore SP value by adding the offset value */
X	    offset = nregs + size; /* maximum offset value is 32 */
X
X	    while (offset > 0) { /* should be executed at most twice */
X		inc = (offset > 16) ? 16 : offset;
X		asm_fprintf (f, "\tSUB\t%0R%s,%0R%s,%0I%d\n",
X			     reg_names[STACK_POINTER_REGNUM],
X			     reg_names[STACK_POINTER_REGNUM],
X			     -inc);
X		offset -= inc;
X	    }
X	}
X	else {			/* SP was pushed by prologue in this case */
X	    asm_fprintf (f, "\tPOP\t%0R%s\n", reg_names[STACK_POINTER_REGNUM]);
X	}
X    }
X
X    asm_fprintf (f, "\t;;; RET\n");
}
X
X
/*
**  A C compound statement to output to stdio stream f the
**  assembler syntax for an instruction operand op. op is an RTL
**  expression.
**
**  letter is a value that can be used to specify one of several ways
**  of printing the operand.  It is used when identical operands
**  must be printed differently depending on the context.  letter
**  comes from the `%' specification that was used to request
**  printing of the operand.  If the specification was just `%DIGIT'
**  then letter is 0; if the specification was `%LTR DIGIT' then letter
**  is the ASCII letter for LTR.
**
**  If op is a register, this macro should print the register's name.
**  The names can be found in an array `reg_names' whose type is
**  `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
**
**  When the machine description has a specification `%PUNCT' (a `%'
**  followed by a punctuation character), this macro is called with
**  a null pointer for op and the punctuation character for letter.
**
**  The risc32 specific letters are:
**
**  '#' for an immediate operand prefix
**  '%' for a register operand prefix
*/
X
void
print_operand (f, op, letter)
FILE *f;		/* file to write to */
rtx op;			/* operand to print */
int letter;		/* %<letter> or 0 */
{
X    switch (letter) {
X      case '#':
X	asm_fprintf (f, "%0I");
X	break;
X
X      case '%':
X	asm_fprintf (f, "%0R");
X	break;
X
X      default:
X	abort ();
X	/*NOTREACHED*/
X
X      case 0:
X	switch (GET_CODE (op)) {
X	  case REG:
X	    asm_fprintf (f, "%0R%s", reg_names[REGNO (op)]);
X	    break;
X
X	  case MEM:
X	    output_address (XEXP (op, 0));
X	    break;
X
X	  case CONST:
X	  case CONST_INT:
X	  case LABEL_REF:
X	  case SYMBOL_REF:
X	    asm_fprintf (f, "%0I");
X	    output_addr_const (f, op);
X	    break;
X
X	  default:
X	    fprintf (stderr, "print_operand: unknown code %d\n", GET_CODE (op));
X	    abort ();
X	    /*NOTREACHED*/
X	}
X    }
}
X
X
/*
**  A C compound statement to output to stdio stream f the
**  assembler syntax for an instruction operand that is a memory
**  reference whose address is addr.  addr is an RTL expression.
*/
X
void
print_operand_address (f, addr)
FILE *f;
rtx addr;
{
X    rtx base;
X    rtx offset = 0;
X    rtx index = 0;
X
X    switch (GET_CODE (addr)) {
X      case REG:
X	asm_fprintf (f, "%0R%s", reg_names[REGNO (addr)]);
X	break;
X
X      case PLUS:
X	if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
X	    offset = XEXP (addr, 0), base = XEXP (addr, 1);
X	else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
X	    offset = XEXP (addr, 1), base = XEXP (addr, 0);
X	else
X	    index = XEXP (addr, 1), base = XEXP (addr, 0);
X
X	asm_fprintf (f, "%0R%s", reg_names [REGNO (base)]);
X	if (index)
X	    asm_fprintf (f, ",%0R%s", reg_names [REGNO (index)]);
X	else {
X	    assert (((unsigned) INTVAL (offset) + 16) < 32);
X	    asm_fprintf (f, ",");
X	    output_addr_const (f, offset);
X	}
X	break;
X
X      case CONST:
X      case CONST_INT:
X      case LABEL_REF:
X      case SYMBOL_REF:
X	output_addr_const (f, addr);
X	break;
X
X      default:
X	fprintf (stderr, "print_operand_address: unknown code %d\n", 
X		 GET_CODE (addr));
X	abort ();
X	/*NOTREACHED*/
X    }
}
X
X
/*
**  r32_call_operand checks whether op is a legal operand for a RISC32 CALL
**  instruction. Most call operands are memory references. These are ignored
**  by calling r32_call_operand recursivly with the first expression of the
**  memory reference. Legal operands are CONST_INT and SYMBOL_REF.
**  The mode of the operand is currently ignored. Maybe it should be compared 
**  against FUNCTION_MODE.
*/
X
/*ARGSUSED*/
int r32_call_operand (op, mode)
rtx op;
enum machine_mode mode;
{
X    switch (GET_CODE (op)) {
X      case MEM:
X	return (r32_call_operand (XEXP (op, 0), mode));
X
X      case CONST_INT:
X      case SYMBOL_REF:
X	return (1);
X    }	
X    return (0);
}
X
X
/*
**  Function calls to absolute addresses (e.g. ((int (*)()) 0)(arg)) are
**  converted to a call to a register. The constant is forced to a register
**  immediately before the expansion of the call insn. To allow such constructs,
**  the define_expand for a call and a call_value insn checks for register
**  operands and calls r32_get_reg_value_rtx. This function checks the 
**  previous non-note insn whether it is a set insn with dest = op and a
**  constant src. This constant is returned if found because it's the current
**  value of the register used in the call insn. Otherwise 0 is returned and the
**  define_expand will treat this as an error.
*/
X
rtx r32_get_reg_value_rtx (op)
rtx op;
{
X    rtx insn;
X
X    assert (GET_CODE (op) == REG);
X
X    insn = get_last_insn_anywhere ();
X    while (insn && GET_CODE (insn) == NOTE)
X	insn = previous_insn (insn);
X
X    if (insn && GET_CODE (insn) == INSN) {
X	rtx pat = PATTERN (insn);
X	if ((GET_CODE (pat) == SET
X	     && GET_CODE (SET_DEST (pat)) == REG
X	     && REGNO (SET_DEST (pat)) == REGNO (op)
X	     && GET_MODE (SET_DEST (pat)) == GET_MODE (op)
X	     && CONSTANT_P (SET_SRC (pat))))
X	    return (SET_SRC (pat));
X    }
X
X    return ((rtx) 0);
}
X
SHAR_EOF
chmod 0664 risc32.c ||
echo 'restore of risc32.c failed'
Wc_c="`wc -c < 'risc32.c'`"
test 14894 -eq "$Wc_c" ||
	echo 'risc32.c: original size 14894, current size' "$Wc_c"
fi
# ============= risc32.h ==============
if test -f 'risc32.h' -a X"$1" != X"-c"; then
	echo 'x - skipping risc32.h (File already exists)'
else
echo 'x - extracting risc32.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'risc32.h' &&
/* Definitions of target machine for GNU compiler, for IMS RISC32 controller.
X   Copyright (C) 1992 Andreas Luik <luik@isa.de>.
X
This file is part of GNU CC.
X
GNU CC 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.
X
GNU CC 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.
X
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
X
X
/*
**  External variables/functions defined in risc32.c.
*/
X
extern char *risc32_inline_shift_limit_cp;
extern int risc32_inline_shift_limit;
X
/*
**  Controlling the Compilation Driver
**  ----------------------------------
*/
X
/* #define SWITCHES_TAKES_ARG(C) */
/* #define WORD_SWITCH_TAKES_ARG(NAME) */
/* #define SWITCHES_NEED_SPACES */
#define CPP_SPEC "%{mbarrel-shifter:-D__HAVE_BARREL_SHIFTER__}"
/* #define SIGNED_CHAR_SPEC */
/* #define CC1_SPEC */
/* #define CC1PLUS_SPEC */
/* #define ASM_SPEC */
/* #define ASM_FINAL_SPEC */
/* #define LINK_SPEC */
#define LIB_SPEC    	    	    	""
#define STARTFILE_SPEC 	    	    	"%{crt0-r32.o%s}"
/* #define ENDFILE_SPEC */
/* #define LINK_LIBGCC_SPECIAL */
/* #define RELATIVE_PREFIX_NOT_LINKDIR */
/* #define STANDARD_EXEC_PREFIX */
/* #define STANDARD_STARTFILE_PREFIX */
X
X
/*
**  Run-time Target Specification
**  ------------------------------
*/
X
#define CPP_PREDEFINES 	    	    	"-Drisc32"
/* #define STDC_VALUE */
X
extern int target_flags;
X
#define TARGET_BARREL_SHIFTER		(target_flags & 1)
#define TARGET_STACK_CHECK		(target_flags & 2)
#define TARGET_ABORT_ON_NOT_IMPLEMENTED	(target_flags & 4)
X
#define TARGET_DEFAULT 	    	    	0x0
X
#define TARGET_SWITCHES     {	    	\
X    {"barrel-shifter", 1},	    	\
X    {"no-barrel-shifter", -1},	    	\
X    {"stack-check", 2},		    	\
X    {"no-stack-check", -2},	    	\
X    {"abort-on-not-implemented", 4},	\
X    {"no-abort-on-not-implemented", -4},\
X    { "", TARGET_DEFAULT}}
X
#define TARGET_OPTIONS 	    {   \
X    { "inline-shift-limit-", &risc32_inline_shift_limit_cp } }
X
#define OVERRIDE_OPTIONS    	    	    	    	    	    	    	\
X    do {    	    	    	    	    	    	    	    	    	\
X    	if (profile_flag)   	    	    	    	    	    	    	\
X    	{   	    	    	    	    	    	    	    	    	\
X	      warning ("`-p' option (function profile) not supported");	    	\
X	      profile_flag = 0;	    	    	    	    	    	    	\
X	}   	    	    	    	    	    	    	    	    	\
X    	if (risc32_inline_shift_limit_cp)   	    	    	    	    	\
X	{   	    	    	    	    	    	    	    	    	\
X    	    int err = FALSE;	    	    	    	    	    	    	\
X    	    int limit;	    	    	    	    	    	    	    	\
X	    char *p; 	    	    	    	    	    	    	    	\
X    	    	    	    	    	    	    	    	    	    	\
X	    for (p = risc32_inline_shift_limit_cp; *p && !err; p++)	    	\
X		if (! (*p >= '0' && *p <= '9')) 	    	    	       	\
X    	    	    err = TRUE;	    	    	    	    	    	    	\
X    	    	    	    	    	    	    	    	    	    	\
X	    if ((limit = atoi (risc32_inline_shift_limit_cp)) <= 1)	    	\
X		err = TRUE; 	    	    	    	    	    	    	\
X    	    if (!err)	    	    	    	    	    	    	    	\
X		risc32_inline_shift_limit = limit;  	    	    	    	\
X	    else error ("Invalid option value `-minline-shift-limit-%s'",    	\
X	       	        risc32_inline_shift_limit_cp);	    	    	    	\
X	}   	    	    	    	    	    	    	    	    	\
X    } while (0)
X
/* Omit frame pointer at high optimization levels.  */
#define OPTIMIZATION_OPTIONS(OPTIMIZE) \
X    do {  								    	\
X    	if (OPTIMIZE >= 3) 						    	\
X    	    flag_omit_frame_pointer = 1;				    	\
X    } while (0)
X
#define TARGET_VERSION 	    	\
X    fprintf (stderr, " (IMS RISC32, ASM syntax)");
X
X
/*
**  Storage Layout
**  --------------
*/
X
/* #define BITS_BIG_ENDIAN */
#define BYTES_BIG_ENDIAN		1
#define WORDS_BIG_ENDIAN		1
X
#define BITS_PER_UNIT			8
#define BITS_PER_WORD			32
#define UNITS_PER_WORD			4
#define POINTER_SIZE			32
#define PARM_BOUNDARY			8
#define FUNCTION_BOUNDARY		8
#define BIGGEST_ALIGNMENT		8
#define EMPTY_FIELD_BOUNDARY		8
#define STRICT_ALIGNMENT		1
#define MAX_FIXED_MODE_SIZE		32
/* #define CHECK_FLOAT_VALUE */	               /* floats are not supported yet */
/* #define TARGET_FLOAT_FORMAT */   	       /* floats are not supported yet */
X
/*
**  Layout of Source Language Data Types
**  ------------------------------------
*/
X
#define INT_TYPE_SIZE			BITS_PER_WORD
#define SHORT_TYPE_SIZE			16
#define LONG_TYPE_SIZE			32
#define LONG_LONG_TYPE_SIZE		64
#define CHAR_TYPE_SIZE			BITS_PER_UNIT
#define FLOAT_TYPE_SIZE			32     /* floats are not supported yet */
#define DOUBLE_TYPE_SIZE		64     /* floats are not supported yet */
/* #define LONG_DOUBLE_TYPE_SIZE*/             /* floats are not supported yet */
X
#define DEFAULT_SIGNED_CHAR		1
X
#define SIZE_TYPE   	    	    	"unsigned int" /* XXX */
#define PTRDIFF_TYPE   	    	    	"unsigned int" /* XXX */
#define WCHAR_TYPE			"unsigned int" /* XXX */
#define WCHAR_TYPE_SIZE			32
X
#define TARGET_BELL			007
#define TARGET_BS			010
#define TARGET_TAB			011
#define TARGET_NEWLINE			012
#define TARGET_VT			013
#define TARGET_FF			014
#define TARGET_CR			015
X
X
/*
**  Register Usage
**  --------------
*/
X
#define FIRST_PSEUDO_REGISTER	16
X
#define FIXED_REGISTERS        	\
X    {	    	    	    	\
X	1, 0, 0, 0, 0, 0, 0, 0, \
X	0, 0, 0, 0, 0, 0, 0, 1, \
X    }
X
#define CALL_USED_REGISTERS     \
X    {	    	    	    	\
X	1, 1, 1, 1, 1, 0, 0, 0, \
X	0, 0, 0, 0, 0, 0, 1, 1, \
X    }
X
#define HARD_REGNO_NREGS(REGNO, MODE) \
X    ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
X
#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
X
#define MODES_TIEABLE_P(MODE1,MODE2)	1
X
X
/*
**  Register Classes
**  ----------------
*/
X
enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES };
X
#define N_REG_CLASSES (int) LIM_REG_CLASSES
X
#define REG_CLASS_NAMES \
X    { "NO_REGS", "GENERAL_REGS", "ALL_REGS" }
X
#define REG_CLASS_CONTENTS { 	    	    \
X    	0x00000000,   	/* NO_REGS */	    \
X    	0x0000fffe,	/* GENERAL_REGS */  \
X    	0x0000ffff,	/* ALL_REGS */	    \
X    }
X
#define REGNO_REG_CLASS(REGNO)		((REGNO) == 0 ? ALL_REGS : GENERAL_REGS)
X
#define BASE_REG_CLASS			GENERAL_REGS
#define INDEX_REG_CLASS			GENERAL_REGS
X
#define REG_CLASS_FROM_LETTER(C)	NO_REGS
X
#define HARD_REGNO_OK_FOR_BASE_OR_INDEX_P(REGNO) \
X    ((REGNO) > 0 && (REGNO) < FIRST_PSEUDO_REGISTER)
X
#define REGNO_OK_FOR_BASE_P(REGNO)  \
X    (HARD_REGNO_OK_FOR_BASE_OR_INDEX_P(REGNO) \
X     || HARD_REGNO_OK_FOR_BASE_OR_INDEX_P((unsigned) reg_renumber[REGNO]))
X
#define REGNO_OK_FOR_INDEX_P(REGNO) \
X    (HARD_REGNO_OK_FOR_BASE_OR_INDEX_P(REGNO) \
X     || HARD_REGNO_OK_FOR_BASE_OR_INDEX_P((unsigned) reg_renumber[REGNO]))
X
#define PREFERRED_RELOAD_CLASS(X,CLASS)	CLASS
X
#define CLASS_MAX_NREGS(CLASS, MODE) \
X    ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
X
/*
**  special constraint strings:
**  	I ... immediate value -16..15 for NEG/ONE_CMPL/ROT/LSHI/ASHI
**  	J ... immediate value -16..16 for ADD
**  	K ... immediate value with one bit set or cleared for XOR/OR/AND
*/
X
#define CONST_OK_FOR_LETTER_P(VALUE,C) \
X    ((C) == 'I' ? ((VALUE) >= -16 && (VALUE) <= 15) : \
X     (C) == 'J' ? ((VALUE) >= -16 && (VALUE) <= 16) : \
X     (C) == 'K' ? const_to_logical_const ((VALUE), (int *) 0) : 0) \
X
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE,C) \
X    0
X
X
/*
**  Describing Stack Layout and Calling Conventions
**  -----------------------------------------------
*/
X
#define STACK_GROWS_DOWNWARD
#define FRAME_GROWS_DOWNWARD
#define STARTING_FRAME_OFFSET		0
#define FIRST_PARM_OFFSET(FNDECL)	0
X
#define STACK_POINTER_REGNUM		15
#define FRAME_POINTER_REGNUM		14
#define ARG_POINTER_REGNUM		FRAME_POINTER_REGNUM
#define STATIC_CHAIN_REGNUM		13
X
#define FRAME_POINTER_REQUIRED		0
X
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) 	    	\
X    (DEPTH) = initial_frame_pointer_offset ()
X
/* #define LONGJMP_RESTORE_FROM_STACK */
X
#define PROMOTE_PROTOTYPES
/* #define PUSH_ROUNDING(BYTES) */         /* we do not use a push instruction */
#define RETURN_POPS_ARGS(FUNTYPE,SIZE)	0
X
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)	0
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED)  0
#define CUMULATIVE_ARGS	    	    	int
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME)    	\
X    ((CUM) = 0)
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
X    ((CUM) += ((MODE) != BLKmode    	    	    	\
X	       ? GET_MODE_SIZE (MODE) 	    	    	\
X	       : int_size_in_bytes (TYPE)))
#define FUNCTION_ARG_REGNO_P(N)     	0
X
#define FUNCTION_VALUE_REGNUM	    	1
#define FUNCTION_VALUE(VALTYPE, FUNC) 	\
X    gen_rtx (REG, TYPE_MODE (VALTYPE), FUNCTION_VALUE_REGNUM)
#define LIBCALL_VALUE(MODE)  	    	\
X    gen_rtx (REG, MODE, FUNCTION_VALUE_REGNUM)
#define FUNCTION_VALUE_REGNO_P(N)   	((N) == FUNCTION_VALUE_REGNUM)
X
#define STRUCT_VALUE_REGNUM 	    	2
X
#define FUNCTION_PROLOGUE(FILE, SIZE) 	output_function_prologue(FILE, SIZE)
#define EXIT_IGNORE_STACK 1
#define FUNCTION_EPILOGUE(FILE, SIZE)	output_function_epilogue(FILE, SIZE)
X
/* FUNCTION_PROFILER is used for -p */
#define FUNCTION_PROFILER(FILE, LABEL)	            /* profiling not supported */
X
/* Block profiling is enabled with "-a", but this is optional and not supported
X   on the RISC32. */
/* #define FUNCTION_BLOCK_PROFILER(FILE, LABEL) */
/* #define BLOCK_PROFILER(FILE, BLOCK) */
X
X
/*
**  Implementing the Varargs Macro
**  ------------------------------
*/
X
/*
**  The default varargs macros may be used since we pass parameters on a
**  stack
*/
X
/*
**  Trampolines for Nested Functions
**  --------------------------------
*/
X
#define TRAMPOLINE_TEMPLATE(FILE)   	          /* trampolines not supported */
#define TRAMPOLINE_SIZE	    	    	0
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) /* trampolines not supported */
/* #define INSN_CACHE_SIZE */
/* #define INSN_CACHE_LINE_WIDTH */
/* #define INSN_CACHE_DEPTH */
X
/*
**  Implicit Calls to Library Routines
**  ----------------------------------
*/
X
/*
**  Addressing Modes
**  ----------------
*/
X
#define CONSTANT_ADDRESS_P(X)		CONSTANT_P(X) /* XXX */
X
#define MAX_REGS_PER_ADDRESS		2
X
#ifndef REG_OK_STRICT
# define REG_OK_FOR_INDEX_P(X)		FALSE
# define REG_OK_FOR_BASE_P(X)		(REGNO (X) != 0)
#else
# define REG_OK_FOR_INDEX_P(X)	       	(REGNO_OK_FOR_INDEX_P (REGNO (X)))
# define REG_OK_FOR_BASE_P(X)	      	(REGNO_OK_FOR_BASE_P (REGNO (X)))
#endif
X
#define IS_REG_OK_FOR_BASE_P(X)				    \
X    (REG_P (X) && REG_OK_FOR_BASE_P (X))
X
#define GO_IF_CONST_ADDRESS(X, ADDR)			    \
X    {							    \
X    	if ((CONSTANT_ADDRESS_P (X) ||			    \
X	     IS_REG_OK_FOR_BASE_P (X)))     	    	    \
X	    goto ADDR;	    	    	    	    	    \
X    }
X
#define GO_IF_OFFSET_ADDRESS(X, ADDR)			    \
X    {							    \
X	if ((GET_CODE (X) == PLUS &&			    \
X	     IS_REG_OK_FOR_BASE_P (XEXP (X, 0)) &&	    \
X	     GET_CODE (XEXP (X, 1)) == CONST_INT &&	    \
X	     ((unsigned) INTVAL (XEXP (X, 1)) + 16) < 32))  \
X	    goto ADDR;	    	    	    	    	    \
X    }
X
#define GO_IF_INDEX_ADDRESS(X, ADDR)			    \
X    {							    \
X	if ((GET_CODE (X) == PLUS &&			    \
X	     IS_REG_OK_FOR_BASE_P (XEXP (X, 0)) &&	    \
X	     IS_REG_OK_FOR_BASE_P (XEXP (X, 1))))    	    \
X	    goto ADDR;	    	    	    	    	    \
X    }
X
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)		    \
X    {							    \
X	GO_IF_CONST_ADDRESS (X, ADDR);			    \
X	GO_IF_OFFSET_ADDRESS (X, ADDR);			    \
X	GO_IF_INDEX_ADDRESS (X, ADDR);			    \
X    }
X
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	    	    {}
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)   	    {}
X
#define LEGITIMATE_CONSTANT_P(X)    1
X
X
/*
**  Condition Code Status
**  ---------------------
*/
X
#define NOTICE_UPDATE_CC(EXP, INSN) 	    	    	    \
X    notice_update_cc(EXP, INSN)
X
X
/*
**  Describing Relative Costs of Operations
**  ---------------------------------------
*/
X
#define CONST_COSTS(RTX,CODE,OUTER_CODE)		    \
X  case CONST_INT:					    \
X    if (((unsigned) INTVAL (RTX)) + 16 < 32)		    \
X    	return 1;					    \
X    return 2;						    \
X  case CONST:						    \
X  case LABEL_REF:					    \
X  case SYMBOL_REF:					    \
X    return 1;						    \
X  case CONST_DOUBLE:					    \
X    return 8;
X
#define RTX_COSTS(X,CODE,OUTER_CODE)			    \
X  case SIGN_EXTEND:					    \
X    return (COSTS_N_INSNS (TARGET_BARREL_SHIFTER ? 4 : 5)); \
X  case ASHIFT:	    	    	    	    	    	    \
X  case ASHIFTRT:    	    	    	    	    	    \
X  case LSHIFT:	    	    	    	    	    	    \
X  case LSHIFTRT:    	    	    	    	    	    \
X  case ROTATE:	    	    	    	    	    	    \
X  case ROTATERT:    	    	    	    	    	    \
X    return (COSTS_N_INSNS (TARGET_BARREL_SHIFTER ? 1 : 6)); \
X  case MULT:						    \
X    return COSTS_N_INSNS (10); /* XXX */		    \
X  case DIV:						    \
X  case UDIV:						    \
X  case MOD:						    \
X  case UMOD:						    \
X    return COSTS_N_INSNS (10); /* XXX */
X
#define SLOW_BYTE_ACCESS    	    0
#define NO_FUNCTION_CSE
#define NO_RECURSIVE_FUNCTION_CSE
X
X
/*
**  Dividing the Output into Sections
**  ---------------------------------
*/
X
#define TEXT_SECTION_ASM_OP 	    ".TEXT"
#define DATA_SECTION_ASM_OP 	    ".DATA"
/* #define SHARED_SECTION_ASM_OP */
/* #define INIT_SECTION_ASM_OP */
#define READONLY_DATA_SECTION	    data_section
X
X
/*
**  Position Independent Code
**  -------------------------
*/
X
/*
**  it is not possible to implement position independent code on RISC32
*/
X
X
/*
**  Defining the Output Assembler Language
**  --------------------------------------
*/
X
#define ASM_FILE_START(FILE)				    \
X    fprintf (FILE, "%s", ASM_APP_OFF);			    \
X    if (TARGET_BARREL_SHIFTER)				    \
X    	fprintf (FILE, "\tBARREL\n");			    \
X    fprintf (FILE, "\tPRG\n");
X
/* #define ASM_FILE_END(FILE) */
X
#define ASM_IDENTIFY_GCC(FILE)	    fprintf (FILE, ";gcc2_compiled.:\n");
X
#define ASM_COMMENT_START   	    ";"
X
#define ASM_APP_ON  	    	    ";APP\n"
#define ASM_APP_OFF  	    	    ";NO_APP\n"
#define ASM_OUTPUT_SOURCE_FILENAME(FILE,NAME)
#define ASM_OUTPUT_SOURCE_LINE(FILE,LINE)
/* #define ASM_OUTPUT_IDENT(FILE,IDENT) */
#define OBJC_PROLOGUE
X
#define ASM_OUTPUT_DOUBLE(FILE,VALUE)			    \
X    (sorry ("double constants"),    	    	    	    \
X     fprintf (FILE, "\t;DOUBLE\t0r%.20g\n", (VALUE)))
X
#define ASM_OUTPUT_FLOAT(FILE,VALUE)			    \
X    (sorry ("float constants"),	    	    	    	    \
X     fprintf (FILE, "\t;FLOAT\t0r%.20g\n", (VALUE)))
X
#define ASM_OUTPUT_SHORT(FILE,VALUE)			    \
X    (sorry ("initialized variables"),	    	    	    \
X     fprintf (FILE, "\t;WORD\t"),			    \
X     output_addr_const (FILE, (VALUE)),			    \
X     fprintf (FILE, "\n"))
X
#define ASM_OUTPUT_CHAR(FILE,VALUE)			    \
X    (sorry ("initialized variables"),	    	    	    \
X     fprintf (FILE, "\t;WORD\t"),			    \
X     output_addr_const (FILE, (VALUE)),			    \
X     fprintf (FILE, "\n"))
X
/* ASM_BYTE_OP is only used in dwarfout.c and in assemble_zeros() if 
X   ASM_NO_SKIP_IN_TEXT == 1. */
#define ASM_BYTE_OP 	    	    ";WORD"
X
#define ASM_OUTPUT_BYTE(FILE,VALUE)			    \
X    (sorry ("initialized variables"),	    	    	    \
X     fprintf (FILE, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)))
X
#define ASM_OUTPUT_ASCII(FILE,PTR,LEN)			    \
X    sorry ("string constants");
X
#define ASM_OPEN_PAREN	    	    "("
#define ASM_CLOSE_PAREN	    	    ")"
X
#define ASM_OUTPUT_COMMON(FILE,NAME,SIZE,ROUNDED)	    \
X    (fprintf (FILE, "\t.GLOBAL\t"),			    \
X     assemble_name (FILE, (NAME)),			    \
X     fprintf (FILE, "\n"),				    \
X     ASM_OUTPUT_LOCAL(FILE,NAME,SIZE,ROUNDED))
X
#define ASM_OUTPUT_LOCAL(FILE,NAME,SIZE,ROUNDED)	    \
X    (fprintf (FILE, "\t.COMMON\t"),			    \
X     assemble_name (FILE, (NAME)),			    \
X     fprintf (FILE, ",%u\n",(ROUNDED)))			    \
X
#define ASM_OUTPUT_LABEL(FILE,NAME)			    \
X    (assemble_name (FILE, NAME), fputs (":\n", FILE))
X
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL)	    \
X    (assemble_name (FILE, NAME), fputs ("\tPROC\n", FILE))
X
/* ASM_DECLARE_FUNCTION_SIZE is used to output the ENDPROC assembler
X   directive. Alternatively, this may go into output_function_epilogue
X   but getting the function name is more difficult there. */
#define ASM_DECLARE_FUNCTION_SIZE(FILE,NAME,DECL)	    \
X    (assemble_name (FILE, NAME), fputs ("\tENDPROC\n", FILE))
X
/* #define ASM_DECLARE_OBJECT_NAME(FILE,NAME,DECL) */
X
#define ASM_GLOBALIZE_LABEL(FILE,NAME)			    \
X    (fprintf (FILE, "\t.EXPORT\t"),			    \
X     assemble_name (FILE, (NAME)),			    \
X     fprintf (FILE, "\n"))
X
/* #define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) */
/* #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE,SYMREF) */
X
#define ASM_OUTPUT_LABELREF(FILE,NAME)			    \
X    asm_fprintf (FILE, "%U%s", NAME)
X
/* #define ASM_OUTPUT_LABELREF_AS_INT(FILE,LABEL) */
X
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)	    \
X    asm_fprintf (FILE, "%0L%s%d:\n", PREFIX, NUM)
X
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)	    \
X    sprintf (LABEL, "*%s%s%d", LOCAL_LABEL_PREFIX, PREFIX, NUM)
X
#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)	    \
X    ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),	    \
X     sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
X
/* #include "aoutos.h" */
X
#define REGISTER_NAMES {				    \
X    "R0", "R1",  "R2",  "R3",  "R4",  "R5" , "R6",  "R7",   \
X    "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" }
X
#define ADDITIONAL_REGISTER_NAMES {			    \
X    { "FP", 14 },					    \
X    { "SP", 15 } }
X
/* #define ASM_OUTPUT_OPCODE(FILE,CP) */
X
#define PRINT_OPERAND(FILE, X, CODE) 	    print_operand (FILE, X, CODE)
X
#define PRINT_OPERAND_PUNCT_VALID_P(CODE)   ((CODE) == '#' || (CODE) == '%')
X
#define PRINT_OPERAND_ADDRESS(FILE, ADDR)   print_operand_address (FILE, ADDR)
X
#define REGISTER_PREFIX	    ""	/* used for %R in asm_fprintf */
#define LOCAL_LABEL_PREFIX  ""	/* used for %L in asm_fprintf */
#define USER_LABEL_PREFIX   "_"	/* used for %U in asm_fprintf */
#define IMMEDIATE_PREFIX    ""	/* used for %I in asm_fprintf */
X
/* The next two macros (reg PUSH and POP) are only used for profiling which
X   is currently unsupported. */
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)			    \
X    asm_fprintf (FILE, "\tPUSH\t%0R%s\n", reg_names[REGNO]);
X
#define ASM_OUTPUT_REG_POP(FILE,REGNO)			    \
X    asm_fprintf (FILE, "\tPOP\t%0R%s\n", reg_names[REGNO]);
X
/* Code for dispatch tables is not required because we use an (nearly)
X   infinite CASE_VALUES_THRESHOLD. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL)  	    abort ()
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)	    	    abort ()
X
#define ASM_OUTPUT_SKIP(FILE,BYTES)			    	    	    	\
X    {							    	    	    	\
X	int i = (BYTES);				    	    	    	\
X	if (in_text_section ()) {   	    	    	    	    	    	\
X	    while (i--)	    	    	    	    	    	    	    	\
X		asm_fprintf (FILE, "\tNOP\t; skip one byte (contents zero)\n");	\
X	}   	    	    	    	    	    	    	    	    	\
X    	else {	    	    	    	    	    	    	    	    	\
X	    while (i--)	    	    	    	    	    	    	    	\
X	    	ASM_OUTPUT_BYTE (FILE, 0);			    	    	\
X	}   	    	    	    	    	    	    	    	    	\
X    }
X
#define ASM_NO_SKIP_IN_TEXT 	    	    0
X
#define ASM_OUTPUT_ALIGN(FILE,POWER)	    abort ();
X
/*
**  Controlling Debbuging Information Format
**  ----------------------------------------
*/
X
/*
**  Debugging informations are not supported yet. Currently no debugger is
**  available.
*/
X
#define DBX_REGISTER_NUMBER(REGNO)  	    (REGNO)
X
X
/*
**  Cross Compilation and Floating Point Format
**  -------------------------------------------
*/
X
/*
**  No floating point format was definied for the risc32 yet, so we leave this
**  section empty.
*/
X
X
/*
**  Miscellaneous Parameters
**  ------------------------
*/
X
#define CASE_VECTOR_MODE    	    	    	SImode
#define CASE_VALUES_THRESHOLD	    	    	32767
#define EASY_DIV_EXPR 	    	    	    	TRUNC_DIV_EXPR
#define MOVE_MAX    	    	    	    	1
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 	1
#define STORE_FLAG_VALUE    	    	    	-1 /* XXX */
#define Pmode	    	    	    	    	SImode
#define FUNCTION_MODE 	    	    	    	SImode
X
X
/*
**  Declare functions defined in risc32.c and used in templates.
*/
X
SHAR_EOF
chmod 0664 risc32.h ||
echo 'restore of risc32.h failed'
Wc_c="`wc -c < 'risc32.h'`"
test 20416 -eq "$Wc_c" ||
	echo 'risc32.h: original size 20416, current size' "$Wc_c"
fi
# ============= risc32.md ==============
if test -f 'risc32.md' -a X"$1" != X"-c"; then
	echo 'x - skipping risc32.md (File already exists)'
else
echo 'x - extracting risc32.md (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'risc32.md' &&
;;- Machine description for GNU compiler
;;- IMS RISC32 controler Version
;;   Copyright (C) 1992 Andreas Luik <luik@isa.de>.
X
;; This file is part of GNU CC.
X
;; GNU CC 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.
X
;; GNU CC 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.
X
;; You should have received a copy of the GNU General Public License
;; along with GNU CC; see the file COPYING.  If not, write to
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X
X
;;
;;  Test and compare operations (PSW operations)
;;  --------------------------------------------
;;
X
(define_insn "tstsi"
X  [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
X  ""
X  "TST	%0")
X
(define_insn "cmpsi"
X  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r")
X		       (match_operand:SI 1 "register_operand" "r")))]
X  ""
X  "CMP	%0,%1")
X
X
;;
;;  Unconditional jumps
;;  -------------------
;;
X
(define_insn "jump"
X  [(set (pc) (label_ref (match_operand 0 "" "")))]
X  ""
X  "JMP	%l0")
X
(define_insn "indirect_jump"
X  [(set (pc) (match_operand:SI 0 "general_operand" "r"))]
X  ""
X  "*
{
X    sorry (\"computed goto or goto to non-local label\");
X    return \"JMP	%0\";
}")
X
;;
;;  Subroutine handling and stack operations
;;  ----------------------------------------
;;
X
(define_expand "call"
X  [(call (mem:SI (match_operand:SI 0 "" ""))
X	 (match_operand 1 "" ""))]
X  ""
X  "
{
X    rtx op0;			/* operand0 without (mem ()) */
X    extern rtx r32_get_reg_value_rtx ();
X
X    op0 = GET_CODE (operands[0]) == MEM ? XEXP (operands[0], 0) : operands[0];
X    if (GET_CODE (op0) == REG) {
X	rtx value = r32_get_reg_value_rtx (op0); /* search for register value */
X	if (value)		/* value of register found, use it */
X	    op0 = value;
X    }
X
X    if (!r32_call_operand (op0, SImode)) {
X	sorry (\"pointers to functions\");
X	if (TARGET_ABORT_ON_NOT_IMPLEMENTED)
X	    abort ();
X	op0 = gen_rtx (SYMBOL_REF, SImode, \"unknown\");
X    }
X
X    operands[0] = op0;		/* (mem ()) added by RTL template */
}")
X
(define_insn ""
X  [(call (match_operand:SI 0 "r32_call_operand" "m")
X	 (match_operand 1 "general_operand" "g"))]
X  ;; Operand 1 not really used on the risc32.
X  ""
X  "CALL	%0")
X
X
(define_expand "call_value"
X  [(set (match_operand 0 "" "=r")
X	(call (mem:SI (match_operand:SI 1 "" ""))
X	      (match_operand 2 "" "")))]
X  ""
X  "
{
X    rtx op1;			/* operand1 without (mem ()) */
X    extern rtx r32_get_reg_value_rtx ();
X
X    op1 = GET_CODE (operands[1]) == MEM ? XEXP (operands[1], 0) : operands[1];
X    if (GET_CODE (op1) == REG) {
X	rtx value = r32_get_reg_value_rtx (op1); /* search for register value */
X	if (value)		/* value of register found, use it */
X	    op1 = value;
X    }
X
X    if (!r32_call_operand (op1, SImode)) {
X	sorry (\"pointers to functions\");
X	if (TARGET_ABORT_ON_NOT_IMPLEMENTED)
X	    abort ();
X	op1 = gen_rtx (SYMBOL_REF, SImode, \"unknown\");
X    }
X
X    operands[1] = op1;		/* (mem ()) added by RTL template */
}")
X
(define_insn ""
X  [(set (match_operand 0 "" "=r")
X	(call (match_operand:SI 1 "r32_call_operand" "m")
X	      (match_operand 2 "general_operand" "g")))]
X  ;; Operand 2 not really used on the risc32.
X  ""
X  "CALL	%1")
X
X
;;
;;  Conditional jumps
;;  -----------------
;;
X
(define_insn "beq"
X  [(set (pc) (if_then_else (eq (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JEQ	%l0")
X
(define_insn "bne"
X  [(set (pc) (if_then_else (ne (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JNE	%l0")
X
(define_insn "bgt"
X  [(set (pc) (if_then_else (gt (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JGT	%l0")
X
(define_insn "bgtu"
X  [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JHI	%l0")
X
(define_insn "blt"
X  [(set (pc) (if_then_else (lt (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JLT	%l0")
X
(define_insn "bltu"
X  [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JLO	%l0")
X
(define_insn "bge"
X  [(set (pc) (if_then_else (ge (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JGE	%l0")
X
(define_insn "bgeu"
X  [(set (pc) (if_then_else (geu (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JHS	%l0")
X
(define_insn "ble"
X  [(set (pc) (if_then_else (le (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JLE	%l0")
X
(define_insn "bleu"
X  [(set (pc) (if_then_else (leu (cc0) (const_int 0))
X			   (label_ref (match_operand 0 "" ""))
X			   (pc)))]
X  ""
X  "JLS	%l0")
X
;; reverse-conditional branches
X
(define_insn ""
X  [(set (pc) (if_then_else (eq (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JNE	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (ne (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JEQ	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (gt (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JLE	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JLS	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (lt (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JGE	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JHS	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (ge (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JLT	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (geu (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JLO	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (le (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JGT	%l0")
X
(define_insn ""
X  [(set (pc) (if_then_else (leu (cc0) (const_int 0))
X			   (pc)
X			   (label_ref (match_operand 0 "" ""))))]
X  ""
X  "JHI	%l0")
X
X
;;
;;  Load and Store operations
;;  -------------------------
;;
X
(define_insn "movsi"
X  [(set (match_operand:SI 0 "general_operand" "=r,r,r,o")
X	(match_operand:SI 1 "general_operand" "r,o,i,r"))]
X  ""
X  "*
{
X    switch (which_alternative) {
X      case 0:
X    	return \"MOV	%0,%1\";
X
X      case 1:			/* operands[1] must have code MEM */
X	switch (GET_CODE (XEXP (operands[1], 0))) {
X	  case SYMBOL_REF:
X	    return \"LDA	%0,%1\";
X	  case REG:
X	    return \"LD	%0,%1,%#0\";
X	  default:
X	    return \"LD	%0,%1\";
X	}
X
X      case 2:
X	if (INTVAL (operands[1]) == 0)
X	    return \"CLR	%0\";
X	else
X	    return \"LDI	%0,%1\";
X
X      case 3:			/* operands[0] must have code MEM */
X	switch (GET_CODE (XEXP (operands[0], 0))) {
X	  case SYMBOL_REF:
X	    return \"STA	%1,%0\";
X	  case REG:
X	    return \"ST	%1,%0,%#0\";
X	  default:
X	    return \"ST	%1,%0\";
X	}
X
X      default:
X	abort ();
X	/*NOTREACHED*/
X    };
}")
X
;;
;;  Arithmetic operations
;;  ---------------------
;;
X
(define_insn "addsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(plus:SI (match_operand:SI 1 "register_operand" "r")
X		 (match_operand:SI 2 "general_operand" "rJ")))]
X  ""
X  "*
{
X    if (GET_CODE (operands[2]) == CONST_INT) {
X	int value = INTVAL (operands[2]);
X
X	/*
X	**  Use SUB instead of ADD for negative constants. Note that 
X	**  addition of the constant 16 is converted to subtraction of 
X	**  -16 (this saves one instruction because 16 is too big for
X	**  an immediate add operand).
X	*/
X
X	if (value == 16 || (value > -16 && value < 0)) {
X	    operands[2] = GEN_INT (-value);
X	    return \"SUB	%0,%1,%2\";
X	}
X    }
X
X    return \"ADD	%0,%1,%2\";
}")
X
(define_insn "subsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(minus:SI (match_operand:SI 1 "register_operand" "r")
X		  (match_operand:SI 2 "register_operand" "r")))]
X  ""
X  "SUB	%0,%1,%2")
X
;;
;;  Logical operations
;;  ------------------
;;
X
(define_insn "andsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(and:SI (match_operand:SI 1 "register_operand" "r")
X		(match_operand:SI 2 "general_operand" "rK")))]
X  ""
X  "*
{
X    extern rtx operand_to_logical_operand ();
X    operands[2] = operand_to_logical_operand (operands[2]);
X    return \"AND	%0,%1,%2\";
}")
X
(define_insn ""
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
X		(not:SI (match_operand:SI 2 "general_operand" "rK"))))]
X  ""
X  "*
{
X    extern rtx operand_to_logical_operand ();
X    operands[2] = operand_to_logical_operand (operands[2]);
X    return \"NAND	%0,%1,%2\";
}")
X
(define_insn "iorsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(ior:SI (match_operand:SI 1 "register_operand" "r")
X		(match_operand:SI 2 "general_operand" "rK")))]
X  ""
X  "*
{
X    extern rtx operand_to_logical_operand ();
X    operands[2] = operand_to_logical_operand (operands[2]);
X    return \"OR	%0,%1,%2\";
}")
X
(define_insn "xorsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(xor:SI (match_operand:SI 1 "register_operand" "r")
X		(match_operand:SI 2 "general_operand" "rK")))]
X  ""
X  "*
{
X    extern rtx operand_to_logical_operand ();
X    operands[2] = operand_to_logical_operand (operands[2]);
X    return \"XOR	%0,%1,%2\";
}")
X
(define_insn "negsi2"
X  [(set (match_operand:SI 0 "register_operand" "=r,r")
X	(neg:SI (match_operand:SI 1 "general_operand" "r,I")))]
X  ""
X  "@
X   CPL	%0,%1
X   SUB	%0,R0,%1	; CPL	%0,%1")
X
(define_insn "one_cmplsi2"
X  [(set (match_operand:SI 0 "register_operand" "=r,r")
X	(not:SI (match_operand:SI 1 "general_operand" "r,I")))]
X  ""
X  "@
X   NEG	%0,%1
X   NADD	%0,R0,%1	; NEG	%0,%1")
X
;;
;;  Shift- and rotate operations
;;  ----------------------------
;;
X
;; arithmetic shift left
(define_insn "ashlsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(ashift:SI (match_operand:SI 1 "register_operand" "r")
X		   (match_operand:SI 2 "general_operand" "rI")))]
X  "TARGET_BARREL_SHIFTER"
X  "ASHL	%0,%1,%2")
X
(define_insn ""
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(ashift:SI (match_operand:SI 1 "register_operand" "r")
X		   (match_operand:SI 2 "general_operand" "I")))]
X  "GET_CODE (operands[2]) == CONST_INT"
X  "*
{
X    int shift_count = INTVAL (operands[2]);
X    output_asm_insn (\"ASHL	%0,%1\", operands);
X    while (--shift_count)
X    	output_asm_insn (\"ASHL	%0,%0\", operands);
}")
X
;; arithmetic shift right
(define_insn "ashrsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
X		     (match_operand:SI 2 "general_operand" "rI")))]
X  "TARGET_BARREL_SHIFTER"
X  "ASHR	%0,%1,%2")
X
(define_insn ""
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
X		     (match_operand:SI 2 "general_operand" "I")))]
X  "GET_CODE (operands[2]) == CONST_INT"
X  "*
{
X    int shift_count = INTVAL (operands[2]);
X    output_asm_insn (\"ASHR	%0,%1\", operands);
X    while (--shift_count)
X    	output_asm_insn (\"ASHR	%0,%0\", operands);
}")
X
;; logical shift right
(define_insn "lshrsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
X		     (match_operand:SI 2 "general_operand" "rI")))]
X  "TARGET_BARREL_SHIFTER"
X  "LSHR	%0,%1,%2")
X
(define_insn ""
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
X		     (match_operand:SI 2 "general_operand" "I")))]
X  "GET_CODE (operands[2]) == CONST_INT"
X  "*
{
X    int shift_count = INTVAL (operands[2]);
X    output_asm_insn (\"LSHR	%0,%1\", operands);
X    while (--shift_count)
X    	output_asm_insn (\"LSHR	%0,%0\", operands);
}")
X
;; rotate left
(define_insn "rotlsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(rotate:SI (match_operand:SI 1 "register_operand" "r")
X		   (match_operand:SI 2 "general_operand" "rI")))]
X  "TARGET_BARREL_SHIFTER"
X  "ROL	%0,%1,%2")
X
(define_insn ""
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(rotate:SI (match_operand:SI 1 "register_operand" "r")
X		   (match_operand:SI 2 "general_operand" "I")))]
X  "GET_CODE (operands[2]) == CONST_INT"
X  "*
{
X    int shift_count = INTVAL (operands[2]);
X    output_asm_insn (\"ROL	%0,%1\", operands);
X    while (--shift_count)
X    	output_asm_insn (\"ROL	%0,%0\", operands);
}")
X
;; rotate right
(define_insn "rotrsi3"
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(rotatert:SI (match_operand:SI 1 "register_operand" "r")
X		     (match_operand:SI 2 "general_operand" "rI")))]
X  "TARGET_BARREL_SHIFTER"
X  "ROR	%0,%1,%2")
X
(define_insn ""
X  [(set (match_operand:SI 0 "register_operand" "=r")
X	(rotatert:SI (match_operand:SI 1 "register_operand" "r")
X		     (match_operand:SI 2 "general_operand" "I")))]
X  "GET_CODE (operands[2]) == CONST_INT"
X  "*
{
X    int shift_count = INTVAL (operands[2]);
X    output_asm_insn (\"ROR	%0,%1\", operands);
X    while (--shift_count)
X    	output_asm_insn (\"ROR	%0,%0\", operands);
}")
X
;;
;;  Misc operations
;;  ---------------
;;
X
(define_insn "nop"
X  [(const_int 0)]
X  ""
X  "NOP")
X
X
;;- Local variables:
;;- 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 ?} "){")
;;- End:
SHAR_EOF
chmod 0664 risc32.md ||
echo 'restore of risc32.md failed'
Wc_c="`wc -c < 'risc32.md'`"
test 13802 -eq "$Wc_c" ||
	echo 'risc32.md: original size 13802, current size' "$Wc_c"
fi
# ============= xm-risc32.h ==============
if test -f 'xm-risc32.h' -a X"$1" != X"-c"; then
	echo 'x - skipping xm-risc32.h (File already exists)'
else
echo 'x - extracting xm-risc32.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xm-risc32.h' &&
/* Configuration for GNU C-compiler for IMS RISC32 controller.
X   Copyright (C) 1992 Andreas Luik <luik@isa.de>.
X
This file is part of GNU CC.
X
GNU CC 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.
X
GNU CC 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.
X
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
X
X
/* #defines that need visibility everywhere.  */
#define FALSE 0
#define TRUE 1
X
/* Arguments to use with `exit'.  */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
X
/* Doubles are stored in memory with the high order word first.  This
X   matters when cross-compiling.  */
#define HOST_WORDS_BIG_ENDIAN
X
/* This describes the machine the compiler is hosted on.  */
#define HOST_BITS_PER_CHAR 16
#define HOST_BITS_PER_SHORT 16
#define HOST_BITS_PER_INT 32
#define HOST_BITS_PER_LONG 32
#define HOST_BITS_PER_LONGLONG 64
X
/* target machine dependencies.
X   tm.h is a symbolic link to the actual target specific file.   */
#include "tm.h"
X
/* If compiled with GNU C, use the built-in alloca.  */
#ifdef __GNUC__
/* Use an arg in this macro because that's what some other
X   system does--let's avoid conflict.  */
#define alloca(x) __builtin_alloca(x)
#endif
SHAR_EOF
chmod 0664 xm-risc32.h ||
echo 'restore of xm-risc32.h failed'
Wc_c="`wc -c < 'xm-risc32.h'`"
test 1657 -eq "$Wc_c" ||
	echo 'xm-risc32.h: original size 1657, current size' "$Wc_c"
fi
exit 0

-- 
Andreas Luik                E-Mail: luik@isa.de
(postmaster@isa.de)         UUCP:   ...!{uunet!unido,pyramid}!isaak!luik


Newsgroups: gnu.gcc.bug