config.gcc: Add stormy16-*-elf case.

* config.gcc: Add stormy16-*-elf case.
	* config/stormy16/stormy-abi: New file.
	* config/stormy16/stormy16-lib2.c: New file.
	* config/stormy16/stormy16-protos.h: New file.
	* config/stormy16/stormy16.c: New file.
	* config/stormy16/stormy16.h: New file.
	* config/stormy16/stormy16.md: New file.
	* config/stormy16/t-stormy16: New file.

From-SVN: r45173
This commit is contained in:
Geoffrey Keating 2001-08-25 17:14:36 +00:00 committed by Geoffrey Keating
parent d3fe11e624
commit 4b58290fe6
9 changed files with 8618 additions and 0 deletions

View File

@ -1,3 +1,14 @@
2001-08-22 Geoffrey Keating <geoffk@redhat.com>
* config.gcc: Add stormy16-*-elf case.
* config/stormy16/stormy-abi: New file.
* config/stormy16/stormy16-lib2.c: New file.
* config/stormy16/stormy16-protos.h: New file.
* config/stormy16/stormy16.c: New file.
* config/stormy16/stormy16.h: New file.
* config/stormy16/stormy16.md: New file.
* config/stormy16/t-stormy16: New file.
Sat Aug 25 15:46:51 CEST 2001 Jan Hubicka <jh@suse.cz>
* i386.h (no-accumulate-outgoing-args): Use proper mask.

View File

@ -3099,6 +3099,10 @@ sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux
fi
float_format=sparc
;;
stormy16-*-elf)
tmake_file="stormy16/t-stormy16"
extra_parts="crtbegin.o crtend.o"
;;
strongarm-*-elf*)
tm_file=arm/strongarm-elf.h
tmake_file=arm/t-strongarm-elf

View File

@ -0,0 +1,153 @@
Stormy16 ABI
************
!!!!! NOTE !!!!!
This document is a draft and is subject to change.
!!!!! NOTE !!!!!
This part of the file describes the conventions required to write
ELF object files that are link-compatible with the ones produced
by the GNU toolchains.
Bit and Byte Ordering
=====================
This implementation is little-endian. Bits are numbered starting
from 0 being the LSB.
In this document, 'word' means 16 bits.
Calling Sequence
================
The registers are allocated as follows:
Register Purpose
-------------------------------------------------------------------
r0, r1 Call-volatile. May be changed during the execution
of a call instruction.
r2 through r9 Argument passing; call-clobbered.
r10 through r13 Call-saved.
r14 Program status word.
r15 Stack pointer.
The return value of a procedure is returned in r2-r9 if it fits,
otherwise a pointer is passed as a `hidden' first argument
and the return value is placed there.
Arguments are passed in registers starting in r2, then on the stack.
Arguments of size not a multiple of a word are padded to whole words.
If an argument would otherwise be passed partially in registers, and
partially on the stack, the whole of it is passed on the stack. The
last argument is pushed on the stack first.
After a procedure's arguments are pushed on the stack,
the return address is pushed on the stack, as if by the call
instruction. The return address is on the top of the stack when
a procedure is called.
Objects whose size is a multiple of 16 bits are aligned to a 16-bit
boundary.
Pointers are 16 bits, referencing addresses between 0 and 0xFFFF.
Procedure pointers are also implemented as 16-bit pointers.
Variable Argument Functions
===========================
The C type 'va_list' is implemented as a structure, as follows:
struct {
char *base;
unsigned count;
}
Both fields are 16 bits. An argument of size N bytes
(N will be even) is accessed as if by the following code:
char *result;
if (count + N > 16)
{
if (count < 16)
count = 16;
result = base - (count + N - 16 + 4);
}
else
{
result = base + count;
}
count += N;
/* The argument is at `*result'. */
One implementation of this is if a variadic function first
pushes registers 2 through 9 in sequence at entry, and
sets 'base' to the address of the first word pushed,
producing a stack that appears like:
SP ->
[other data]
r9
r8
r7
r6
r5
r4
r3
count-> r2
Return address (two words)
9th procedure parameter word
10th procedure parameter word
...
last procedure parameter word
and initialises 'count' to be the number of bytes of non-variable
arguments to the function.
ELF File Format
===============
ELF file header
---------------
Stormy16 ELF files are distinguished by the value EM_STORMY16 in
the e_machine field of the ELF file header:
#define EM_STORMY16 0xad45
DWARF Register Number Mapping
-----------------------------
Registers r0 through r15 are mapped to numbers 0 through 15.
Relocations
-----------
RELA relocs are used exclusively. The relocation types defined are:
Name Value Field Calculation Overflow
----------------------------------------------------------------
R_STORMY16_NONE 0 none none none
R_STORMY16_32 1 32 S + A none
R_STORMY16_16 2 16 S + A unsigned
R_STORMY16_8 3 8 S + A unsigned
R_STORMY16_PC32 4 32 S + A - P none
R_STORMY16_PC16 5 16 S + A - P signed
R_STORMY16_PC8 6 8 S + A - P signed
R_STORMY16_REL_12 7 16:12:0 S + A - P signed
R_STORMY16_24 8 32:23:1 (S + A) >> 1 unsigned
R_STORMY16_GNU_VTINHERIT 9 n/a n/a n/a
R_STORMY16_GNU_VTENTRY 10 n/a n/a n/a
In the 'Calculation' column, 'S' is the value of the symbol to which
the reloc refers, 'A' is the addend, and 'P' represents the place of
the storage unit being relocated.
In the 'Field' column, the first number indicates whether the
relocation refers to a byte, word or doubleword. The second number,
if any, indicates the size of the bitfield into which the relocation
is to occur (and also the size for overflow checking). The third
number indicates the first bit of the bitfield in the word or
doubleword, counting the LSB as bit 0.

