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:
parent
d3fe11e624
commit
4b58290fe6
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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")])
|
|
@ -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
|
Loading…
Reference in New Issue