View File

@ -0,0 +1,142 @@
typedef int HItype __attribute__ ((mode (HI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int word_type __attribute__ ((mode (__word__)));
USItype
udivmodsi4(USItype num, USItype den, word_type modwanted)
{
USItype bit = 1;
USItype res = 0;
while (den < num && bit && !(den & (1L<<31)))
{
den <<=1;
bit <<=1;
}
while (bit)
{
if (num >= den)
{
num -= den;
res |= bit;
}
bit >>=1;
den >>=1;
}
if (modwanted) return num;
return res;
}
SItype
__divsi3 (SItype a, SItype b)
{
word_type neg = 0;
SItype res;
if (a < 0)
{
a = -a;
neg = !neg;
}
if (b < 0)
{
b = -b;
neg = !neg;
}
res = udivmodsi4 (a, b, 0);
if (neg)
res = -res;
return res;
}
SItype
__modsi3 (SItype a, SItype b)
{
word_type neg = 0;
SItype res;
if (a < 0)
{
a = -a;
neg = 1;
}
if (b < 0)
b = -b;
res = udivmodsi4 (a, b, 1);
if (neg)
res = -res;
return res;
}
SItype
__udivsi3 (SItype a, SItype b)
{
return udivmodsi4 (a, b, 0);
}
SItype
__umodsi3 (SItype a, SItype b)
{
return udivmodsi4 (a, b, 1);
}
SItype
__ashlsi3 (SItype a, SItype b)
{
word_type i;
if (b & 16)
a <<= 16;
if (b & 8)
a <<= 8;
for (i = (b & 0x7); i > 0; --i)
a <<= 1;
return a;
}
SItype
__ashrsi3 (SItype a, SItype b)
{
word_type i;
if (b & 16)
a >>= 16;
if (b & 8)
a >>= 8;
for (i = (b & 0x7); i > 0; --i)
a >>= 1;
return a;
}
USItype
__lshrsi3 (USItype a, USItype b)
{
word_type i;
if (b & 16)
a >>= 16;
if (b & 8)
a >>= 8;
for (i = (b & 0x7); i > 0; --i)
a >>= 1;
return a;
}

View File

@ -0,0 +1,91 @@
/* Prototypes for exported functions defined in stormy16.c
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of GNU CC.
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.
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.
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, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
extern struct stormy16_stack_layout
stormy16_compute_stack_layout PARAMS((void));
extern void stormy16_expand_prologue PARAMS ((void));
extern void stormy16_expand_epilogue PARAMS ((void));
extern int stormy16_initial_elimination_offset PARAMS ((int, int));
extern int direct_return PARAMS ((void));
extern int stormy16_interrupt_function_p PARAMS ((void));
extern int stormy16_epilogue_uses PARAMS ((int));
#if defined (TREE_CODE)
# if defined (HAVE_MACHINE_MODES)
extern CUMULATIVE_ARGS stormy16_function_arg_advance
PARAMS ((CUMULATIVE_ARGS, enum machine_mode, tree, int));
# endif
extern void stormy16_setup_incoming_varargs
PARAMS ((CUMULATIVE_ARGS, int, tree, int *));
extern tree stormy16_build_va_list PARAMS ((void));
extern void stormy16_encode_section_info PARAMS ((tree));
#endif
#if defined (TREE_CODE) && defined (RTX_CODE)
extern void stormy16_expand_builtin_va_start PARAMS ((int, tree, rtx));
extern rtx stormy16_expand_builtin_va_arg PARAMS ((tree, tree));
extern void stormy16_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern rtx stormy16_function_value PARAMS ((tree, tree));
#endif
#ifdef RTX_CODE
extern void stormy16_emit_cbranch PARAMS ((enum rtx_code, rtx));
extern char * stormy16_output_cbranch_hi PARAMS ((rtx, const char *, int,
rtx));
extern char * stormy16_output_cbranch_si PARAMS ((rtx, const char *, int,
rtx));
extern int stormy16_mode_dependent_address_p PARAMS ((rtx));
extern int stormy16_extra_constraint_p PARAMS ((rtx, int));
extern void stormy16_print_operand PARAMS ((FILE *, rtx, int));
extern void stormy16_print_operand_address PARAMS ((FILE *, rtx));
extern void stormy16_expand_casesi PARAMS ((rtx, rtx, rtx, rtx, rtx));
extern void stormy16_output_addr_vec PARAMS ((FILE *, rtx, rtx));
extern void stormy16_expand_call PARAMS ((rtx, rtx, rtx));
#endif
#if defined (HAVE_MACHINE_MODES) && defined (RTX_CODE)
extern int stormy16_ineqsi_operator PARAMS ((rtx, enum machine_mode));
extern int equality_operator PARAMS ((rtx, enum machine_mode));
extern int inequality_operator PARAMS ((rtx, enum machine_mode));
extern void stormy16_split_cbranch PARAMS ((enum machine_mode,
rtx, rtx, rtx, rtx));
extern int short_memory_operand PARAMS ((rtx, enum machine_mode));
extern enum reg_class stormy16_secondary_reload_class
PARAMS ((enum reg_class, enum machine_mode, rtx));
extern int stormy16_carry_plus_operand PARAMS ((rtx, enum machine_mode));
extern enum reg_class stormy16_preferred_reload_class
PARAMS ((rtx, enum reg_class));
extern int stormy16_legitimate_address_p
PARAMS ((enum machine_mode, rtx, int));
extern void stormy16_split_move PARAMS ((enum machine_mode, rtx, rtx));
extern void stormy16_expand_move PARAMS ((enum machine_mode, rtx, rtx));
extern void stormy16_expand_arith PARAMS ((enum machine_mode, enum rtx_code,
rtx, rtx, rtx, rtx));
extern int shift_operator PARAMS ((rtx, enum machine_mode));
extern const char * stormy16_output_shift PARAMS ((enum machine_mode,
enum rtx_code,
rtx, rtx, rtx));
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,971 @@
;; STORMY16 Machine description template
;; Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
;; Contributed by Red Hat, Inc.
;; This file is part of GNU CC.
;; 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.
;; 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.
;; 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, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;; ::::::::::::::::::::
;; ::
;; :: Attributes
;; ::
;; ::::::::::::::::::::
; Categorize branches for the conditional in the length attribute.
(define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4"
(const_string "notdirectbranch"))
; The length of an instruction, used for branch shortening.
(define_attr "length" ""
(cond
[(eq_attr "branch_class" "br12")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2046))
(lt (minus (match_dup 0) (pc)) (const_int 2048)))
(const_int 2)
(const_int 4))
(eq_attr "branch_class" "bcc12")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
(lt (minus (match_dup 0) (pc)) (const_int 2048)))
(const_int 4)
(const_int 8))
(eq_attr "branch_class" "bcc8p2")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -124))
(lt (minus (match_dup 0) (pc)) (const_int 128)))
(const_int 4)
(const_int 8))
(eq_attr "branch_class" "bcc8p4")
(if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -122))
(lt (minus (match_dup 0) (pc)) (const_int 128)))
(const_int 6)
(const_int 10))]
(const_int 2)))
; The operand which determines the setting of Rpsw.
; The numbers indicate the operand number,
; 'clobber' indicates it is changed in some unspecified way
; 'nop' means it is not changed.
(define_attr "psw_operand" "clobber,nop,0,1,2,3,4" (const_string "0"))
(define_asm_attributes [(set_attr "length" "4")
(set_attr "psw_operand" "clobber")])
;; ::::::::::::::::::::
;; ::
;; :: Moves
;; ::
;; ::::::::::::::::::::
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"{ stormy16_expand_move (QImode, operands[0], operands[1]); DONE; }")
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,Q,r,m,e,e,T,r,S")
(match_operand:QI 1 "general_operand" "r,r,R,e,m,i,i,i,i"))]
""
"@
mov %0,%1
push %1
pop %0
mov.b %0,%1
mov.b %0,%1
mov %0,%1
mov Rx,%1
mov %0,%1
mov.b %0,%1"
[(set_attr_alternative "length"
[(const_int 2)
(const_int 2)
(const_int 2)
(if_then_else (match_operand:QI 0 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(const_int 2)
(const_int 2)
(const_int 4)
(const_int 4)])
(set_attr "psw_operand" "0,nop,nop,0,0,0,nop,0,nop")])
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"{ stormy16_expand_move (HImode, operands[0], operands[1]); DONE; }")
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,Q,r,m,e,e,T,r,S")
(match_operand:HI 1 "general_operand" "r,r,R,e,m,L,L,i,i"))]
""
"@
mov %0,%1
push %1
pop %0
mov.w %0,%1
mov.w %0,%1
mov.w %0,%1
mov.w Rx,%1
mov.w %0,%1
mov.w %0,%1"
[(set_attr_alternative "length"
[(const_int 2)
(const_int 2)
(const_int 2)
(if_then_else (match_operand:QI 0 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 2)
(const_int 4))
(const_int 2)
(const_int 2)
(const_int 4)
(const_int 4)])
(set_attr "psw_operand" "0,nop,nop,0,0,0,nop,0,nop")])
(define_expand "movsi"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"{ stormy16_expand_move (SImode, operands[0], operands[1]); DONE; }")
(define_insn_and_split "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,Q,r,m,e,&e,e,r,S")
(match_operand:SI 1 "general_operand" "r,r,R,e,o, V,L,i,i"))]
""
"#"
"reload_completed"
[(pc)]
"{ stormy16_split_move (SImode, operands[0], operands[1]); DONE; }"
[(set_attr_alternative "length"
[(const_int 4)
(const_int 4)
(const_int 4)
(if_then_else (match_operand:QI 0 "short_memory_operand" "")
(const_int 6)
(const_int 8))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 6)
(const_int 8))
(if_then_else (match_operand:QI 1 "short_memory_operand" "")
(const_int 6)
(const_int 8))
(const_int 4)
(const_int 8)
(const_int 8)])])
;; ::::::::::::::::::::
;; ::
;; :: Conversions
;; ::
;; ::::::::::::::::::::
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI (match_operand:QI 1 "register_operand" "0")))]
""
"cbw %0")
;; ::::::::::::::::::::
;; ::
;; :: Bit field extraction
;; ::
;; ::::::::::::::::::::
;; Extract an unsigned bit field
;(define_insn "extzv"
; [(set (match_operand:SI 0 "register_operand" "=r")
; (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
; (match_operand:SI 2 "const_int_operand" "n")
; (match_operand:SI 3 "const_int_operand" "n")))]
; ""
; "extzv %0,%1,%2,%3"
; [(set_attr "length" "4")])
;; Insert a bit field
;(define_insn "insv"
; [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
; (match_operand:SI 1 "const_int_operand" "n")
; (match_operand:SI 2 "const_int_operand" "n"))
; (match_operand:SI 3 "nonmemory_operand" "ri"))]
; ""
; "insv %0,%1,%2,%3"
; [(set_attr "length" "4")])
;; ::::::::::::::::::::
;; ::
;; :: 16 bit Integer arithmetic
;; ::
;; ::::::::::::::::::::
;; Addition
; Operand 3 is marked earlyclobber because that helps reload
; to generate better code---this pattern will never need the
; carry register as an input, and some output reloads or input
; reloads might need to use it. In fact, without the '&' reload
; will fail in some cases.
(define_insn "addhi3"
[(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "O,P,L,M,Ir,N,i")))
(clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
""
"@
inc %0,%o2
dec %0,%O2
add Rx,%2
sub Rx,#%n2
add %0,%2
sub %0,#%n2
add %0,%2"
[(set_attr "length" "2,2,2,2,2,2,4")])
; Reload can generate addition operations. The SECONDARY_RELOAD_CLASS
; macro causes it to allocate the carry register; this pattern
; shows it how to place the register in RTL to make the addition work.
(define_expand "reload_inhi"
[(parallel [(set (match_operand:HI 0 "register_operand" "=r")
(match_operand:HI 1 "stormy16_carry_plus_operand" ""))
(clobber (match_operand:BI 2 "" "=&y"))])]
""
"if (! rtx_equal_p (operands[0], XEXP (operands[1], 0)))
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0], XEXP (operands[1], 0)));
operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), operands[0],
XEXP (operands[1], 1));
}
")
(define_insn "addchi4"
[(set (match_operand:HI 0 "register_operand" "=T,r,r")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
(match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
(set (match_operand:BI 3 "register_operand" "=y,y,y")
(truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
(zero_extend:SI (match_dup 2)))
(const_int 16))))]
""
"@
add Rx,%2
add %0,%2
add %0,%2"
[(set_attr "length" "2,2,4")])
(define_insn "addchi5"
[(set (match_operand:HI 0 "register_operand" "=T,r,r")
(plus:HI (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
(zero_extend:HI (match_operand:BI 3
"register_operand"
"y,y,y")))
(match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
(set (match_operand:BI 4 "register_operand" "=y,y,y")
(truncate:BI (lshiftrt:SI (plus:SI (plus:SI
(zero_extend:SI (match_dup 1))
(zero_extend:SI (match_dup 3)))
(zero_extend:SI (match_dup 2)))
(const_int 16))))]
""
"@
adc Rx,%2
adc %0,%2
adc %0,%2"
[(set_attr "length" "2,2,4")])
;; Subtraction
; Operand 3 is marked earlyclobber because that helps reload
; to generate better code---this pattern will never need the
; carry register as an input, and some output reloads or input
; reloads might need to use it. In fact, without the '&' reload
; will fail in some cases.
(define_insn "subhi3"
[(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
(minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "O,P,L,M,rI,M,i")))
(clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
""
"@
dec %0,%o2
inc %0,%O2
sub Rx,%2
add Rx,#%n2
sub %0,%2
add %0,#%n2
sub %0,%2"
[(set_attr "length" "2,2,2,2,2,2,4")])
(define_insn "subchi4"
[(set (match_operand:HI 0 "register_operand" "=T,r,r")
(minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
(match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
(set (match_operand:BI 3 "register_operand" "=y,y,y")
(truncate:BI (lshiftrt:SI (minus:SI (zero_extend:SI (match_dup 1))
(zero_extend:SI (match_dup 2)))
(const_int 16))))]
""
"@
sub Rx,%2
sub %0,%2
sub %0,%2"
[(set_attr "length" "2,2,4")])
(define_insn "subchi5"
[(set (match_operand:HI 0 "register_operand" "=T,r,r")
(minus:HI (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
(zero_extend:HI (match_operand:BI 3
"register_operand"
"y,y,y")))
(match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
(set (match_operand:BI 4 "register_operand" "=y,y,y")
(truncate:BI (lshiftrt:SI (minus:SI (minus:SI
(zero_extend:SI (match_dup 1))
(zero_extend:SI (match_dup 3)))
(zero_extend:SI (match_dup 2)))
(const_int 16))))]
""
"@
sbc Rx,%2
sbc %0,%2
sbc %0,%2"
[(set_attr "length" "2,2,4")])
; Basic multiplication
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=a")
(mult:HI (match_operand:HI 1 "register_operand" "%a")
(match_operand:HI 2 "register_operand" "c")))
(clobber (match_scratch:HI 3 "=b"))
]
""
"mul"
[(set_attr "psw_operand" "nop")])
;; Unsigned multiplication producing 64 bit results from 32 bit inputs
; The constraint on operand 0 is 't' because it is actually two regs
; long, and both regs must match the constraint.
(define_insn "umulhisi3"
[(set (match_operand:SI 0 "register_operand" "=t")
(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%a"))
(zero_extend:SI (match_operand:HI 2 "register_operand" "c"))))
]
""
"mul"
[(set_attr "psw_operand" "nop")])
;; Unsigned division giving both quotient and remainder
(define_insn "udivmodhi4"
[(set (match_operand:HI 0 "register_operand" "=a")
(div:HI (match_operand:HI 1 "register_operand" "a")
(match_operand:HI 2 "register_operand" "c")))
(set (match_operand:HI 3 "register_operand" "=b")
(mod:HI (match_dup 1)
(match_dup 2)))]
""
"div"
[(set_attr "psw_operand" "nop")])
;; Negation
(define_expand "neghi2"
[(set (match_operand:HI 0 "register_operand" "")
(not:HI (match_operand:HI 1 "register_operand" "")))
(parallel [(set (match_dup 0) (plus:HI (match_dup 0) (const_int 1)))
(clobber (match_scratch:BI 3 ""))])]
""
"")
;; ::::::::::::::::::::
;; ::
;; :: 16 bit Integer Shifts and Rotates
;; ::
;; ::::::::::::::::::::
;; Arithmetic Shift Left
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(ashift:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "ri")))
(clobber (match_scratch:BI 3 "=y"))]
""
"shl %0,%2")
;; Arithmetic Shift Right
(define_insn "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "ri")))
(clobber (match_scratch:BI 3 "=y"))]
""
"asr %0,%2")
;; Logical Shift Right
(define_insn "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "ri")))
(clobber (match_scratch:BI 3 "=y"))]
""
"shr %0,%2")
;; ::::::::::::::::::::
;; ::
;; :: 16 Bit Integer Logical operations
;; ::
;; ::::::::::::::::::::
;; Logical AND, 16 bit integers
(define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "L,r,K,i")))]
""
"@
and Rx,%2
and %0,%2
clr1 %0,%B2
and %0,%2"
[(set_attr "length" "2,2,2,4")])
;; Inclusive OR, 16 bit integers
(define_insn "iorhi3"
[(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
(match_operand:HI 2 "nonmemory_operand" "L,r,J,i")))]
""
"@
or Rx,%2
or %0,%2
set1 %0,%B2
or %0,%2"
[(set_attr "length" "2,2,2,4")])
;; Exclusive OR, 16 bit integers
(define_insn "xorhi3"
[(set (match_operand:HI 0 "register_operand" "=T,r,r")
(xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
(match_operand:HI 2 "nonmemory_operand" "L,r,i")))]
""
"@
xor Rx,%2
xor %0,%2
xor %0,%2"
[(set_attr "length" "2,2,4")])
;; One's complement, 16 bit integers
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(not:HI (match_operand:HI 1 "register_operand" "0")))]
""
"not %0")
;; ::::::::::::::::::::
;; ::
;; :: 32 bit Integer arithmetic
;; ::
;; ::::::::::::::::::::
;; Addition
(define_insn_and_split "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "ri")))
(clobber (match_scratch:BI 3 "=y"))]
""
"#"
"reload_completed"
[(pc)]
"{ stormy16_expand_arith (SImode, PLUS, operands[0], operands[1],
operands[2], operands[3]); DONE; } "
[(set_attr "length" "4")])
;; Subtraction
(define_insn_and_split "subsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "ri")))
(clobber (match_scratch:BI 3 "=y"))]
""
"#"
"reload_completed"
[(pc)]
"{ stormy16_expand_arith (SImode, MINUS, operands[0], operands[1],
operands[2], operands[3]); DONE; } "
[(set_attr "length" "4")])
(define_expand "negsi2"
[(set (match_operand:SI 0 "register_operand" "")
(neg:SI (match_operand:SI 1 "register_operand" "")))]
""
"{ stormy16_expand_arith (SImode, NEG, operands[0], const0_rtx,
operands[1], gen_reg_rtx (BImode)); DONE; }")
;; ::::::::::::::::::::
;; ::
;; :: 32 bit Integer Shifts and Rotates
;; ::
;; ::::::::::::::::::::
;; Arithmetic Shift Left
(define_expand "ashlsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_dup 3))
(clobber (match_dup 4))])]
""
" if (! const_int_operand (operands[2], SImode)) FAIL;
operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
;; Arithmetic Shift Right
(define_expand "ashrsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_dup 3))
(clobber (match_dup 4))])]
""
" if (! const_int_operand (operands[2], SImode)) FAIL;
operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
;; Logical Shift Right
(define_expand "lshrsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_dup 3))
(clobber (match_dup 4))])]
""
" if (! const_int_operand (operands[2], SImode)) FAIL;
operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
(define_insn "*shiftsi"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 5 "shift_operator"
[(match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "const_int_operand" "U,n")]))
(clobber (match_operand:BI 3 "register_operand" "=y,y"))
(clobber (match_operand:HI 4 "" "=X,r"))]
""
"* return stormy16_output_shift (SImode, GET_CODE (operands[5]),
operands[0], operands[2], operands[4]);"
[(set_attr "length" "6,10")
(set_attr "psw_operand" "clobber,clobber")])
;; ::::::::::::::::::::
;; ::
;; :: Comparisons
;; ::
;; ::::::::::::::::::::
;; Note, we store the operands in the comparison insns, and use them later
;; when generating the branch or scc operation.
;; First the routines called by the machine independent part of the compiler
(define_expand "cmphi"
[(set (cc0)
(compare (match_operand:HI 0 "register_operand" "")
(match_operand:HI 1 "nonmemory_operand" "")))]
""
"
{
stormy16_compare_op0 = operands[0];
stormy16_compare_op1 = operands[1];
DONE;
}")
; There are no real SImode comparisons, but some can be emulated
; by performing a SImode subtract and looking at the condition flags.
(define_expand "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "nonmemory_operand" "")))]
""
"
{
stormy16_compare_op0 = operands[0];
stormy16_compare_op1 = operands[1];
DONE;
}")
;; ::::::::::::::::::::
;; ::
;; :: Branches
;; ::
;; ::::::::::::::::::::
(define_expand "beq"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (EQ, operands[0]); DONE; }")
(define_expand "bne"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (NE, operands[0]); DONE; }")
(define_expand "bge"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (GE, operands[0]); DONE; }")
(define_expand "bgt"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (GT, operands[0]); DONE; }")
(define_expand "ble"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (LE, operands[0]); DONE; }")
(define_expand "blt"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (LT, operands[0]); DONE; }")
(define_expand "bgeu"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (GEU, operands[0]); DONE; }")
(define_expand "bgtu"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (GTU, operands[0]); DONE; }")
(define_expand "bleu"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (LEU, operands[0]); DONE; }")
(define_expand "bltu"
[(use (match_operand 0 "" ""))]
""
"{ stormy16_emit_cbranch (LTU, operands[0]); DONE; }")
(define_insn "*cbranchhi"
[(set (pc)
(if_then_else (match_operator:HI 1 "comparison_operator"
[(match_operand:HI 2 "nonmemory_operand"
"r,e,L")
(match_operand:HI 3 "nonmemory_operand"
"r,L,e")])
(label_ref (match_operand 0 "" ""))
(pc)))
(clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
""
"*
{
return stormy16_output_cbranch_hi (operands[1], \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "bcc12")
(set_attr "psw_operand" "0,0,1")])
(define_insn "*cbranchhi_neg"
[(set (pc)
(if_then_else (match_operator:HI 1 "comparison_operator"
[(match_operand:HI 2 "nonmemory_operand"
"r,e,L")
(match_operand:HI 3 "nonmemory_operand"
"r,L,e")])
(pc)
(label_ref (match_operand 0 "" ""))))
(clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
""
"*
{
return stormy16_output_cbranch_hi (operands[1], \"%l0\", 1, insn);
}"
[(set_attr "branch_class" "bcc12")
(set_attr "psw_operand" "0,0,1")])
(define_insn "*eqbranchsi"
[(set (pc)
(if_then_else (match_operator:SI 1 "equality_operator"
[(match_operand:SI 2 "register_operand"
"+r")
(const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))
;; Although I would greatly like the 'match_dup' in the following line
;; to actually be a register constraint, there is (at the time of writing) no
;; way for reload to insert an output reload on the edges out of a branch.
;; If reload is fixed to use insert_insn_on_edge, this can be changed.
(clobber (match_dup 2))]
""
"*
{
return stormy16_output_cbranch_si (operands[1], \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "bcc8p2")
(set_attr "psw_operand" "clobber")])
(define_insn_and_split "*ineqbranchsi"
[(set (pc)
(if_then_else (match_operator:SI 1 "stormy16_ineqsi_operator"
[(match_operand:SI 2 "register_operand"
"+r")
(match_operand:SI 3 "nonmemory_operand"
"ri")])
(label_ref (match_operand 0 "" ""))
(pc)))
;; Although I would greatly like the 'match_dup' in the following line
;; to actually be a register constraint, there is (at the time of writing) no
;; way for reload to insert an output reload on the edges out of a branch.
;; If reload is fixed to use insert_insn_on_edge, this can be changed,
;; preferably to a 'minus' operand that explains the actual operation, like:
; (set (match_operand 5 "register_operand" "=2")
; (minus:SI (match_operand 6 "register_operand" "2")
; (match_operand 7 "register_operand" "3")))
(clobber (match_dup 2))
(clobber (match_operand:BI 4 "" "=&y"))]
""
"#"
"reload_completed"
[(pc)]
"{ stormy16_split_cbranch (SImode, operands[0], operands[1], operands[2],
operands[4]); DONE; }"
[(set_attr "length" "8")])
(define_insn "*ineqbranch_1"
[(set (pc)
(if_then_else (match_operator:HI 5 "stormy16_ineqsi_operator"
[(minus:HI (match_operand:HI 1 "register_operand"
"T,r,r")
(zero_extend:HI (match_operand:BI 4
"register_operand"
"y,y,y")))
(match_operand:HI 3 "nonmemory_operand" "L,Ir,i")])
(label_ref (match_operand 0 "" ""))
(pc)))
(set (match_operand:HI 2 "register_operand" "=2,2,2")
(minus:HI (minus:HI (match_dup 1) (zero_extend:HI (match_dup 4)))
(match_dup 3)))
(clobber (match_operand:BI 6 "" "=y,y,y"))]
""
"*
{
return stormy16_output_cbranch_si (operands[5], \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4")
(set_attr "psw_operand" "2,2,2")])
;; ::::::::::::::::::::
;; ::
;; :: Call and branch instructions
;; ::
;; ::::::::::::::::::::
;; Subroutine call instruction returning no value. Operand 0 is the function
;; to call; operand 1 is the number of bytes of arguments pushed (in mode
;; `SImode', except it is normally a `const_int'); operand 2 is the number of
;; registers used as operands.
;; On most machines, operand 2 is not actually stored into the RTL pattern. It
;; is supplied for the sake of some RISC machines which need to put this
;; information into the assembler code; they can put it in the RTL instead of
;; operand 1.
(define_expand "call"
[(call (match_operand:HI 0 "memory_operand" "m")
(match_operand 1 "" ""))
(use (match_operand 2 "immediate_operand" ""))]
""
"stormy16_expand_call (NULL_RTX, operands[0], operands[1]); DONE;")
;; Subroutine call instruction returning a value. Operand 0 is the hard
;; register in which the value is returned. There are three more operands, the
;; same as the three operands of the `call' instruction (but with numbers
;; increased by one).
;; Subroutines that return `BLKmode' objects use the `call' insn.
(define_expand "call_value"
[(set (match_operand 0 "register_operand" "=r")
(call (match_operand:HI 1 "memory_operand" "m")
(match_operand:SI 2 "" "")))
(use (match_operand 3 "immediate_operand" ""))]
""
"stormy16_expand_call (operands[0], operands[1], operands[2]); DONE;")
(define_insn "*call_internal"
[(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
(match_operand 1 "" ""))
(use (match_operand:HI 2 "nonmemory_operand" "X,t"))]
""
"@
callf %C0
call %2,%0"
[(set_attr "length" "4,2")
(set_attr "psw_operand" "clobber")])
(define_insn "*call_value_internal"
[(set (match_operand 3 "register_operand" "=r,r")
(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
(match_operand 1 "" "")))
(use (match_operand:HI 2 "nonmemory_operand" "X,t"))]
""
"@
callf %C0
call %2,%0"
[(set_attr "length" "4,2")
(set_attr "psw_operand" "clobber")])
;; Subroutine return
(define_expand "return"
[(return)]
"direct_return()"
"")
(define_insn "return_internal"
[(return)]
""
"ret"
[(set_attr "psw_operand" "nop")])
(define_insn "return_internal_interrupt"
[(return)
(unspec_volatile [(const_int 0)] 1)]
""
"iret"
[(set_attr "psw_operand" "clobber")])
;; Normal unconditional jump
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
"*
{
return stormy16_output_cbranch_hi (NULL_RTX, \"%l0\", 0, insn);
}"
[(set_attr "branch_class" "br12")
(set_attr "psw_operand" "nop")])
;; Indirect jump through a register
(define_expand "indirect_jump"
[(set (match_dup 1) (const_int 0))
(parallel [(set (pc) (match_operand:HI 0 "register_operand" "r"))
(use (match_dup 1))])]
""
"operands[1] = gen_reg_rtx (HImode);")
(define_insn ""
[(set (pc) (match_operand:HI 0 "register_operand" "r"))
(use (match_operand:HI 1 "register_operand" "t"))]
""
"jmp %1,%0"
[(set_attr "length" "4")
(set_attr "psw_operand" "nop")])
;; Table-based switch statements.
(define_expand "casesi"
[(use (match_operand:SI 0 "register_operand" ""))
(use (match_operand:SI 1 "immediate_operand" ""))
(use (match_operand:SI 2 "immediate_operand" ""))
(use (label_ref (match_operand 3 "" "")))
(use (label_ref (match_operand 4 "" "")))]
""
"
{
stormy16_expand_casesi (operands[0], operands[1], operands[2],
operands[3], operands[4]);
DONE;
}")
(define_insn "tablejump_pcrel"
[(set (pc) (plus:HI (pc) (match_operand:HI 0 "register_operand" "r")))
(use (label_ref:SI (match_operand 1 "" "")))]
""
"br %0"
[(set_attr "psw_operand" "nop")])
;; ::::::::::::::::::::
;; ::
;; :: Prologue and Epilogue instructions
;; ::
;; ::::::::::::::::::::
;; Called after register allocation to add any instructions needed for the
;; prologue. Using a prologue insn is favored compared to putting all of the
;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
;; to intermix instructions with the saves of the caller saved registers. In
;; some cases, it might be necessary to emit a barrier instruction as the last
;; insn to prevent such scheduling.
(define_expand "prologue"
[(const_int 1)]
""
"
{
stormy16_expand_prologue ();
DONE;
}")
;; Called after register allocation to add any instructions needed for the
;; epilogue. Using a epilogue insn is favored compared to putting all of the
;; instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler
;; to intermix instructions with the restires of the caller saved registers.
;; In some cases, it might be necessary to emit a barrier instruction as the
;; first insn to prevent such scheduling.
(define_expand "epilogue"
[(const_int 2)]
""
"
{
stormy16_expand_epilogue ();
DONE;
}")
;; ::::::::::::::::::::
;; ::
;; :: Miscellaneous instructions
;; ::
;; ::::::::::::::::::::
;; No operation, needed in case the user uses -g but not -O.
(define_insn "nop"
[(const_int 0)]
""
"nop"
[(set_attr "psw_operand" "nop")])
;; Pseudo instruction that prevents the scheduler from moving code above this
;; point.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
""
""
[(set_attr "length" "0")
(set_attr "psw_operand" "nop")])

View File

@ -0,0 +1,18 @@
# -*- makefile -*-
# SImode routines
LIB2FUNCS_EXTRA = \
$(srcdir)/config/stormy16/stormy16-lib2.c
# floating point emulation libraries
FPBIT = fp-bit.c
DPBIT = dp-bit.c
fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
cat $(srcdir)/config/fp-bit.c > dp-bit.c