diff options
author | Geoffrey Keating <geoffk@redhat.com> | 2001-08-25 17:14:36 +0000 |
---|---|---|
committer | Geoffrey Keating <geoffk@gcc.gnu.org> | 2001-08-25 17:14:36 +0000 |
commit | 4b58290fe6d467cf8d1c4f72e35c308218728b3b (patch) | |
tree | fbf9af098961c2e4bb58532af29c22fbd8e437a0 | |
parent | d3fe11e62408ef839371ae20b5c666219de209a9 (diff) | |
download | gcc-4b58290fe6d467cf8d1c4f72e35c308218728b3b.zip gcc-4b58290fe6d467cf8d1c4f72e35c308218728b3b.tar.gz gcc-4b58290fe6d467cf8d1c4f72e35c308218728b3b.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config.gcc | 4 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy-abi | 153 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16-lib2.c | 142 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16-protos.h | 91 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16.c | 1873 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16.h | 5355 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16.md | 971 | ||||
-rw-r--r-- | gcc/config/stormy16/t-stormy16 | 18 |
9 files changed, 8618 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4786c2..f3ad806 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config.gcc b/gcc/config.gcc index 6a54455..a6d89ae 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -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 diff --git a/gcc/config/stormy16/stormy-abi b/gcc/config/stormy16/stormy-abi new file mode 100644 index 0000000..78ed4b0 --- /dev/null +++ b/gcc/config/stormy16/stormy-abi @@ -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. diff --git a/gcc/config/stormy16/stormy16-lib2.c b/gcc/config/stormy16/stormy16-lib2.c new file mode 100644 index 0000000..7038624 --- /dev/null +++ b/gcc/config/stormy16/stormy16-lib2.c @@ -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; +} diff --git a/gcc/config/stormy16/stormy16-protos.h b/gcc/config/stormy16/stormy16-protos.h new file mode 100644 index 0000000..39a8453 --- /dev/null +++ b/gcc/config/stormy16/stormy16-protos.h @@ -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 + diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c new file mode 100644 index 0000000..c29bc08 --- /dev/null +++ b/gcc/config/stormy16/stormy16.c @@ -0,0 +1,1873 @@ +/* Stormy16 target functions. + Copyright (C) 1997, 1998, 1999, 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. */ + +#include "config.h" +#include "system.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "real.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "recog.h" +#include "toplev.h" +#include "obstack.h" +#include "tree.h" +#include "expr.h" +#include "optabs.h" +#include "output.h" +#include "except.h" +#include "function.h" +#include "target.h" +#include "target-def.h" +#include "tm_p.h" + +static rtx emit_addhi3_postreload PARAMS ((rtx, rtx, rtx)); + +/* Define the information needed to generate branch and scc insns. This is + stored from the compare operation. */ +struct rtx_def * stormy16_compare_op0; +struct rtx_def * stormy16_compare_op1; + +/* Return 1 if this is a LT, GE, LTU, or GEU operator. */ + +int +stormy16_ineqsi_operator (op, mode) + register rtx op; + enum machine_mode mode; +{ + enum rtx_code code = GET_CODE (op); + + return ((mode == VOIDmode || GET_MODE (op) == mode) + && (code == LT || code == GE || code == LTU || code == GEU)); +} + +/* Return 1 if this is an EQ or NE operator. */ + +int +equality_operator (op, mode) + register rtx op; + enum machine_mode mode; +{ + return ((mode == VOIDmode || GET_MODE (op) == mode) + && (GET_CODE (op) == EQ || GET_CODE (op) == NE)); +} + +/* Return 1 if this is a comparison operator but not an EQ or NE operator. */ + +int +inequality_operator (op, mode) + register rtx op; + enum machine_mode mode; +{ + return comparison_operator (op, mode) && ! equality_operator (op, mode); +} + +/* Branches are handled as follows: + + 1. HImode compare-and-branches. The machine supports these + natively, so the appropriate pattern is emitted directly. + + 2. SImode EQ and NE. These are emitted as pairs of HImode + compare-and-branches. + + 3. SImode LT, GE, LTU and GEU. These are emitted as a sequence + of a SImode subtract followed by a branch (not a compare-and-branch), + like this: + sub + sbc + blt + + 4. SImode GT, LE, GTU, LEU. These are emitted as a sequence like: + sub + sbc + blt + or + bne +*/ + +/* Emit a branch of kind CODE to location LOC. */ + +void +stormy16_emit_cbranch (code, loc) + enum rtx_code code; + rtx loc; +{ + rtx op0 = stormy16_compare_op0; + rtx op1 = stormy16_compare_op1; + rtx condition_rtx, loc_ref, branch, cy_clobber; + rtvec vec; + enum machine_mode mode; + + mode = GET_MODE (op0); + if (mode != HImode && mode != SImode) + abort (); + + if (mode == SImode + && (code == GT || code == LE || code == GTU || code == LEU)) + { + int unsigned_p = (code == GTU || code == LEU); + int gt_p = (code == GT || code == GTU); + rtx lab; + + if (gt_p) + lab = gen_label_rtx (); + stormy16_emit_cbranch (unsigned_p ? LTU : LT, gt_p ? lab : loc); + /* This should be generated as a comparison against the temporary + created by the previous insn, but reload can't handle that. */ + stormy16_emit_cbranch (gt_p ? NE : EQ, loc); + if (gt_p) + emit_label (lab); + return; + } + else if (mode == SImode + && (code == NE || code == EQ) + && op1 != const0_rtx) + { + rtx lab; + int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; + int i; + + if (code == EQ) + lab = gen_label_rtx (); + + for (i = 0; i < num_words - 1; i++) + { + stormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, + i * UNITS_PER_WORD); + stormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, + i * UNITS_PER_WORD); + stormy16_emit_cbranch (NE, code == EQ ? lab : loc); + } + stormy16_compare_op0 = simplify_gen_subreg (word_mode, op0, mode, + i * UNITS_PER_WORD); + stormy16_compare_op1 = simplify_gen_subreg (word_mode, op1, mode, + i * UNITS_PER_WORD); + stormy16_emit_cbranch (code, loc); + + if (code == EQ) + emit_label (lab); + return; + } + + /* We can't allow reload to try to generate any reload after a branch, + so when some register must match we must make the temporary ourselves. */ + if (mode != HImode) + { + rtx tmp; + tmp = gen_reg_rtx (mode); + emit_move_insn (tmp, op0); + op0 = tmp; + } + + condition_rtx = gen_rtx (code, mode, op0, op1); + loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc); + branch = gen_rtx_SET (VOIDmode, pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx, + loc_ref, pc_rtx)); + + cy_clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (BImode)); + + if (mode == HImode) + vec = gen_rtvec (2, branch, cy_clobber); + else if (code == NE || code == EQ) + vec = gen_rtvec (2, branch, gen_rtx_CLOBBER (VOIDmode, op0)); + else + { + rtx sub; +#if 0 + sub = gen_rtx_SET (VOIDmode, op0, gen_rtx_MINUS (SImode, op0, op1)); +#else + sub = gen_rtx_CLOBBER (SImode, op0); +#endif + vec = gen_rtvec (3, branch, sub, cy_clobber); + } + + emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec)); +} + +/* Take a SImode conditional branch, one of GT/LE/GTU/LEU, and split + the arithmetic operation. Most of the work is done by + stormy16_expand_arith. */ + +void +stormy16_split_cbranch (mode, label, comparison, dest, carry) + enum machine_mode mode; + rtx label; + rtx comparison; + rtx dest; + rtx carry; +{ + rtx op0 = XEXP (comparison, 0); + rtx op1 = XEXP (comparison, 1); + rtx seq; + rtx compare; + + start_sequence (); + stormy16_expand_arith (mode, COMPARE, dest, op0, op1, carry); + seq = gen_sequence (); + end_sequence (); + compare = SET_SRC (XVECEXP (PATTERN (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1)), + 0, 0)); + PUT_CODE (XEXP (compare, 0), GET_CODE (comparison)); + XEXP (compare, 1) = gen_rtx_LABEL_REF (VOIDmode, label); + emit_insn (seq); +} + + +/* Return the string to output a conditional branch to LABEL, which is + the operand number of the label. + + OP is the conditional expression, or NULL for branch-always. + + REVERSED is non-zero if we should reverse the sense of the comparison. + + INSN is the insn. */ + +char * +stormy16_output_cbranch_hi (op, label, reversed, insn) + rtx op; + const char * label; + int reversed; + rtx insn; +{ + static char string[64]; + int need_longbranch = (op != NULL_RTX + ? get_attr_length (insn) == 8 + : get_attr_length (insn) == 4); + int really_reversed = reversed ^ need_longbranch; + const char *ccode; + const char *template; + const char *operands; + enum rtx_code code; + + if (! op) + { + if (need_longbranch) + ccode = "jmpf"; + else + ccode = "br"; + sprintf (string, "%s %s", ccode, label); + return string; + } + + code = GET_CODE (op); + + if (GET_CODE (XEXP (op, 0)) != REG) + { + code = swap_condition (code); + operands = "%3,%2"; + } + else + operands = "%2,%3"; + + /* Work out which way this really branches. */ + if (really_reversed) + code = reverse_condition (code); + + switch (code) + { + case EQ: ccode = "z"; break; + case NE: ccode = "nz"; break; + case GE: ccode = "ge"; break; + case LT: ccode = "lt"; break; + case GT: ccode = "gt"; break; + case LE: ccode = "le"; break; + case GEU: ccode = "nc"; break; + case LTU: ccode = "c"; break; + case GTU: ccode = "hi"; break; + case LEU: ccode = "ls"; break; + + default: + abort (); + } + + if (need_longbranch) + template = "b%s %s,.+8 | jmpf %s"; + else + template = "b%s %s,%s"; + sprintf (string, template, ccode, operands, label); + + return string; +} + +/* Return the string to output a conditional branch to LABEL, which is + the operand number of the label, but suitable for the tail of a + SImode branch. + + OP is the conditional expression (OP is never NULL_RTX). + + REVERSED is non-zero if we should reverse the sense of the comparison. + + INSN is the insn. */ + +char * +stormy16_output_cbranch_si (op, label, reversed, insn) + rtx op; + const char * label; + int reversed; + rtx insn; +{ + static char string[64]; + int need_longbranch = get_attr_length (insn) >= 8; + int really_reversed = reversed ^ need_longbranch; + const char *ccode; + const char *template; + char prevop[16]; + enum rtx_code code; + + code = GET_CODE (op); + + /* Work out which way this really branches. */ + if (really_reversed) + code = reverse_condition (code); + + switch (code) + { + case EQ: ccode = "z"; break; + case NE: ccode = "nz"; break; + case GE: ccode = "ge"; break; + case LT: ccode = "lt"; break; + case GEU: ccode = "nc"; break; + case LTU: ccode = "c"; break; + + /* The missing codes above should never be generated. */ + default: + abort (); + } + + switch (code) + { + case EQ: case NE: + { + int regnum; + + if (GET_CODE (XEXP (op, 0)) != REG) + abort (); + + regnum = REGNO (XEXP (op, 0)); + sprintf (prevop, "or %s,%s", reg_names[regnum], reg_names[regnum+1]); + } + break; + + case GE: case LT: case GEU: case LTU: + strcpy (prevop, "sbc %2,%3"); + break; + + default: + abort (); + } + + if (need_longbranch) + template = "%s | b%s .+6 | jmpf %s"; + else + template = "%s | b%s %s"; + sprintf (string, template, prevop, ccode, label); + + return string; +} + +/* Many machines have some registers that cannot be copied directly to or from + memory or even from other types of registers. An example is the `MQ' + register, which on most machines, can only be copied to or from general + registers, but not memory. Some machines allow copying all registers to and + from memory, but require a scratch register for stores to some memory + locations (e.g., those with symbolic address on the RT, and those with + certain symbolic address on the Sparc when compiling PIC). In some cases, + both an intermediate and a scratch register are required. + + You should define these macros to indicate to the reload phase that it may + need to allocate at least one register for a reload in addition to the + register to contain the data. Specifically, if copying X to a register + CLASS in MODE requires an intermediate register, you should define + `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of + whose registers can be used as intermediate registers or scratch registers. + + If copying a register CLASS in MODE to X requires an intermediate or scratch + register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the + largest register class required. If the requirements for input and output + reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used + instead of defining both macros identically. + + The values returned by these macros are often `GENERAL_REGS'. Return + `NO_REGS' if no spare register is needed; i.e., if X can be directly copied + to or from a register of CLASS in MODE without requiring a scratch register. + Do not define this macro if it would always return `NO_REGS'. + + If a scratch register is required (either with or without an intermediate + register), you should define patterns for `reload_inM' or `reload_outM', as + required.. These patterns, which will normally be implemented with a + `define_expand', should be similar to the `movM' patterns, except that + operand 2 is the scratch register. + + Define constraints for the reload register and scratch register that contain + a single register class. If the original reload register (whose class is + CLASS) can meet the constraint given in the pattern, the value returned by + these macros is used for the class of the scratch register. Otherwise, two + additional reload registers are required. Their classes are obtained from + the constraints in the insn pattern. + + X might be a pseudo-register or a `subreg' of a pseudo-register, which could + either be in a hard register or in memory. Use `true_regnum' to find out; + it will return -1 if the pseudo is in memory and the hard register number if + it is in a register. + + These macros should not be used in the case where a particular class of + registers can only be copied to memory and not to another class of + registers. In that case, secondary reload registers are not needed and + would not be helpful. Instead, a stack location must be used to perform the + copy and the `movM' pattern should use memory as a intermediate storage. + This case often occurs between floating-point and general registers. */ + +enum reg_class +stormy16_secondary_reload_class (class, mode, x) + enum reg_class class; + enum machine_mode mode; + rtx x; +{ + /* This chip has the interesting property that only the first eight + registers can be moved to/from memory. */ + if ((GET_CODE (x) == MEM + || ((GET_CODE (x) == SUBREG || GET_CODE (x) == REG) + && (true_regnum (x) == -1 + || true_regnum (x) >= FIRST_PSEUDO_REGISTER))) + && ! reg_class_subset_p (class, EIGHT_REGS)) + return EIGHT_REGS; + + /* When reloading a PLUS, the carry register will be required + unless the inc or dec instructions can be used. */ + if (stormy16_carry_plus_operand (x, mode)) + return CARRY_REGS; + + return NO_REGS; +} + +/* Recognise a PLUS that needs the carry register. */ +int +stormy16_carry_plus_operand (x, mode) + rtx x; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == CONST_INT + && (INTVAL (XEXP (x, 1)) < -4 || INTVAL (XEXP (x, 1)) > 4)); +} + + +enum reg_class +stormy16_preferred_reload_class (x, class) + enum reg_class class; + rtx x; +{ + if (class == GENERAL_REGS + && GET_CODE (x) == MEM) + return EIGHT_REGS; + + return class; +} + +#define LEGITIMATE_ADDRESS_INTEGER_P(X, OFFSET) \ + (GET_CODE (X) == CONST_INT \ + && (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 2048) < 4096) + +#define LEGITIMATE_ADDRESS_CONST_INT_P(X, OFFSET) \ + (GET_CODE (X) == CONST_INT \ + && INTVAL (X) + (OFFSET) >= 0 \ + && INTVAL (X) + (OFFSET) < 0x8000 \ + && (INTVAL (X) + (OFFSET) < 0x100 || INTVAL (X) + (OFFSET) >= 0x7F00)) + +int +stormy16_legitimate_address_p (mode, x, strict) + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx x; + int strict; +{ + if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0)) + return 1; + + if (GET_CODE (x) == PLUS + && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 0)) + x = XEXP (x, 0); + + if (GET_CODE (x) == POST_INC + || GET_CODE (x) == PRE_DEC) + x = XEXP (x, 0); + + if (GET_CODE (x) == REG && REGNO_OK_FOR_BASE_P (REGNO (x)) + && (! strict || REGNO (x) < FIRST_PSEUDO_REGISTER)) + return 1; + + return 0; +} + +/* Return nonzero if memory address X (an RTX) can have different + meanings depending on the machine mode of the memory reference it + is used for or if the address is valid for some modes but not + others. + + Autoincrement and autodecrement addresses typically have mode-dependent + effects because the amount of the increment or decrement is the size of the + operand being addressed. Some machines have other mode-dependent addresses. + Many RISC machines have no mode-dependent addresses. + + You may assume that ADDR is a valid address for the machine. + + On this chip, this is true if the address is valid with an offset + of 0 but not of 6, because in that case it cannot be used as an + address for DImode or DFmode, or if the address is a post-increment + or pre-decrement address. */ +int +stormy16_mode_dependent_address_p (x) + rtx x; +{ + if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0) + && ! LEGITIMATE_ADDRESS_CONST_INT_P (x, 6)) + return 1; + + if (GET_CODE (x) == PLUS + && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 0) + && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (x, 1), 6)) + return 1; + + if (GET_CODE (x) == PLUS) + x = XEXP (x, 0); + + if (GET_CODE (x) == POST_INC + || GET_CODE (x) == PRE_DEC) + return 1; + + return 0; +} + +/* A C expression that defines the optional machine-dependent constraint + letters (`Q', `R', `S', `T', `U') that can be used to segregate specific + types of operands, usually memory references, for the target machine. + Normally this macro will not be defined. If it is required for a particular + target machine, it should return 1 if VALUE corresponds to the operand type + represented by the constraint letter C. If C is not defined as an extra + constraint, the value returned should be 0 regardless of VALUE. */ +int +stormy16_extra_constraint_p (x, c) + rtx x; + int c; +{ + switch (c) + { + /* 'Q' is for pushes. */ + case 'Q': + return (GET_CODE (x) == MEM + && GET_CODE (XEXP (x, 0)) == POST_INC + && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx); + + /* 'R' is for pops. */ + case 'R': + return (GET_CODE (x) == MEM + && GET_CODE (XEXP (x, 0)) == PRE_DEC + && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx); + + /* 'S' is for immediate memory addresses. */ + case 'S': + return (GET_CODE (x) == MEM + && GET_CODE (XEXP (x, 0)) == CONST_INT + && stormy16_legitimate_address_p (VOIDmode, XEXP (x, 0), 0)); + + /* 'T' is for Rx. */ + case 'T': + /* Not implemented yet. */ + return 0; + + /* 'U' is for CONST_INT values not between 2 and 15 inclusive, + for allocating a scratch register for 32-bit shifts. */ + case 'U': + return (GET_CODE (x) == CONST_INT + && (INTVAL (x) < 2 || INTVAL (x) > 15)); + + default: + return 0; + } +} + +int +short_memory_operand (x, mode) + rtx x; + enum machine_mode mode; +{ + if (! memory_operand (x, mode)) + return 0; + return (GET_CODE (XEXP (x, 0)) != PLUS); +} + +/* Splitter for the 'move' patterns, for modes not directly implemeted + by hardware. Emit insns to copy a value of mode MODE from SRC to + DEST. + + This function is only called when reload_completed. + */ + +void +stormy16_split_move (mode, dest, src) + enum machine_mode mode; + rtx dest; + rtx src; +{ + int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; + int direction, end, i; + int src_modifies = 0; + int dest_modifies = 0; + int src_volatile = 0; + int dest_volatile = 0; + rtx mem_operand; + + /* Check initial conditions. */ + if (! reload_completed + || mode == QImode || mode == HImode + || ! nonimmediate_operand (dest, mode) + || ! general_operand (src, mode)) + abort (); + + /* This case is not supported below, and shouldn't be generated. */ + if (GET_CODE (dest) == MEM + && GET_CODE (src) == MEM) + abort (); + + /* This case is very very bad after reload, so trap it now. */ + if (GET_CODE (dest) == SUBREG + || GET_CODE (src) == SUBREG) + abort (); + + /* The general idea is to copy by words, offsetting the source and + destination. Normally the least-significant word will be copied + first, but for pre-dec operations it's better to copy the + most-significant word first. Only one operand can be a pre-dec + or post-inc operand. + + It's also possible that the copy overlaps so that the direction + must be reversed. */ + direction = 1; + + if (GET_CODE (dest) == MEM) + { + mem_operand = XEXP (dest, 0); + dest_modifies = side_effects_p (mem_operand); + dest_volatile = MEM_VOLATILE_P (dest); + if (dest_volatile) + { + dest = copy_rtx (dest); + MEM_VOLATILE_P (dest) = 0; + } + } + else if (GET_CODE (src) == MEM) + { + mem_operand = XEXP (src, 0); + src_modifies = side_effects_p (mem_operand); + src_volatile = MEM_VOLATILE_P (src); + if (src_volatile) + { + src = copy_rtx (src); + MEM_VOLATILE_P (src) = 0; + } + } + else + mem_operand = NULL_RTX; + + if (mem_operand == NULL_RTX) + { + if (GET_CODE (src) == REG + && GET_CODE (dest) == REG + && reg_overlap_mentioned_p (dest, src) + && REGNO (dest) > REGNO (src)) + direction = -1; + } + else if (GET_CODE (mem_operand) == PRE_DEC + || (GET_CODE (mem_operand) == PLUS + && GET_CODE (XEXP (mem_operand, 0)) == PRE_DEC)) + direction = -1; + else if (GET_CODE (src) == MEM + && reg_overlap_mentioned_p (dest, src)) + { + int regno; + if (GET_CODE (dest) != REG) + abort (); + regno = REGNO (dest); + + if (! refers_to_regno_p (regno, regno + num_words, mem_operand, 0)) + abort (); + + if (refers_to_regno_p (regno, regno + 1, mem_operand, 0)) + direction = -1; + else if (refers_to_regno_p (regno + num_words - 1, regno + num_words, + mem_operand, 0)) + direction = 1; + else + /* This means something like + (set (reg:DI r0) (mem:DI (reg:HI r1))) + which we'd need to support by doing the set of the second word + last. */ + abort (); + } + + end = direction < 0 ? -1 : num_words; + for (i = direction < 0 ? num_words - 1 : 0; i != end; i += direction) + { + rtx w_src, w_dest; + if (src_modifies) + w_src = gen_rtx_MEM (word_mode, mem_operand); + else + w_src = simplify_gen_subreg (word_mode, src, mode, i * UNITS_PER_WORD); + if (src_volatile) + MEM_VOLATILE_P (w_src) = 1; + if (dest_modifies) + w_dest = gen_rtx_MEM (word_mode, mem_operand); + else + w_dest = simplify_gen_subreg (word_mode, dest, mode, + i * UNITS_PER_WORD); + if (dest_volatile) + MEM_VOLATILE_P (w_dest) = 1; + + /* The simplify_subreg calls must always be able to simplify. */ + if (GET_CODE (w_src) == SUBREG + || GET_CODE (w_dest) == SUBREG) + abort (); + + emit_insn (gen_rtx_SET (VOIDmode, w_dest, w_src)); + } +} + +/* Expander for the 'move' patterns. Emit insns to copy a value of + mode MODE from SRC to DEST. */ + +void +stormy16_expand_move (mode, dest, src) + enum machine_mode mode; + rtx dest; + rtx src; +{ + /* There are only limited immediate-to-memory move instructions. */ + if (! reload_in_progress + && ! reload_completed + && GET_CODE (dest) == MEM + && (GET_CODE (XEXP (dest, 0)) != CONST_INT + || ! stormy16_legitimate_address_p (mode, XEXP (dest, 0), 0)) + && GET_CODE (src) != REG + && GET_CODE (src) != SUBREG) + src = copy_to_mode_reg (mode, src); + + /* Don't emit something we would immediately split. */ + if (reload_completed + && mode != HImode && mode != QImode) + { + stormy16_split_move (mode, dest, src); + return; + } + + emit_insn (gen_rtx_SET (VOIDmode, dest, src)); +} + + +/* Stack Layout: + + The stack is laid out as follows: + +SP-> +FP-> Local variables + Register save area (up to 4 words) + Argument register save area for stdarg (NUM_ARGUMENT_REGISTERS words) + +AP-> Return address (two words) + 9th procedure parameter word + 10th procedure parameter word + ... + last procedure parameter word + + The frame pointer location is tuned to make it most likely that all + parameters and local variables can be accessed using a load-indexed + instruction. */ + +/* A structure to describe the layout. */ +struct stormy16_stack_layout +{ + /* Size of the topmost three items on the stack. */ + int locals_size; + int register_save_size; + int stdarg_save_size; + /* Sum of the above items. */ + int frame_size; + /* Various offsets. */ + int first_local_minus_ap; + int sp_minus_fp; + int fp_minus_ap; +}; + +/* Does REGNO need to be saved? */ +#define REG_NEEDS_SAVE(REGNUM, IFUN) \ + ((regs_ever_live[REGNUM] && ! call_used_regs[REGNUM]) \ + || (IFUN && ! fixed_regs[REGNUM] && call_used_regs[REGNUM] \ + && (regs_ever_live[REGNUM] || ! current_function_is_leaf))) + +/* Compute the stack layout. */ +struct stormy16_stack_layout +stormy16_compute_stack_layout () +{ + struct stormy16_stack_layout layout; + int regno; + const int ifun = stormy16_interrupt_function_p (); + + layout.locals_size = get_frame_size (); + + layout.register_save_size = 0; + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (REG_NEEDS_SAVE (regno, ifun)) + layout.register_save_size += UNITS_PER_WORD; + + if (current_function_varargs || current_function_stdarg) + layout.stdarg_save_size = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD; + else + layout.stdarg_save_size = 0; + + layout.frame_size = (layout.locals_size + + layout.register_save_size + + layout.stdarg_save_size); + + if (current_function_args_size <= 2048 && current_function_args_size != -1) + { + if (layout.frame_size + INCOMING_FRAME_SP_OFFSET + + current_function_args_size <= 2048) + layout.fp_minus_ap = layout.frame_size + INCOMING_FRAME_SP_OFFSET; + else + layout.fp_minus_ap = 2048 - current_function_args_size; + } + else + layout.fp_minus_ap = (layout.stdarg_save_size + + layout.register_save_size + + INCOMING_FRAME_SP_OFFSET); + layout.sp_minus_fp = (layout.frame_size + INCOMING_FRAME_SP_OFFSET + - layout.fp_minus_ap); + layout.first_local_minus_ap = layout.sp_minus_fp - layout.locals_size; + return layout; +} + +/* Determine how all the special registers get eliminated. */ +int +stormy16_initial_elimination_offset (from, to) + int from, to; +{ + struct stormy16_stack_layout layout; + int result; + + layout = stormy16_compute_stack_layout (); + + if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) + result = layout.sp_minus_fp - layout.locals_size; + else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + result = -layout.locals_size; + else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) + result = -layout.fp_minus_ap; + else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) + result = -(layout.sp_minus_fp + layout.fp_minus_ap); + else + abort (); + + return result; +} + +static rtx +emit_addhi3_postreload (dest, src0, src1) + rtx dest; + rtx src0; + rtx src1; +{ + rtx set, clobber, insn; + + set = gen_rtx_SET (VOIDmode, dest, gen_rtx_PLUS (HImode, src0, src1)); + clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, 16)); + insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber))); + return insn; +} + +/* 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. + + Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1 + so that the debug info generation code can handle them properly. */ +void +stormy16_expand_prologue () +{ + struct stormy16_stack_layout layout; + int regno; + rtx insn; + rtx mem_push_rtx; + rtx mem_fake_push_rtx; + const int ifun = stormy16_interrupt_function_p (); + + mem_push_rtx = gen_rtx_POST_INC (Pmode, stack_pointer_rtx); + mem_push_rtx = gen_rtx_MEM (HImode, mem_push_rtx); + mem_fake_push_rtx = gen_rtx_PRE_INC (Pmode, stack_pointer_rtx); + mem_fake_push_rtx = gen_rtx_MEM (HImode, mem_fake_push_rtx); + + layout = stormy16_compute_stack_layout (); + + /* Save the argument registers if necessary. */ + if (layout.stdarg_save_size) + for (regno = FIRST_ARGUMENT_REGISTER; + regno < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS; + regno++) + { + rtx reg = gen_rtx_REG (HImode, regno); + insn = emit_move_insn (mem_push_rtx, reg); + RTX_FRAME_RELATED_P (insn) = 1; + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, + gen_rtx_SET (VOIDmode, + mem_fake_push_rtx, + reg), + REG_NOTES (insn)); + } + + /* Push each of the registers to save. */ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (REG_NEEDS_SAVE (regno, ifun)) + { + rtx reg = gen_rtx_REG (HImode, regno); + insn = emit_move_insn (mem_push_rtx, reg); + RTX_FRAME_RELATED_P (insn) = 1; + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, + gen_rtx_SET (VOIDmode, + mem_fake_push_rtx, + reg), + REG_NOTES (insn)); + } + + /* It's just possible that the SP here might be what we need for + the new FP... */ + if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size) + { + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + } + + /* Allocate space for local variables. */ + if (layout.locals_size) + { + insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (layout.locals_size)); + RTX_FRAME_RELATED_P (insn) = 1; + } + + /* Set up the frame pointer, if required. */ + if (frame_pointer_needed && layout.sp_minus_fp != layout.locals_size) + { + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + if (layout.sp_minus_fp) + { + insn = emit_addhi3_postreload (hard_frame_pointer_rtx, + hard_frame_pointer_rtx, + GEN_INT (-layout.sp_minus_fp)); + RTX_FRAME_RELATED_P (insn) = 1; + } + } +} + +/* Do we need an epilogue at all? */ +int +direct_return () +{ + return (reload_completed + && stormy16_compute_stack_layout ().frame_size == 0); +} + +/* 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_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. */ + +void +stormy16_expand_epilogue () +{ + struct stormy16_stack_layout layout; + rtx mem_pop_rtx; + int regno; + const int ifun = stormy16_interrupt_function_p (); + + mem_pop_rtx = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); + mem_pop_rtx = gen_rtx_MEM (HImode, mem_pop_rtx); + + layout = stormy16_compute_stack_layout (); + + /* Pop the stack for the locals. */ + if (layout.locals_size) + emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (- layout.locals_size)); + + /* Restore any call-saved registers. */ + for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) + if (REG_NEEDS_SAVE (regno, ifun)) + emit_move_insn (gen_rtx_REG (HImode, regno), mem_pop_rtx); + + /* Pop the stack for the stdarg save area. */ + if (layout.stdarg_save_size) + emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (- layout.stdarg_save_size)); + + /* Return. */ + if (ifun) + emit_jump_insn (gen_return_internal_interrupt ()); + else + emit_jump_insn (gen_return_internal ()); +} + +int +stormy16_epilogue_uses (regno) + int regno; +{ + if (reload_completed && call_used_regs[regno]) + { + const int ifun = stormy16_interrupt_function_p (); + return REG_NEEDS_SAVE (regno, ifun); + } + return 0; +} + +/* Return an updated summarizer variable CUM to advance past an + argument in the argument list. The values MODE, TYPE and NAMED + describe that argument. Once this is done, the variable CUM is + suitable for analyzing the *following* argument with + `FUNCTION_ARG', etc. + + This function need not do anything if the argument in question was + passed on the stack. The compiler knows how to track the amount of + stack space used for arguments without any special help. However, + it makes life easier for stormy16_build_va_list if it does update + the word count. */ +CUMULATIVE_ARGS +stormy16_function_arg_advance (cum, mode, type, named) + CUMULATIVE_ARGS cum; + enum machine_mode mode; + tree type; + int named ATTRIBUTE_UNUSED; +{ + /* If an argument would otherwise be passed partially in registers, + and partially on the stack, the whole of it is passed on the + stack. */ + if (cum < NUM_ARGUMENT_REGISTERS + && cum + STORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS) + cum = NUM_ARGUMENT_REGISTERS; + + cum += STORMY16_WORD_SIZE (type, mode); + + return cum; +} + +/* Do any needed setup for a variadic function. CUM has not been updated + for the last named argument which has type TYPE and mode MODE. */ +void +stormy16_setup_incoming_varargs (cum, int_mode, type, pretend_size) + CUMULATIVE_ARGS cum ATTRIBUTE_UNUSED; + int int_mode ATTRIBUTE_UNUSED; + tree type ATTRIBUTE_UNUSED; + int * pretend_size ATTRIBUTE_UNUSED; +{ +} + +/* Build the va_list type. + + For this chip, va_list is a record containing a counter and a pointer. + The counter is of type 'int' and indicates how many bytes + have been used to date. The pointer indicates the stack position + for arguments that have not been passed in registers. + To keep the layout nice, the pointer is first in the structure. */ + +tree +stormy16_build_va_list () +{ + tree f_1, f_2, record, type_decl; + + record = make_lang_type (RECORD_TYPE); + type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); + + f_2 = build_decl (FIELD_DECL, get_identifier ("base"), + ptr_type_node); + f_1 = build_decl (FIELD_DECL, get_identifier ("count"), + unsigned_type_node); + + DECL_FIELD_CONTEXT (f_1) = record; + DECL_FIELD_CONTEXT (f_2) = record; + + TREE_CHAIN (record) = type_decl; + TYPE_NAME (record) = type_decl; + TYPE_FIELDS (record) = f_1; + TREE_CHAIN (f_1) = f_2; + + layout_type (record); + + return record; +} + +/* Implement the stdarg/varargs va_start macro. STDARG_P is non-zero if this + is stdarg.h instead of varargs.h. VALIST is the tree of the va_list + variable to initialize. NEXTARG is the machine independent notion of the + 'next' argument after the variable arguments. */ +void +stormy16_expand_builtin_va_start (stdarg_p, valist, nextarg) + int stdarg_p ATTRIBUTE_UNUSED; + tree valist; + rtx nextarg ATTRIBUTE_UNUSED; +{ + tree f_base, f_count; + tree base, count; + tree t; + + if (stormy16_interrupt_function_p ()) + error ("cannot use va_start in interrupt function"); + + f_base = TYPE_FIELDS (va_list_type_node); + f_count = TREE_CHAIN (f_base); + + base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base); + count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count); + + t = make_tree (TREE_TYPE (base), virtual_incoming_args_rtx); + t = build (PLUS_EXPR, TREE_TYPE (base), t, + build_int_2 (INCOMING_FRAME_SP_OFFSET, 0)); + t = build (MODIFY_EXPR, TREE_TYPE (base), base, t); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + + t = build (MODIFY_EXPR, TREE_TYPE (count), count, + build_int_2 (current_function_args_info * UNITS_PER_WORD, 0)); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); +} + +/* Implement the stdarg/varargs va_arg macro. VALIST is the variable + of type va_list as a tree, TYPE is the type passed to va_arg. */ +rtx +stormy16_expand_builtin_va_arg (valist, type) + tree valist; + tree type; +{ + tree f_base, f_count; + tree base, count; + rtx count_rtx, addr_rtx, r; + rtx lab_gotaddr, lab_fromstack; + tree t; + int size, last_reg_count; + tree size_tree, count_plus_size; + + f_base = TYPE_FIELDS (va_list_type_node); + f_count = TREE_CHAIN (f_base); + + base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base); + count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count); + + size = PUSH_ROUNDING (int_size_in_bytes (type)); + size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD); + + last_reg_count = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD - size; + + count_rtx = expand_expr (count, NULL_RTX, HImode, EXPAND_NORMAL); + lab_gotaddr = gen_label_rtx (); + lab_fromstack = gen_label_rtx (); + addr_rtx = gen_reg_rtx (Pmode); + emit_cmp_and_jump_insns (count_rtx, GEN_INT (last_reg_count), + GTU, const1_rtx, HImode, 1, 1, lab_fromstack); + + t = build (PLUS_EXPR, ptr_type_node, base, count); + r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); + if (r != addr_rtx) + emit_move_insn (addr_rtx, r); + + emit_jump_insn (gen_jump (lab_gotaddr)); + emit_barrier (); + emit_label (lab_fromstack); + + /* Arguments larger than a word might need to skip over some + registers, since arguments are either passed entirely in + registers or entirely on the stack. */ + if (size > 2 || size < 0) + { + rtx lab_notransition = gen_label_rtx (); + emit_cmp_and_jump_insns (count_rtx, GEN_INT (NUM_ARGUMENT_REGISTERS + * UNITS_PER_WORD), + GEU, const1_rtx, HImode, 1, 1, + lab_notransition); + + t = build (MODIFY_EXPR, TREE_TYPE (count), count, + build_int_2 (NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD, 0)); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + + emit_label (lab_notransition); + } + + t = build (PLUS_EXPR, sizetype, size_tree, + build_int_2 ((- NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD + + INCOMING_FRAME_SP_OFFSET), + -1)); + t = build (PLUS_EXPR, TREE_TYPE (count), count, fold (t)); + t = build (MINUS_EXPR, TREE_TYPE (base), base, t); + r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); + if (r != addr_rtx) + emit_move_insn (addr_rtx, r); + + emit_label (lab_gotaddr); + + count_plus_size = build (PLUS_EXPR, TREE_TYPE (count), count, size_tree); + t = build (MODIFY_EXPR, TREE_TYPE (count), count, count_plus_size); + TREE_SIDE_EFFECTS (t) = 1; + expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); + + return addr_rtx; +} + +/* Initialize the variable parts of a trampoline. ADDR is an RTX for + the address of the trampoline; FNADDR is an RTX for the address of + the nested function; STATIC_CHAIN is an RTX for the static chain + value that should be passed to the function when it is called. */ +void +stormy16_initialize_trampoline (addr, fnaddr, static_chain) + rtx addr; + rtx fnaddr; + rtx static_chain; +{ + rtx reg_addr = gen_reg_rtx (Pmode); + rtx temp = gen_reg_rtx (HImode); + rtx reg_fnaddr = gen_reg_rtx (HImode); + rtx reg_addr_mem; + + reg_addr_mem = gen_rtx_MEM (HImode, gen_rtx_POST_INC (Pmode, reg_addr)); + + emit_move_insn (reg_addr, addr); + emit_move_insn (temp, GEN_INT (0x3130 | STATIC_CHAIN_REGNUM)); + emit_move_insn (reg_addr_mem, temp); + emit_move_insn (temp, static_chain); + emit_move_insn (reg_addr_mem, temp); + emit_move_insn (reg_fnaddr, fnaddr); + emit_move_insn (temp, reg_fnaddr); + emit_insn (gen_andhi3 (temp, temp, GEN_INT (0xFF))); + emit_insn (gen_iorhi3 (temp, temp, GEN_INT (0x0200))); + emit_move_insn (reg_addr_mem, temp); + emit_insn (gen_lshrhi3 (reg_fnaddr, reg_fnaddr, GEN_INT (8))); + emit_move_insn (reg_addr_mem, reg_fnaddr); +} + +/* Create an RTX representing the place where a function returns a + value of data type VALTYPE. VALTYPE is a tree node representing a + data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode + used to represent that type. On many machines, only the mode is + relevant. (Actually, on most machines, scalar values are returned + in the same place regardless of mode). + + If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion + rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type. + + If the precise function being called is known, FUNC is a tree node + (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it + possible to use a different value-returning convention for specific + functions when all their calls are known. + + `FUNCTION_VALUE' is not used for return vales with aggregate data types, + because these are returned in another way. See `STRUCT_VALUE_REGNUM' and + related macros. */ +rtx +stormy16_function_value (valtype, func) + tree valtype; + tree func ATTRIBUTE_UNUSED; +{ + enum machine_mode mode; + mode = TYPE_MODE (valtype); + PROMOTE_MODE (mode, 0, valtype); + return gen_rtx_REG (mode, RETURN_VALUE_REGNUM); +} + +/* Mark functions with SYMBOL_REF_FLAG. */ + +void +stormy16_encode_section_info (decl) + tree decl; +{ + if (TREE_CODE (decl) == FUNCTION_DECL) + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; +} + +/* Print a memory address as an operand to reference that memory location. */ +void +stormy16_print_operand_address (file, address) + FILE * file; + rtx address; +{ + HOST_WIDE_INT offset; + int pre_dec, post_inc; + + /* There are a few easy cases. */ + if (GET_CODE (address) == CONST_INT) + { + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (address) & 0xFFFF); + return; + } + + if (CONSTANT_P (address) || GET_CODE (address) == CODE_LABEL) + { + output_addr_const (file, address); + return; + } + + /* Otherwise, it's hopefully something of the form + (plus:HI (pre_dec:HI (reg:HI ...)) (const_int ...)) + */ + + if (GET_CODE (address) == PLUS) + { + if (GET_CODE (XEXP (address, 1)) != CONST_INT) + abort (); + offset = INTVAL (XEXP (address, 1)); + address = XEXP (address, 0); + } + else + offset = 0; + + pre_dec = (GET_CODE (address) == PRE_DEC); + post_inc = (GET_CODE (address) == POST_INC); + if (pre_dec || post_inc) + address = XEXP (address, 0); + + if (GET_CODE (address) != REG) + abort (); + + fputc ('(', file); + if (pre_dec) + fputs ("--", file); + fputs (reg_names [REGNO (address)], file); + if (post_inc) + fputs ("++", file); + if (offset != 0) + { + fputc (',', file); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset); + } + fputc (')', file); +} + +/* Print an operand to a assembler instruction. */ +void +stormy16_print_operand (file, x, code) + FILE * file; + rtx x; + int code; +{ + switch (code) + { + case 'B': + /* There is either one bit set, or one bit clear, in X. + Print it preceded by '#'. */ + { + HOST_WIDE_INT xx, l; + + if (GET_CODE (x) == CONST_INT) + xx = INTVAL (x); + else + output_operand_lossage ("`B' operand is not constant"); + + l = exact_log2 (xx); + if (l == -1) + l = exact_log2 (~xx); + if (l == -1) + output_operand_lossage ("`B' operand has multiple bits set"); + + fputs (IMMEDIATE_PREFIX, file); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, l); + return; + } + + case 'C': + /* Print the symbol without a surrounding @fptr(). */ + if (GET_CODE (x) == SYMBOL_REF) + assemble_name (file, XSTR (x, 0)); + else + stormy16_print_operand_address (file, x); + return; + + case 'o': + case 'O': + /* Print the immediate operand less one, preceded by '#'. + For 'O', negate it first. */ + { + HOST_WIDE_INT xx; + + if (GET_CODE (x) == CONST_INT) + xx = INTVAL (x); + else + output_operand_lossage ("`o' operand is not constant"); + + if (code == 'O') + xx = -xx; + + fputs (IMMEDIATE_PREFIX, file); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, xx - 1); + return; + } + + case 0: + /* Handled below. */ + break; + + default: + output_operand_lossage ("stormy16_print_operand: unknown code"); + return; + } + + switch (GET_CODE (x)) + { + case REG: + fputs (reg_names [REGNO (x)], file); + break; + + case MEM: + stormy16_print_operand_address (file, XEXP (x, 0)); + break; + + default: + /* Some kind of constant or label; an immediate operand, + so prefix it with '#' for the assembler. */ + fputs (IMMEDIATE_PREFIX, file); + output_addr_const (file, x); + break; + } + + return; +} + + +/* Expander for the `casesi' pattern. + INDEX is the index of the switch statement. + LOWER_BOUND is a CONST_INT that is the value of INDEX corresponding + to the first table entry. + RANGE is the number of table entries. + TABLE is an ADDR_VEC that is the jump table. + DEFAULT_LABEL is the address to branch to if INDEX is outside the + range LOWER_BOUND to LOWER_BOUND+RANGE-1. +*/ + +void +stormy16_expand_casesi (index, lower_bound, range, table, default_label) + rtx index; + rtx lower_bound; + rtx range; + rtx table; + rtx default_label; +{ + HOST_WIDE_INT range_i = INTVAL (range); + rtx int_index; + + /* This code uses 'br', so it can deal only with tables of size up to + 8192 entries. */ + if (range_i >= 8192) + sorry ("switch statement of size %lu entries too large", + (unsigned long) range_i); + + index = expand_binop (SImode, sub_optab, index, lower_bound, index, 0, + OPTAB_LIB_WIDEN); + emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, SImode, 1, + 0, default_label); + int_index = gen_lowpart_common (HImode, index); + emit_insn (gen_ashlhi3 (int_index, int_index, GEN_INT (2))); + emit_jump_insn (gen_tablejump_pcrel (int_index, table)); +} + +/* Output an ADDR_VEC. It is output as a sequence of 'jmpf' + instructions, without label or alignment or any other special + constructs. We know that the previous instruction will be the + `tablejump_pcrel' output above. + + TODO: it might be nice to output 'br' instructions if they could + all reach. */ + +void +stormy16_output_addr_vec (file, label, table) + FILE *file; + rtx label ATTRIBUTE_UNUSED; + rtx table; +{ + int vlen, idx; + + function_section (current_function_decl); + + vlen = XVECLEN (table, 0); + for (idx = 0; idx < vlen; idx++) + { + fputs ("\tjmpf ", file); + stormy16_print_operand_address (file, + XEXP (XVECEXP (table, 0, idx), 0)); + fputc ('\n', file); + } +} + + +/* Expander for the `call' patterns. + INDEX is the index of the switch statement. + LOWER_BOUND is a CONST_INT that is the value of INDEX corresponding + to the first table entry. + RANGE is the number of table entries. + TABLE is an ADDR_VEC that is the jump table. + DEFAULT_LABEL is the address to branch to if INDEX is outside the + range LOWER_BOUND to LOWER_BOUND+RANGE-1. +*/ + +void +stormy16_expand_call (retval, dest, counter) + rtx retval; + rtx dest; + rtx counter; +{ + rtx call, temp; + enum machine_mode mode; + + if (GET_CODE (dest) != MEM) + abort (); + dest = XEXP (dest, 0); + + if (! CONSTANT_P (dest) + && GET_CODE (dest) != REG) + dest = force_reg (Pmode, dest); + + if (retval == NULL) + mode = VOIDmode; + else + mode = GET_MODE (retval); + + call = gen_rtx_CALL (mode, gen_rtx_MEM (FUNCTION_MODE, dest), + counter); + if (retval) + call = gen_rtx_SET (VOIDmode, retval, call); + + if (! CONSTANT_P (dest)) + { + temp = gen_reg_rtx (HImode); + emit_move_insn (temp, const0_rtx); + } + else + temp = const0_rtx; + + call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, + gen_rtx_USE (VOIDmode, temp))); + emit_call_insn (call); +} + +/* Expanders for multiword computational operations. */ + +/* Expander for arithmetic operations; emit insns to compute + + (set DEST (CODE:MODE SRC0 SRC1)) + + using CARRY as a temporary. When CODE is COMPARE, a branch + template is generated (this saves duplicating code in + stormy16_split_cbranch). */ + +void +stormy16_expand_arith (mode, code, dest, src0, src1, carry) + enum machine_mode mode; + enum rtx_code code; + rtx dest; + rtx src0; + rtx src1; + rtx carry; +{ + int num_words = GET_MODE_BITSIZE (mode) / BITS_PER_WORD; + int i; + int firstloop = 1; + + if (code == NEG) + { + rtx zero_reg = gen_reg_rtx (word_mode); + emit_move_insn (zero_reg, src0); + src0 = zero_reg; + } + + for (i = 0; i < num_words; i++) + { + rtx w_src0, w_src1, w_dest; + rtx insn; + + if (code == NEG) + w_src0 = src0; + else + w_src0 = simplify_gen_subreg (word_mode, src0, mode, + i * UNITS_PER_WORD); + w_src1 = simplify_gen_subreg (word_mode, src1, mode, i * UNITS_PER_WORD); + w_dest = simplify_gen_subreg (word_mode, dest, mode, i * UNITS_PER_WORD); + + switch (code) + { + case PLUS: + if (firstloop + && GET_CODE (w_src1) == CONST_INT && INTVAL (w_src1) == 0) + continue; + + if (firstloop) + insn = gen_addchi4 (w_dest, w_src0, w_src1, carry); + else + insn = gen_addchi5 (w_dest, w_src0, w_src1, carry, carry); + break; + + case NEG: + case MINUS: + case COMPARE: + if (code == COMPARE && i == num_words - 1) + { + rtx branch, sub, clobber, sub_1; + + sub_1 = gen_rtx_MINUS (HImode, w_src0, + gen_rtx_ZERO_EXTEND (HImode, carry)); + sub = gen_rtx_SET (VOIDmode, w_dest, + gen_rtx_MINUS (HImode, sub_1, w_src1)); + clobber = gen_rtx_CLOBBER (VOIDmode, carry); + branch = gen_rtx_SET (VOIDmode, pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, + gen_rtx_EQ (HImode, + sub_1, + w_src1), + pc_rtx, + pc_rtx)); + insn = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (3, branch, sub, clobber)); + } + else if (firstloop + && code != COMPARE + && GET_CODE (w_src1) == CONST_INT && INTVAL (w_src1) == 0) + continue; + else if (firstloop) + insn = gen_subchi4 (w_dest, w_src0, w_src1, carry); + else + insn = gen_subchi5 (w_dest, w_src0, w_src1, carry, carry); + break; + + case IOR: + case XOR: + case AND: + if (GET_CODE (w_src1) == CONST_INT + && INTVAL (w_src1) == -(code == AND)) + continue; + + insn = gen_rtx_SET (VOIDmode, w_dest, gen_rtx (code, mode, + w_src0, w_src1)); + break; + + case NOT: + insn = gen_rtx_SET (VOIDmode, w_dest, gen_rtx_NOT (mode, w_src0)); + break; + + default: + abort (); + } + + firstloop = 0; + emit (insn); + } +} + +/* Return 1 if OP is a shift operator. */ + +int +shift_operator (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + enum rtx_code code = GET_CODE (op); + + return (code == ASHIFT + || code == ASHIFTRT + || code == LSHIFTRT); +} + +/* The shift operations are split at output time for constant values; + variable-width shifts get handed off to a library routine. + + Generate an output string to do (set X (CODE:MODE X SIZE_R)) + SIZE_R will be a CONST_INT, X will be a hard register. */ + +const char * +stormy16_output_shift (mode, code, x, size_r, temp) + enum machine_mode mode; + enum rtx_code code; + rtx x; + rtx size_r; + rtx temp; +{ + HOST_WIDE_INT size; + const char *r0, *r1, *rt; + static char r[64]; + + if (GET_CODE (size_r) != CONST_INT + || GET_CODE (x) != REG + || mode != SImode) + abort (); + size = INTVAL (size_r) & (GET_MODE_BITSIZE (mode) - 1); + + if (size == 0) + return ""; + + r0 = reg_names [REGNO (x)]; + r1 = reg_names [REGNO (x) + 1]; + rt = reg_names [REGNO (temp)]; + + /* For shifts of size 1, we can use the rotate instructions. */ + if (size == 1) + { + switch (code) + { + case ASHIFT: + sprintf (r, "shl %s,#1 | rlc %s,#1", r0, r1); + break; + case ASHIFTRT: + sprintf (r, "asr %s,#1 | rrc %s,#1", r1, r0); + break; + case LSHIFTRT: + sprintf (r, "shr %s,#1 | rrc %s,#1", r1, r0); + break; + default: + abort (); + } + return r; + } + + /* For large shifts, there are easy special cases. */ + if (size == 16) + { + switch (code) + { + case ASHIFT: + sprintf (r, "mov %s,%s | mov %s,#0", r1, r0, r0); + break; + case ASHIFTRT: + sprintf (r, "mov %s,%s | asr %s,#15", r0, r1, r1); + break; + case LSHIFTRT: + sprintf (r, "mov %s,%s | mov %s,#0", r0, r1, r1); + break; + default: + abort (); + } + return r; + } + if (size > 16) + { + switch (code) + { + case ASHIFT: + sprintf (r, "mov %s,%s | mov %s,#0 | shl %s,#%d", + r1, r0, r0, r1, (int) size - 16); + break; + case ASHIFTRT: + sprintf (r, "mov %s,%s | asr %s,#15 | asr %s,#%d", + r0, r1, r1, r0, (int) size - 16); + break; + case LSHIFTRT: + sprintf (r, "mov %s,%s | mov %s,#0 | shr %s,#%d", + r0, r1, r1, r0, (int) size - 16); + break; + default: + abort (); + } + return r; + } + + /* For the rest, we have to do more work. In particular, we + need a temporary. */ + switch (code) + { + case ASHIFT: + sprintf (r, + "mov %s,%s | shl %s,#%d | shl %s,#%d | shr %s,#%d | or %s,%s", + rt, r0, r0, (int) size, r1, (int) size, rt, (int) 16-size, + r1, rt); + break; + case ASHIFTRT: + sprintf (r, + "mov %s,%s | asr %s,#%d | shr %s,#%d | shl %s,#%d | or %s,%s", + rt, r1, r1, (int) size, r0, (int) size, rt, (int) 16-size, + r0, rt); + break; + case LSHIFTRT: + sprintf (r, + "mov %s,%s | shr %s,#%d | shr %s,#%d | shl %s,#%d | or %s,%s", + rt, r1, r1, (int) size, r0, (int) size, rt, (int) 16-size, + r0, rt); + break; + default: + abort (); + } + return r; +} + +/* Attribute handling. */ + +/* Return nonzero if the function is an interrupt function. */ +int +stormy16_interrupt_function_p () +{ + tree attributes; + + /* The dwarf2 mechanism asks for INCOMING_FRAME_SP_OFFSET before + any functions are declared, which is demonstrably wrong, but + it is worked around here. FIXME. */ + if (!cfun) + return 0; + + attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); + return lookup_attribute ("interrupt", attributes) != NULL_TREE; +} + +/* If defined, a C function which returns nonzero if IDENTIFIER + with arguments ARGS is a valid machine specific attribute for TYPE. + The attributes in ATTRIBUTES have previously been assigned to TYPE. */ +#undef TARGET_VALID_TYPE_ATTRIBUTE +#define TARGET_VALID_TYPE_ATTRIBUTE stormy16_valid_type_attribute +static int stormy16_valid_type_attribute PARAMS ((tree TYPE, + tree ATTRIBUTES, + tree IDENTIFIER, + tree ARGS)); + +static int +stormy16_valid_type_attribute (type, attributes, identifier, args) + tree type; + tree attributes ATTRIBUTE_UNUSED; + tree identifier; + tree args ATTRIBUTE_UNUSED; +{ + if (TREE_CODE (type) != FUNCTION_TYPE) + return 0; + + if (is_attribute_p ("interrupt", identifier)) + return 1; + + return 0; +} + +struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/stormy16/stormy16.h b/gcc/config/stormy16/stormy16.h new file mode 100644 index 0000000..7310e6c --- /dev/null +++ b/gcc/config/stormy16/stormy16.h @@ -0,0 +1,5355 @@ +/* Stormy16 cpu description. + Copyright (C) 1997, 1998, 1999, 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. */ + + +/* Set up System V.4 (aka ELF) defaults. */ +#include "svr4.h" + + +/* Driver configuration */ + +/* A C expression which determines whether the option `-CHAR' takes arguments. + The value should be the number of arguments that option takes-zero, for many + options. + + By default, this macro is defined to handle the standard options properly. + You need not define it unless you wish to add additional options which take + arguments. + + Defined in svr4.h. */ +/* #define SWITCH_TAKES_ARG(CHAR) */ + +/* A C expression which determines whether the option `-NAME' takes arguments. + The value should be the number of arguments that option takes-zero, for many + options. This macro rather than `SWITCH_TAKES_ARG' is used for + multi-character option names. + + By default, this macro is defined as `DEFAULT_WORD_SWITCH_TAKES_ARG', which + handles the standard options properly. You need not define + `WORD_SWITCH_TAKES_ARG' unless you wish to add additional options which take + arguments. Any redefinition should call `DEFAULT_WORD_SWITCH_TAKES_ARG' and + then check for additional options. + + Defined in svr4.h. */ +/* #define WORD_SWITCH_TAKES_ARG(NAME) */ + +/* A string-valued C expression which is nonempty if the linker needs a space + between the `-L' or `-o' option and its argument. + + If this macro is not defined, the default value is 0. */ +/* #define SWITCHES_NEED_SPACES "" */ + +/* A C string constant that tells the GNU CC driver program options to pass to + CPP. It can also specify how to translate options you give to GNU CC into + options for GNU CC to pass to the CPP. + + Do not define this macro if it does not need to do anything. */ +/* #define CPP_SPEC "" */ + +/* If this macro is defined, the preprocessor will not define the builtin macro + `__SIZE_TYPE__'. The macro `__SIZE_TYPE__' must then be defined by + `CPP_SPEC' instead. + + This should be defined if `SIZE_TYPE' depends on target dependent flags + which are not accessible to the preprocessor. Otherwise, it should not be + defined. */ +/* #define NO_BUILTIN_SIZE_TYPE */ + +/* If this macro is defined, the preprocessor will not define the builtin macro + `__PTRDIFF_TYPE__'. The macro `__PTRDIFF_TYPE__' must then be defined by + `CPP_SPEC' instead. + + This should be defined if `PTRDIFF_TYPE' depends on target dependent flags + which are not accessible to the preprocessor. Otherwise, it should not be + defined. */ +/* #define NO_BUILTIN_PTRDIFF_TYPE */ + +/* A C string constant that tells the GNU CC driver program options to pass to + CPP. By default, this macro is defined to pass the option + `-D__CHAR_UNSIGNED__' to CPP if `char' will be treated as `unsigned char' by + `cc1'. + + Do not define this macro unless you need to override the default definition. */ +/* #if DEFAULT_SIGNED_CHAR + #define SIGNED_CHAR_SPEC "%{funsigned-char:-D__CHAR_UNSIGNED__}" + #else + #define SIGNED_CHAR_SPEC "%{!fsigned-char:-D__CHAR_UNSIGNED__}" + #endif */ + +/* A C string constant that tells the GNU CC driver program options to pass to + `cc1'. It can also specify how to translate options you give to GNU CC into + options for GNU CC to pass to the `cc1'. + + Do not define this macro if it does not need to do anything. */ +/* #define CC1_SPEC "" */ + +/* A C string constant that tells the GNU CC driver program options to pass to + `cc1plus'. It can also specify how to translate options you give to GNU CC + into options for GNU CC to pass to the `cc1plus'. + + Do not define this macro if it does not need to do anything. */ +/* #define CC1PLUS_SPEC "" */ + +/* A C string constant that tells the GNU CC driver program options to pass to + the assembler. It can also specify how to translate options you give to GNU + CC into options for GNU CC to pass to the assembler. See the file `sun3.h' + for an example of this. + + Do not define this macro if it does not need to do anything. + + Defined in svr4.h. */ +#undef ASM_SPEC + +/* A C string constant that tells the GNU CC driver program how to run any + programs which cleanup after the normal assembler. Normally, this is not + needed. See the file `mips.h' for an example of this. + + Do not define this macro if it does not need to do anything. + + Defined in svr4.h. */ +/* #define ASM_FINAL_SPEC "" */ + +/* A C string constant that tells the GNU CC driver program options to pass to + the linker. It can also specify how to translate options you give to GNU CC + into options for GNU CC to pass to the linker. + + Do not define this macro if it does not need to do anything. + + Defined in svr4.h. */ +/* #define LINK_SPEC "" */ + +/* Another C string constant used much like `LINK_SPEC'. The difference + between the two is that `LIB_SPEC' is used at the end of the command given + to the linker. + + If this macro is not defined, a default is provided that loads the standard + C library from the usual place. See `gcc.c'. + + Defined in svr4.h. */ +#undef LIB_SPEC +#define LIB_SPEC "-( -lc %{msim:-lsim}%{!msim:-lnosys} -)" + +/* Another C string constant that tells the GNU CC driver program how and when + to place a reference to `libgcc.a' into the linker command line. This + constant is placed both before and after the value of `LIB_SPEC'. + + If this macro is not defined, the GNU CC driver provides a default that + passes the string `-lgcc' to the linker unless the `-shared' option is + specified. */ +/* #define LIBGCC_SPEC "" */ + +/* Another C string constant used much like `LINK_SPEC'. The difference + between the two is that `STARTFILE_SPEC' is used at the very beginning of + the command given to the linker. + + If this macro is not defined, a default is provided that loads the standard + C startup file from the usual place. See `gcc.c'. + + Defined in svr4.h. */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s" + +/* Another C string constant used much like `LINK_SPEC'. The difference + between the two is that `ENDFILE_SPEC' is used at the very end of the + command given to the linker. + + Do not define this macro if it does not need to do anything. + + Defined in svr4.h. */ +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +/* Define this macro if the driver program should find the library `libgcc.a' + itself and should not pass `-L' options to the linker. If you do not define + this macro, the driver program will pass the argument `-lgcc' to tell the + linker to do the search and will pass `-L' options to it. */ +/* #define LINK_LIBGCC_SPECIAL */ + +/* Define this macro if the driver program should find the library `libgcc.a'. + If you do not define this macro, the driver program will pass the argument + `-lgcc' to tell the linker to do the search. This macro is similar to + `LINK_LIBGCC_SPECIAL', except that it does not affect `-L' options. */ +/* #define LINK_LIBGCC_SPECIAL_1 */ + +/* Define this macro to provide additional specifications to put in the `specs' + file that can be used in various specifications like `CC1_SPEC'. + + The definition should be an initializer for an array of structures, + containing a string constant, that defines the specification name, and a + string constant that provides the specification. + + Do not define this macro if it does not need to do anything. */ +/* #define EXTRA_SPECS {{}} */ + +/* Define this macro as a C expression for the initializer of an array of + string to tell the driver program which options are defaults for this target + and thus do not need to be handled specially when using `MULTILIB_OPTIONS'. + + Do not define this macro if `MULTILIB_OPTIONS' is not defined in the target + makefile fragment or if none of the options listed in `MULTILIB_OPTIONS' are + set by default. */ +/* #define MULTILIB_DEFAULTS {} */ + +/* Define this macro to tell `gcc' that it should only translate a `-B' prefix + into a `-L' linker option if the prefix indicates an absolute file name. */ +/* #define RELATIVE_PREFIX_NOT_LINKDIR */ + +/* Define this macro as a C string constant if you wish to override the + standard choice of `/usr/local/lib/gcc-lib/' as the default prefix to try + when searching for the executable files of the compiler. */ +/* #define STANDARD_EXEC_PREFIX "" */ + +/* If defined, this macro is an additional prefix to try after + `STANDARD_EXEC_PREFIX'. `MD_EXEC_PREFIX' is not searched when the `-b' + option is used, or the compiler is built as a cross compiler. + + Defined in svr4.h for host compilers. */ +/* #define MD_EXEC_PREFIX "" */ + +/* Define this macro as a C string constant if you wish to override the + standard choice of `/usr/local/lib/' as the default prefix to try when + searching for startup files such as `crt0.o'. */ +/* #define STANDARD_STARTFILE_PREFIX "" */ + +/* If defined, this macro supplies an additional prefix to try after the + standard prefixes. `MD_EXEC_PREFIX' is not searched when the `-b' option is + used, or when the compiler is built as a cross compiler. + + Defined in svr4.h for host compilers. */ +/* #define MD_STARTFILE_PREFIX "" */ + +/* If defined, this macro supplies yet another prefix to try after the standard + prefixes. It is not searched when the `-b' option is used, or when the + compiler is built as a cross compiler. */ +/* #define MD_STARTFILE_PREFIX_1 "" */ + +/* Define this macro as a C string constant if you with to set environment + variables for programs called by the driver, such as the assembler and + loader. The driver passes the value of this macro to `putenv' to initialize + the necessary environment variables. */ +/* #define INIT_ENVIRONMENT "" */ + +/* Define this macro as a C string constant if you wish to override the + standard choice of `/usr/local/include' as the default prefix to try when + searching for local header files. `LOCAL_INCLUDE_DIR' comes before + `SYSTEM_INCLUDE_DIR' in the search order. + + Cross compilers do not use this macro and do not search either + `/usr/local/include' or its replacement. */ +/* #define LOCAL_INCLUDE_DIR "" */ + +/* Define this macro as a C string constant if you wish to specify a + system-specific directory to search for header files before the standard + directory. `SYSTEM_INCLUDE_DIR' comes before `STANDARD_INCLUDE_DIR' in the + search order. + + Cross compilers do not use this macro and do not search the directory + specified. */ +/* #define SYSTEM_INCLUDE_DIR "" */ + +/* Define this macro as a C string constant if you wish to override the + standard choice of `/usr/include' as the default prefix to try when + searching for header files. + + Cross compilers do not use this macro and do not search either + `/usr/include' or its replacement. */ +/* #define STANDARD_INCLUDE_DIR "" */ + +/* Define this macro if you wish to override the entire default search path for + include files. The default search path includes `GCC_INCLUDE_DIR', + `LOCAL_INCLUDE_DIR', `SYSTEM_INCLUDE_DIR', `GPLUSPLUS_INCLUDE_DIR', and + `STANDARD_INCLUDE_DIR'. In addition, `GPLUSPLUS_INCLUDE_DIR' and + `GCC_INCLUDE_DIR' are defined automatically by `Makefile', and specify + private search areas for GCC. The directory `GPLUSPLUS_INCLUDE_DIR' is used + only for C++ programs. + + The definition should be an initializer for an array of structures. Each + array element should have two elements: the directory name (a string + constant) and a flag for C++-only directories. Mark the end of the array + with a null element. For example, here is the definition used for VMS: + + #define INCLUDE_DEFAULTS \ + { \ + { "GNU_GXX_INCLUDE:", 1}, \ + { "GNU_CC_INCLUDE:", 0}, \ + { "SYS$SYSROOT:[SYSLIB.]", 0}, \ + { ".", 0}, \ + { 0, 0} \ + } + + Here is the order of prefixes tried for exec files: + + 1. Any prefixes specified by the user with `-B'. + + 2. The environment variable `GCC_EXEC_PREFIX', if any. + + 3. The directories specified by the environment variable + `COMPILER_PATH'. + + 4. The macro `STANDARD_EXEC_PREFIX'. + + 5. `/usr/lib/gcc/'. + + 6. The macro `MD_EXEC_PREFIX', if any. + + Here is the order of prefixes tried for startfiles: + + 1. Any prefixes specified by the user with `-B'. + + 2. The environment variable `GCC_EXEC_PREFIX', if any. + + 3. The directories specified by the environment variable + `LIBRARY_PATH' (native only, cross compilers do not use this). + + 4. The macro `STANDARD_EXEC_PREFIX'. + + 5. `/usr/lib/gcc/'. + + 6. The macro `MD_EXEC_PREFIX', if any. + + 7. The macro `MD_STARTFILE_PREFIX', if any. + + 8. The macro `STANDARD_STARTFILE_PREFIX'. + + 9. `/lib/'. + + 10. `/usr/lib/'. */ +/* #define INCLUDE_DEFAULTS {{ }} */ + + +/* Run-time target specifications */ + +/* Define this to be a string constant containing `-D' options to define the + predefined macros that identify this machine and system. These macros will + be predefined unless the `-ansi' option is specified. + + In addition, a parallel set of macros are predefined, whose names are made + by appending `__' at the beginning and at the end. These `__' macros are + permitted by the ANSI standard, so they are predefined regardless of whether + `-ansi' is specified. + + For example, on the Sun, one can use the following value: + + "-Dmc68000 -Dsun -Dunix" + + The result is to define the macros `__mc68000__', `__sun__' and `__unix__' + unconditionally, and the macros `mc68000', `sun' and `unix' provided `-ansi' + is not specified. */ +#define CPP_PREDEFINES "-Dstormy16 -Amachine=stormy16 -D__INT_MAX__=32767" + +/* This declaration should be present. */ +extern int target_flags; + +/* This series of macros is to allow compiler command arguments to enable or + disable the use of optional features of the target machine. For example, + one machine description serves both the 68000 and the 68020; a command + argument tells the compiler whether it should use 68020-only instructions or + not. This command argument works by means of a macro `TARGET_68020' that + tests a bit in `target_flags'. + + Define a macro `TARGET_FEATURENAME' for each such option. Its definition + should test a bit in `target_flags'; for example: + + #define TARGET_68020 (target_flags & 1) + + One place where these macros are used is in the condition-expressions of + instruction patterns. Note how `TARGET_68020' appears frequently in the + 68000 machine description file, `m68k.md'. Another place they are used is + in the definitions of the other macros in the `MACHINE.h' file. */ +/* #define TARGET_... */ + +/* This macro defines names of command options to set and clear bits in + `target_flags'. Its definition is an initializer with a subgrouping for + each command option. + + Each subgrouping contains a string constant, that defines the + option name, a number, which contains the bits to set in + `target_flags', and an optional second string which is the textual + description that will be displayed when the user passes --help on + the command line. If the number entry is negative then the + specified bits will be cleared instead of being set. If the second + string entry is present but empty, then no help information will be + displayed for that option, but it will not count as an undocumented + option. The actual option name, as seen on the command line is + made by appending `-m' to the specified name. + + One of the subgroupings should have a null string. The number in this + grouping is the default value for `target_flags'. Any target options act + starting with that value. + + Here is an example which defines `-m68000' and `-m68020' with opposite + meanings, and picks the latter as the default: + + #define TARGET_SWITCHES \ + { { "68020", 1, ""}, \ + { "68000", -1, "Compile for the m68000"}, \ + { "", 1, }} + + This declaration must be present. */ + +#define TARGET_SWITCHES \ + {{ "sim", 0, "Provide libraries for the simulator" }, \ + { "", 0, "" }} + +/* This macro is similar to `TARGET_SWITCHES' but defines names of command + options that have values. Its definition is an initializer with a + subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the fixed part of + the option name, the address of a variable, and an optional description string. + The variable, of type `char *', is set to the text following the fixed part of + the option as it is specified on the command line. The actual option name is + made by appending `-m' to the specified name. + + Here is an example which defines `-mshort-data-NUMBER'. If the given option + is `-mshort-data-512', the variable `m88k_short_data' will be set to the + string `"512"'. + + extern char *m88k_short_data; + #define TARGET_OPTIONS \ + { { "short-data-", & m88k_short_data, \ + "Specify the size of the short data section" } } + + This declaration is optional. */ +/* #define TARGET_OPTIONS */ + +/* This macro is a C statement to print on `stderr' a string describing the + particular machine description choice. Every machine description should + define `TARGET_VERSION'. For example: + + #ifdef MOTOROLA + #define TARGET_VERSION \ + fprintf (stderr, " (68k, Motorola syntax)"); + #else + #define TARGET_VERSION \ + fprintf (stderr, " (68k, MIT syntax)"); + #endif */ +#define TARGET_VERSION fprintf (stderr, " (stormy16 cpu core)"); + +/* Sometimes certain combinations of command options do not make sense on a + particular target machine. You can define a macro `OVERRIDE_OPTIONS' to + take account of this. This macro, if defined, is executed once just after + all the command options have been parsed. + + Don't use this macro to turn on various extra optimizations for `-O'. That + is what `OPTIMIZATION_OPTIONS' is for. */ +/* #define OVERRIDE_OPTIONS */ + +/* Some machines may desire to change what optimizations are performed for + various optimization levels. This macro, if defined, is executed once just + after the optimization level is determined and before the remainder of the + command options have been parsed. Values set in this macro are used as the + default values for the other command line options. + + LEVEL is the optimization level specified; 2 if `-O2' is specified, 1 if + `-O' is specified, and 0 if neither is specified. + + SIZE is non-zero if `-Os' is specified, 0 otherwise. + + You should not use this macro to change options that are not + machine-specific. These should uniformly selected by the same optimization + level on all supported machines. Use this macro to enable machbine-specific + optimizations. + + *Do not examine `write_symbols' in this macro!* The debugging options are + *not supposed to alter the generated code. */ +/* #define OPTIMIZATION_OPTIONS(LEVEL,SIZE) */ + +/* Define this macro if debugging can be performed even without a frame + pointer. If this macro is defined, GNU CC will turn on the + `-fomit-frame-pointer' option whenever `-O' is specified. */ +#define CAN_DEBUG_WITHOUT_FP + + +/* Storage Layout */ + +/* Define this macro to have the value 1 if the most significant bit in a byte + has the lowest number; otherwise define it to have the value zero. This + means that bit-field instructions count from the most significant bit. If + the machine has no bit-field instructions, then this must still be defined, + but it doesn't matter which value it is defined to. This macro need not be + a constant. + + This macro does not affect the way structure fields are packed into bytes or + words; that is controlled by `BYTES_BIG_ENDIAN'. */ +#define BITS_BIG_ENDIAN 1 + +/* Define this macro to have the value 1 if the most significant byte in a word + has the lowest number. This macro need not be a constant. */ +#define BYTES_BIG_ENDIAN 0 + +/* Define this macro to have the value 1 if, in a multiword object, the most + significant word has the lowest number. This applies to both memory + locations and registers; GNU CC fundamentally assumes that the order of + words in memory is the same as the order in registers. This macro need not + be a constant. */ +#define WORDS_BIG_ENDIAN 0 + +/* Define this macro if WORDS_BIG_ENDIAN is not constant. This must be a + constant value with the same meaning as WORDS_BIG_ENDIAN, which will be used + only when compiling libgcc2.c. Typically the value will be set based on + preprocessor defines. */ +/* #define LIBGCC2_WORDS_BIG_ENDIAN */ + +/* Define this macro to have the value 1 if `DFmode', `XFmode' or `TFmode' + floating point numbers are stored in memory with the word containing the + sign bit at the lowest address; otherwise define it to have the value 0. + This macro need not be a constant. + + You need not define this macro if the ordering is the same as for multi-word + integers. */ +/* #define FLOAT_WORDS_BIG_ENDIAN */ + +/* Define this macro to be the number of bits in an addressable storage unit + (byte); normally 8. */ +#define BITS_PER_UNIT 8 + +/* Number of bits in a word; normally 32. */ +#define BITS_PER_WORD 16 + +/* Maximum number of bits in a word. If this is undefined, the default is + `BITS_PER_WORD'. Otherwise, it is the constant value that is the largest + value that `BITS_PER_WORD' can have at run-time. */ +/* #define MAX_BITS_PER_WORD */ + +/* Number of storage units in a word; normally 4. */ +#define UNITS_PER_WORD 2 + +/* Minimum number of units in a word. If this is undefined, the default is + `UNITS_PER_WORD'. Otherwise, it is the constant value that is the smallest + value that `UNITS_PER_WORD' can have at run-time. */ +/* #define MIN_UNITS_PER_WORD */ + +/* Width of a pointer, in bits. You must specify a value no wider than the + width of `Pmode'. If it is not equal to the width of `Pmode', you must + define `POINTERS_EXTEND_UNSIGNED'. */ +#define POINTER_SIZE 16 + +/* A C expression whose value is nonzero if pointers that need to be extended + from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and zero if + they are zero-extended. + + You need not define this macro if the `POINTER_SIZE' is equal to the width + of `Pmode'. */ +/* #define POINTERS_EXTEND_UNSIGNED */ + +/* A macro to update MODE and UNSIGNEDP when an object whose type is TYPE and + which has the specified mode and signedness is to be stored in a register. + This macro is only called when TYPE is a scalar type. + + On most RISC machines, which only have operations that operate on a full + register, define this macro to set M to `word_mode' if M is an integer mode + narrower than `BITS_PER_WORD'. In most cases, only integer modes should be + widened because wider-precision floating-point operations are usually more + expensive than their narrower counterparts. + + For most machines, the macro definition does not change UNSIGNEDP. However, + some machines, have instructions that preferentially handle either signed or + unsigned quantities of certain modes. For example, on the DEC Alpha, 32-bit + loads from memory and 32-bit add instructions sign-extend the result to 64 + bits. On such machines, set UNSIGNEDP according to which kind of extension + is more efficient. + + Do not define this macro if it would never modify MODE. */ +#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \ +do { \ + if (GET_MODE_CLASS (MODE) == MODE_INT \ + && GET_MODE_SIZE (MODE) < 2) \ + (MODE) = HImode; \ +} while (0) + +/* Define this macro if the promotion described by `PROMOTE_MODE' should also + be done for outgoing function arguments. */ +#define PROMOTE_FUNCTION_ARGS 1 + +/* Define this macro if the promotion described by `PROMOTE_MODE' should also + be done for the return value of functions. + + If this macro is defined, `FUNCTION_VALUE' must perform the same promotions + done by `PROMOTE_MODE'. */ +#define PROMOTE_FUNCTION_RETURN 1 + +/* Define this macro if the promotion described by `PROMOTE_MODE' should *only* + be performed for outgoing function arguments or function return values, as + specified by `PROMOTE_FUNCTION_ARGS' and `PROMOTE_FUNCTION_RETURN', + respectively. */ +/* #define PROMOTE_FOR_CALL_ONLY */ + +/* Normal alignment required for function parameters on the stack, in bits. + All stack parameters receive at least this much alignment regardless of data + type. On most machines, this is the same as the size of an integer. */ +#define PARM_BOUNDARY 16 + +/* Define this macro if you wish to preserve a certain alignment for the stack + pointer. The definition is a C expression for the desired alignment + (measured in bits). + + If `PUSH_ROUNDING' is not defined, the stack will always be aligned to the + specified boundary. If `PUSH_ROUNDING' is defined and specifies a less + strict alignment than `STACK_BOUNDARY', the stack may be momentarily + unaligned while pushing arguments. */ +#define STACK_BOUNDARY 16 + +/* Alignment required for a function entry point, in bits. */ +#define FUNCTION_BOUNDARY 16 + +/* Biggest alignment that any data type can require on this machine, + in bits. */ +#define BIGGEST_ALIGNMENT 16 + +/* Biggest alignment that any structure field can require on this machine, in + bits. If defined, this overrides `BIGGEST_ALIGNMENT' for structure fields + only. */ +/* #define BIGGEST_FIELD_ALIGNMENT */ + +/* An expression for the alignment of a structure field FIELD if the + alignment computed in the usual way is COMPUTED. GNU CC uses this + value instead of the value in `BIGGEST_ALIGNMENT' or + `BIGGEST_FIELD_ALIGNMENT', if defined, for structure fields only. */ +/* #define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) */ + +/* Biggest alignment supported by the object file format of this machine. Use + this macro to limit the alignment which can be specified using the + `__attribute__ ((aligned (N)))' construct. If not defined, the default + value is `BIGGEST_ALIGNMENT'. + + Defined in svr4.h. */ +/* #define MAX_OFILE_ALIGNMENT */ + +/* If defined, a C expression to compute the alignment for a static variable. + TYPE is the data type, and ALIGN is the alignment that the object + would ordinarily have. The value of this macro is used instead of that + alignment to align the object. + + If this macro is not defined, then ALIGN is used. + + One use of this macro is to increase alignment of medium-size data to make + it all fit in fewer cache lines. Another is to cause character arrays to be + word-aligned so that `strcpy' calls that copy constants to character arrays + can be done inline. */ +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + (TREE_CODE (TYPE) == ARRAY_TYPE \ + && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) + +/* If defined, a C expression to compute the alignment given to a constant that + is being placed in memory. CONSTANT is the constant and ALIGN is the + alignment that the object would ordinarily have. The value of this macro is + used instead of that alignment to align the object. + + If this macro is not defined, then ALIGN is used. + + The typical use of this macro is to increase alignment for string constants + to be word aligned so that `strcpy' calls that copy constants can be done + inline. */ +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + (TREE_CODE (EXP) == STRING_CST \ + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) + +/* Alignment in bits to be given to a structure bit field that follows an empty + field such as `int : 0;'. + + Note that `PCC_BITFIELD_TYPE_MATTERS' also affects the alignment that + results from an empty field. */ +/* #define EMPTY_FIELD_BOUNDARY */ + +/* Number of bits which any structure or union's size must be a multiple of. + Each structure or union's size is rounded up to a multiple of this. + + If you do not define this macro, the default is the same as `BITS_PER_UNIT'. */ +/* #define STRUCTURE_SIZE_BOUNDARY */ + +/* Define this macro to be the value 1 if instructions will fail to work if + given data not on the nominal alignment. If instructions will merely go + slower in that case, define this macro as 0. */ +#define STRICT_ALIGNMENT 1 + +/* Define this if you wish to imitate the way many other C compilers handle + alignment of bitfields and the structures that contain them. + + The behavior is that the type written for a bitfield (`int', `short', or + other integer type) imposes an alignment for the entire structure, as if the + structure really did contain an ordinary field of that type. In addition, + the bitfield is placed within the structure so that it would fit within such + a field, not crossing a boundary for it. + + Thus, on most machines, a bitfield whose type is written as `int' would not + cross a four-byte boundary, and would force four-byte alignment for the + whole structure. (The alignment used may not be four bytes; it is + controlled by the other alignment parameters.) + + If the macro is defined, its definition should be a C expression; a nonzero + value for the expression enables this behavior. + + Note that if this macro is not defined, or its value is zero, some bitfields + may cross more than one alignment boundary. The compiler can support such + references if there are `insv', `extv', and `extzv' insns that can directly + reference memory. + + The other known way of making bitfields work is to define + `STRUCTURE_SIZE_BOUNDARY' as large as `BIGGEST_ALIGNMENT'. Then every + structure can be accessed with fullwords. + + Unless the machine has bitfield instructions or you define + `STRUCTURE_SIZE_BOUNDARY' that way, you must define + `PCC_BITFIELD_TYPE_MATTERS' to have a nonzero value. + + If your aim is to make GNU CC use the same conventions for laying out + bitfields as are used by another compiler, here is how to investigate what + the other compiler does. Compile and run this program: + + struct foo1 + { + char x; + char :0; + char y; + }; + + struct foo2 + { + char x; + int :0; + char y; + }; + + main () + { + printf ("Size of foo1 is %d\n", + sizeof (struct foo1)); + printf ("Size of foo2 is %d\n", + sizeof (struct foo2)); + exit (0); + } + + If this prints 2 and 5, then the compiler's behavior is what you would get + from `PCC_BITFIELD_TYPE_MATTERS'. + + Defined in svr4.h. */ +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* Like PCC_BITFIELD_TYPE_MATTERS except that its effect is limited to aligning + a bitfield within the structure. */ +/* #define BITFIELD_NBYTES_LIMITED */ + +/* Define this macro as an expression for the overall size of a structure + (given by STRUCT as a tree node) when the size computed from the fields is + SIZE and the alignment is ALIGN. + + The default is to round SIZE up to a multiple of ALIGN. */ +/* #define ROUND_TYPE_SIZE(STRUCT, SIZE, ALIGN) */ + +/* Define this macro as an expression for the alignment of a structure (given + by STRUCT as a tree node) if the alignment computed in the usual way is + COMPUTED and the alignment explicitly specified was SPECIFIED. + + The default is to use SPECIFIED if it is larger; otherwise, use the smaller + of COMPUTED and `BIGGEST_ALIGNMENT' */ +/* #define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) */ + +/* An integer expression for the size in bits of the largest integer machine + mode that should actually be used. All integer machine modes of this size + or smaller can be used for structures and unions with the appropriate sizes. + If this macro is undefined, `GET_MODE_BITSIZE (DImode)' is assumed. */ +/* #define MAX_FIXED_MODE_SIZE */ + +/* A C statement to validate the value VALUE (of type `double') for mode MODE. + This means that you check whether VALUE fits within the possible range of + values for mode MODE on this target machine. The mode MODE is always a mode + of class `MODE_FLOAT'. OVERFLOW is nonzero if the value is already known to + be out of range. + + If VALUE is not valid or if OVERFLOW is nonzero, you should set OVERFLOW to + 1 and then assign some valid value to VALUE. Allowing an invalid value to + go through the compiler can produce incorrect assembler code which may even + cause Unix assemblers to crash. + + This macro need not be defined if there is no work for it to do. */ +/* #define CHECK_FLOAT_VALUE(MODE, VALUE, OVERFLOW) */ + +/* A code distinguishing the floating point format of the target machine. + There are three defined values: + + IEEE_FLOAT_FORMAT' + This code indicates IEEE floating point. It is the default; + there is no need to define this macro when the format is IEEE. + + VAX_FLOAT_FORMAT' + This code indicates the peculiar format used on the Vax. + + UNKNOWN_FLOAT_FORMAT' + This code indicates any other format. + + The value of this macro is compared with `HOST_FLOAT_FORMAT' + to determine whether the target machine has the same format as + the host machine. If any other formats are actually in use on supported + machines, new codes should be defined for them. + + The ordering of the component words of floating point values stored in + memory is controlled by `FLOAT_WORDS_BIG_ENDIAN' for the target machine and + `HOST_FLOAT_WORDS_BIG_ENDIAN' for the host. */ +#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT + +/* GNU CC supports two ways of implementing C++ vtables: traditional or with + so-called "thunks". The flag `-fvtable-thunk' chooses between them. Define + this macro to be a C expression for the default value of that flag. If + `DEFAULT_VTABLE_THUNKS' is 0, GNU CC uses the traditional implementation by + default. The "thunk" implementation is more efficient (especially if you + have provided an implementation of `ASM_OUTPUT_MI_THUNK', but is not binary + compatible with code compiled using the traditional implementation. If you + are writing a new ports, define `DEFAULT_VTABLE_THUNKS' to 1. + + If you do not define this macro, the default for `-fvtable-thunk' is 0. */ +#define DEFAULT_VTABLE_THUNKS 1 + + +/* Layout of Source Language Data Types */ + +/* A C expression for the size in bits of the type `int' on the target machine. + If you don't define this, the default is one word. */ +#define INT_TYPE_SIZE 16 + +/* Maximum number for the size in bits of the type `int' on the target machine. + If this is undefined, the default is `INT_TYPE_SIZE'. Otherwise, it is the + constant value that is the largest value that `INT_TYPE_SIZE' can have at + run-time. This is used in `cpp'. */ +/* #define MAX_INT_TYPE_SIZE */ + +/* A C expression for the size in bits of the type `short' on the target + machine. If you don't define this, the default is half a word. (If this + would be less than one storage unit, it is rounded up to one unit.) */ +#define SHORT_TYPE_SIZE 16 + +/* A C expression for the size in bits of the type `long' on the target + machine. If you don't define this, the default is one word. */ +#define LONG_TYPE_SIZE 32 + +/* Maximum number for the size in bits of the type `long' on the target + machine. If this is undefined, the default is `LONG_TYPE_SIZE'. Otherwise, + it is the constant value that is the largest value that `LONG_TYPE_SIZE' can + have at run-time. This is used in `cpp'. */ +/* #define MAX_LONG_TYPE_SIZE */ + +/* A C expression for the size in bits of the type `long long' on the target + machine. If you don't define this, the default is two words. If you want + to support GNU Ada on your machine, the value of macro must be at least 64. */ +#define LONG_LONG_TYPE_SIZE 64 + +/* A C expression for the size in bits of the type `char' on the target + machine. If you don't define this, the default is one quarter of a word. + (If this would be less than one storage unit, it is rounded up to one unit.) */ +#define CHAR_TYPE_SIZE 8 + +/* Maximum number for the size in bits of the type `char' on the target + machine. If this is undefined, the default is `CHAR_TYPE_SIZE'. Otherwise, + it is the constant value that is the largest value that `CHAR_TYPE_SIZE' can + have at run-time. This is used in `cpp'. */ +/* #define MAX_CHAR_TYPE_SIZE */ + +/* A C expression for the size in bits of the type `float' on the target + machine. If you don't define this, the default is one word. */ +#define FLOAT_TYPE_SIZE 32 + +/* A C expression for the size in bits of the type `double' on the target + machine. If you don't define this, the default is two words. */ +#define DOUBLE_TYPE_SIZE 64 + +/* A C expression for the size in bits of the type `long double' on the target + machine. If you don't define this, the default is two words. */ +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* An expression whose value is 1 or 0, according to whether the type `char' + should be signed or unsigned by default. The user can always override this + default with the options `-fsigned-char' and `-funsigned-char'. */ +#define DEFAULT_SIGNED_CHAR 0 + +/* A C expression to determine whether to give an `enum' type only as many + bytes as it takes to represent the range of possible values of that type. A + nonzero value means to do that; a zero value means all `enum' types should + be allocated like `int'. + + If you don't define the macro, the default is 0. */ +/* #define DEFAULT_SHORT_ENUMS */ + +/* A C expression for a string describing the name of the data type to use for + size values. The typedef name `size_t' is defined using the contents of the + string. + + The string can contain more than one keyword. If so, separate them with + spaces, and write first any length keyword, then `unsigned' if appropriate, + and finally `int'. The string must exactly match one of the data type names + defined in the function `init_decl_processing' in the file `c-decl.c'. You + may not omit `int' or change the order--that would cause the compiler to + crash on startup. + + If you don't define this macro, the default is `"long unsigned int"'. + + Defined in svr4.h. */ +#define SIZE_TYPE "unsigned int" + +/* A C expression for a string describing the name of the data type to use for + the result of subtracting two pointers. The typedef name `ptrdiff_t' is + defined using the contents of the string. See `SIZE_TYPE' above for more + information. + + If you don't define this macro, the default is `"long int"'. + + Defined in svr4.h. */ +#define PTRDIFF_TYPE "int" + +/* A C expression for a string describing the name of the data type to use for + wide characters. The typedef name `wchar_t' is defined using the contents + of the string. See `SIZE_TYPE' above for more information. + + If you don't define this macro, the default is `"int"'. + + Defined in svr4.h, to "long int". */ +/* #define WCHAR_TYPE "long int" */ + +/* A C expression for the size in bits of the data type for wide characters. + This is used in `cpp', which cannot make use of `WCHAR_TYPE'. + + Defined in svr4.h. */ +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +/* Maximum number for the size in bits of the data type for wide characters. + If this is undefined, the default is `WCHAR_TYPE_SIZE'. Otherwise, it is + the constant value that is the largest value that `WCHAR_TYPE_SIZE' can have + at run-time. This is used in `cpp'. */ +/* #define MAX_WCHAR_TYPE_SIZE */ + +/* Define this macro if the type of Objective C selectors should be `int'. + + If this macro is not defined, then selectors should have the type `struct + objc_selector *'. */ +/* #define OBJC_INT_SELECTORS */ + +/* Define this macro if the compiler can group all the selectors together into + a vector and use just one label at the beginning of the vector. Otherwise, + the compiler must give each selector its own assembler label. + + On certain machines, it is important to have a separate label for each + selector because this enables the linker to eliminate duplicate selectors. */ +/* #define OBJC_SELECTORS_WITHOUT_LABELS */ + + +/* Register Basics */ + +/* Number of hardware registers known to the compiler. They receive numbers 0 + through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number + really is assigned the number `FIRST_PSEUDO_REGISTER'. */ +#define FIRST_PSEUDO_REGISTER 19 + +/* An initializer that says which registers are used for fixed purposes all + throughout the compiled code and are therefore not available for general + allocation. These would include the stack pointer, the frame pointer + (except on machines where that can be used as a general register when no + frame pointer is needed), the program counter on machines where that is + considered one of the addressable registers, and any other numbered register + with a standard use. + + This information is expressed as a sequence of numbers, separated by commas + and surrounded by braces. The Nth number is 1 if register N is fixed, 0 + otherwise. + + The table initialized from this macro, and the table initialized by the + following one, may be overridden at run time either automatically, by the + actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the + command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */ +#define FIXED_REGISTERS \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1 } + +/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in + general) by function calls as well as for fixed registers. This macro + therefore identifies the registers that are not available for general + allocation of values that must live across function calls. + + If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically + saves it on function entry and restores it on function exit, if the register + is used within the function. */ +#define CALL_USED_REGISTERS \ + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1 } + +/* Zero or more C statements that may conditionally modify two variables + `fixed_regs' and `call_used_regs' (both of type `char []') after they have + been initialized from the two preceding macros. + + This is necessary in case the fixed or call-clobbered registers depend on + target flags. + + You need not define this macro if it has no work to do. + + If the usage of an entire class of registers depends on the target flags, + you may indicate this to GCC by using this macro to modify `fixed_regs' and + `call_used_regs' to 1 for each of the registers in the classes which should + not be used by GCC. Also define the macro `REG_CLASS_FROM_LETTER' to return + `NO_REGS' if it is called with a letter for a class that shouldn't be used. + + (However, if this class is not included in `GENERAL_REGS' and all of the + insn patterns whose constraints permit this class are controlled by target + switches, then GCC will automatically avoid using these registers when the + target switches are opposed to them.) */ +/* #define CONDITIONAL_REGISTER_USAGE */ + +/* If this macro is defined and has a nonzero value, it means that `setjmp' and + related functions fail to save the registers, or that `longjmp' fails to + restore them. To compensate, the compiler avoids putting variables in + registers in functions that use `setjmp'. */ +/* #define NON_SAVING_SETJMP */ + +/* Define this macro if the target machine has register windows. This C + expression returns the register number as seen by the called function + corresponding to the register number OUT as seen by the calling function. + Return OUT if register number OUT is not an outbound register. */ +/* #define INCOMING_REGNO(OUT) */ + +/* Define this macro if the target machine has register windows. This C + expression returns the register number as seen by the calling function + corresponding to the register number IN as seen by the called function. + Return IN if register number IN is not an inbound register. */ +/* #define OUTGOING_REGNO(IN) */ + + +/* Order of allocation of registers */ + +/* If defined, an initializer for a vector of integers, containing the numbers + of hard registers in the order in which GNU CC should prefer to use them + (from most preferred to least). + + If this macro is not defined, registers are used lowest numbered first (all + else being equal). + + One use of this macro is on machines where the highest numbered registers + must always be saved and the save-multiple-registers instruction supports + only sequences of consecutive registers. On such machines, define + `REG_ALLOC_ORDER' to be an initializer that lists the highest numbered + allocatable register first. */ +#define REG_ALLOC_ORDER { 9, 7, 6, 5, 4, 3, 8, 2, 1, 0, 10, 11, 12, 13, 14, 15, 16 } + +/* A C statement (sans semicolon) to choose the order in which to allocate hard + registers for pseudo-registers local to a basic block. + + Store the desired register order in the array `reg_alloc_order'. Element 0 + should be the register to allocate first; element 1, the next register; and + so on. + + The macro body should not assume anything about the contents of + `reg_alloc_order' before execution of the macro. + + On most machines, it is not necessary to define this macro. */ +/* #define ORDER_REGS_FOR_LOCAL_ALLOC */ + + +/* How Values Fit in Registers */ + +/* A C expression for the number of consecutive hard registers, starting at + register number REGNO, required to hold a value of mode MODE. + + On a machine where all registers are exactly one word, a suitable definition + of this macro is + + #define HARD_REGNO_NREGS(REGNO, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \ + / UNITS_PER_WORD)) */ +#define HARD_REGNO_NREGS(REGNO, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* A C expression that is nonzero if it is permissible to store a value of mode + MODE in hard register number REGNO (or in several registers starting with + that one). For a machine where all registers are equivalent, a suitable + definition is + + #define HARD_REGNO_MODE_OK(REGNO, MODE) 1 + + It is not necessary for this macro to check for the numbers of fixed + registers, because the allocation mechanism considers them to be always + occupied. + + On some machines, double-precision values must be kept in even/odd register + pairs. The way to implement that is to define this macro to reject odd + register numbers for such modes. + + The minimum requirement for a mode to be OK in a register is that the + `movMODE' instruction pattern support moves between the register and any + other hard register for which the mode is OK; and that moving a value into + the register and back out not alter it. + + Since the same instruction used to move `SImode' will work for all narrower + integer modes, it is not necessary on any machine for `HARD_REGNO_MODE_OK' + to distinguish between these modes, provided you define patterns `movhi', + etc., to take advantage of this. This is useful because of the interaction + between `HARD_REGNO_MODE_OK' and `MODES_TIEABLE_P'; it is very desirable for + all integer modes to be tieable. + + Many machines have special registers for floating point arithmetic. Often + people assume that floating point machine modes are allowed only in floating + point registers. This is not true. Any registers that can hold integers + can safely *hold* a floating point machine mode, whether or not floating + arithmetic can be done on it in those registers. Integer move instructions + can be used to move the values. + + On some machines, though, the converse is true: fixed-point machine modes + may not go in floating registers. This is true if the floating registers + normalize any value stored in them, because storing a non-floating value + there would garble it. In this case, `HARD_REGNO_MODE_OK' should reject + fixed-point machine modes in floating registers. But if the floating + registers do not automatically normalize, if you can store any bit pattern + in one and retrieve it unchanged without a trap, then any machine mode may + go in a floating register, so you can define this macro to say so. + + The primary significance of special floating registers is rather that they + are the registers acceptable in floating point arithmetic instructions. + However, this is of no concern to `HARD_REGNO_MODE_OK'. You handle it by + writing the proper constraints for those instructions. + + On some machines, the floating registers are especially slow to access, so + that it is better to store a value in a stack frame than in such a register + if floating point arithmetic is not being done. As long as the floating + registers are not in class `GENERAL_REGS', they will not be used unless some + pattern's constraint asks for one. */ +#define HARD_REGNO_MODE_OK(REGNO, MODE) ((REGNO) != 16 || (MODE) == BImode) + +/* A C expression that is nonzero if it is desirable to choose register + allocation so as to avoid move instructions between a value of mode MODE1 + and a value of mode MODE2. + + If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are + ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be + zero. */ +#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) != BImode && (MODE2) != BImode) + +/* Define this macro if the compiler should avoid copies to/from CCmode + registers. You should only define this macro if support fo copying to/from + CCmode is incomplete. */ +/* #define AVOID_CCMODE_COPIES */ + + +/* Handling Leaf Functions */ + +/* A C initializer for a vector, indexed by hard register number, which + contains 1 for a register that is allowable in a candidate for leaf function + treatment. + + If leaf function treatment involves renumbering the registers, then the + registers marked here should be the ones before renumbering--those that GNU + CC would ordinarily allocate. The registers which will actually be used in + the assembler code, after renumbering, should not be marked with 1 in this + vector. + + Define this macro only if the target machine offers a way to optimize the + treatment of leaf functions. */ +/* #define LEAF_REGISTERS */ + +/* A C expression whose value is the register number to which REGNO should be + renumbered, when a function is treated as a leaf function. + + If REGNO is a register number which should not appear in a leaf function + before renumbering, then the expression should yield -1, which will cause + the compiler to abort. + + Define this macro only if the target machine offers a way to optimize the + treatment of leaf functions, and registers need to be renumbered to do this. */ +/* #define LEAF_REG_REMAP(REGNO) */ + + +/* Registers That Form a Stack. */ + +/* Define this if the machine has any stack-like registers. */ +/* #define STACK_REGS */ + +/* The number of the first stack-like register. This one is the top + of the stack. */ +/* #define FIRST_STACK_REG */ + +/* The number of the last stack-like register. This one is the + bottom of the stack. */ +/* #define LAST_STACK_REG */ + + +/* Register Classes */ + +/* An enumeral type that must be defined with all the register class names as + enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last + register class, followed by one more enumeral value, `LIM_REG_CLASSES', + which is not a register class but rather tells how many classes there are. + + Each register class has a number, which is the value of casting the class + name to type `int'. The number serves as an index in many of the tables + described below. */ +enum reg_class +{ + NO_REGS, + R0_REGS, + R1_REGS, + TWO_REGS, + R2_REGS, + EIGHT_REGS, + R8_REGS, + GENERAL_REGS, + CARRY_REGS, + ALL_REGS, + LIM_REG_CLASSES +}; + +/* The number of distinct register classes, defined as follows: + + #define N_REG_CLASSES (int) LIM_REG_CLASSES */ +#define N_REG_CLASSES ((int) LIM_REG_CLASSES) + +/* An initializer containing the names of the register classes as C string + constants. These names are used in writing some of the debugging dumps. */ +#define REG_CLASS_NAMES \ +{ \ + "NO_REGS", \ + "R0_REGS", \ + "R1_REGS", \ + "TWO_REGS", \ + "R2_REGS", \ + "EIGHT_REGS", \ + "R8_REGS", \ + "GENERAL_REGS", \ + "CARRY_REGS", \ + "ALL_REGS" \ +} + +/* An initializer containing the contents of the register classes, as integers + which are bit masks. The Nth integer specifies the contents of class N. + The way the integer MASK is interpreted is that register R is in the class + if `MASK & (1 << R)' is 1. + + When the machine has more than 32 registers, an integer does not suffice. + Then the integers are replaced by sub-initializers, braced groupings + containing several integers. Each sub-initializer must be suitable as an + initializer for the type `HARD_REG_SET' which is defined in + `hard-reg-set.h'. */ +#define REG_CLASS_CONTENTS \ +{ \ + 0x00000, \ + 0x00001, \ + 0x00002, \ + 0x00003, \ + 0x00004, \ + 0x000FF, \ + 0x00100, \ + 0x6FFFF, \ + 0x10000, \ + (1 << FIRST_PSEUDO_REGISTER) - 1 \ +} + +/* A C expression whose value is a register class containing hard register + REGNO. In general there is more than one such class; choose a class which + is "minimal", meaning that no smaller class also contains the register. */ +#define REGNO_REG_CLASS(REGNO) \ + ((REGNO) == 0 ? R0_REGS \ + : (REGNO) == 1 ? R1_REGS \ + : (REGNO) == 2 ? R2_REGS \ + : (REGNO) < 8 ? EIGHT_REGS \ + : (REGNO) == 8 ? R8_REGS \ + : (REGNO) == 16 ? CARRY_REGS \ + : (REGNO) <= 18 ? GENERAL_REGS \ + : ALL_REGS) + +/* A macro whose definition is the name of the class to which a valid base + register must belong. A base register is one used in an address which is + the register value plus a displacement. */ +#define BASE_REG_CLASS GENERAL_REGS + +/* A macro whose definition is the name of the class to which a valid index + register must belong. An index register is one used in an address where its + value is either multiplied by a scale factor or added to another register + (as well as added to a displacement). */ +#define INDEX_REG_CLASS GENERAL_REGS + +/* A C expression which defines the machine-dependent operand constraint + letters for register classes. If CHAR is such a letter, the value should be + the register class corresponding to it. Otherwise, the value should be + `NO_REGS'. The register letter `r', corresponding to class `GENERAL_REGS', + will not be passed to this macro; you do not need to handle it. + + The following letters are unavailable, due to being used as + constraints: + '0'..'9' + '<', '>' + 'E', 'F', 'G', 'H' + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' + 'Q', 'R', 'S', 'T', 'U' + 'V', 'X' + 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */ + +#define REG_CLASS_FROM_LETTER(CHAR) \ + ( (CHAR) == 'a' ? R0_REGS \ + : (CHAR) == 'b' ? R1_REGS \ + : (CHAR) == 'c' ? R2_REGS \ + : (CHAR) == 't' ? TWO_REGS \ + : (CHAR) == 'e' ? EIGHT_REGS \ + : (CHAR) == 'y' ? CARRY_REGS \ + : NO_REGS) + +/* A C expression which is nonzero if register number NUM is suitable for use + as a base register in operand addresses. It may be either a suitable hard + register or a pseudo register that has been allocated such a hard register. */ +#define REGNO_OK_FOR_BASE_P(NUM) 1 + +/* A C expression which is nonzero if register number NUM is suitable for use + as an index register in operand addresses. It may be either a suitable hard + register or a pseudo register that has been allocated such a hard register. + + The difference between an index register and a base register is that the + index register may be scaled. If an address involves the sum of two + registers, neither one of them scaled, then either one may be labeled the + "base" and the other the "index"; but whichever labeling is used must fit + the machine's constraints of which registers may serve in each capacity. + The compiler will try both labelings, looking for one that is valid, and + will reload one or both registers only if neither labeling works. */ +#define REGNO_OK_FOR_INDEX_P(NUM) REGNO_OK_FOR_BASE_P (NUM) + +/* A C expression that places additional restrictions on the register class to + use when it is necessary to copy value X into a register in class CLASS. + The value is a register class; perhaps CLASS, or perhaps another, smaller + class. On many machines, the following definition is safe: + + #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS + + Sometimes returning a more restrictive class makes better code. For + example, on the 68000, when X is an integer constant that is in range for a + `moveq' instruction, the value of this macro is always `DATA_REGS' as long + as CLASS includes the data registers. Requiring a data register guarantees + that a `moveq' will be used. + + If X is a `const_double', by returning `NO_REGS' you can force X into a + memory constant. This is useful on certain machines where immediate + floating values cannot be loaded into certain kinds of registers. + + This declaration must be present. */ +#define PREFERRED_RELOAD_CLASS(X, CLASS) \ + stormy16_preferred_reload_class (X, CLASS) + +/* Like `PREFERRED_RELOAD_CLASS', but for output reloads instead of input + reloads. If you don't define this macro, the default is to use CLASS, + unchanged. */ +#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ + stormy16_preferred_reload_class (X, CLASS) + +/* A C expression that places additional restrictions on the register class to + use when it is necessary to be able to hold a value of mode MODE in a reload + register for which class CLASS would ordinarily be used. + + Unlike `PREFERRED_RELOAD_CLASS', this macro should be used when there are + certain modes that simply can't go in certain reload classes. + + The value is a register class; perhaps CLASS, or perhaps another, smaller + class. + + Don't define this macro unless the target machine has limitations which + require the macro to do something nontrivial. */ +/* #define LIMIT_RELOAD_CLASS(MODE, CLASS) */ + +/* Many machines have some registers that cannot be copied directly to or from + memory or even from other types of registers. An example is the `MQ' + register, which on most machines, can only be copied to or from general + registers, but not memory. Some machines allow copying all registers to and + from memory, but require a scratch register for stores to some memory + locations (e.g., those with symbolic address on the RT, and those with + certain symbolic address on the Sparc when compiling PIC). In some cases, + both an intermediate and a scratch register are required. + + You should define these macros to indicate to the reload phase that it may + need to allocate at least one register for a reload in addition to the + register to contain the data. Specifically, if copying X to a register + CLASS in MODE requires an intermediate register, you should define + `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of + whose registers can be used as intermediate registers or scratch registers. + + If copying a register CLASS in MODE to X requires an intermediate or scratch + register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the + largest register class required. If the requirements for input and output + reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used + instead of defining both macros identically. + + The values returned by these macros are often `GENERAL_REGS'. Return + `NO_REGS' if no spare register is needed; i.e., if X can be directly copied + to or from a register of CLASS in MODE without requiring a scratch register. + Do not define this macro if it would always return `NO_REGS'. + + If a scratch register is required (either with or without an intermediate + register), you should define patterns for `reload_inM' or `reload_outM', as + required.. These patterns, which will normally be implemented with a + `define_expand', should be similar to the `movM' patterns, except that + operand 2 is the scratch register. + + Define constraints for the reload register and scratch register that contain + a single register class. If the original reload register (whose class is + CLASS) can meet the constraint given in the pattern, the value returned by + these macros is used for the class of the scratch register. Otherwise, two + additional reload registers are required. Their classes are obtained from + the constraints in the insn pattern. + + X might be a pseudo-register or a `subreg' of a pseudo-register, which could + either be in a hard register or in memory. Use `true_regnum' to find out; + it will return -1 if the pseudo is in memory and the hard register number if + it is in a register. + + These macros should not be used in the case where a particular class of + registers can only be copied to memory and not to another class of + registers. In that case, secondary reload registers are not needed and + would not be helpful. Instead, a stack location must be used to perform the + copy and the `movM' pattern should use memory as a intermediate storage. + This case often occurs between floating-point and general registers. */ + +/* This chip has the interesting property that only the first eight + registers can be moved to/from memory. */ +#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ + stormy16_secondary_reload_class (CLASS, MODE, X) + +/* #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) */ +/* #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) */ + +/* Certain machines have the property that some registers cannot be copied to + some other registers without using memory. Define this macro on those + machines to be a C expression that is non-zero if objects of mode M in + registers of CLASS1 can only be copied to registers of class CLASS2 by + storing a register of CLASS1 into memory and loading that memory location + into a register of CLASS2. + + Do not define this macro if its value would always be zero. */ +/* #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, M) */ + +/* Normally when `SECONDARY_MEMORY_NEEDED' is defined, the compiler allocates a + stack slot for a memory location needed for register copies. If this macro + is defined, the compiler instead uses the memory location defined by this + macro. + + Do not define this macro if you do not define + `SECONDARY_MEMORY_NEEDED'. */ +/* #define SECONDARY_MEMORY_NEEDED_RTX(MODE) */ + +/* When the compiler needs a secondary memory location to copy between two + registers of mode MODE, it normally allocates sufficient memory to hold a + quantity of `BITS_PER_WORD' bits and performs the store and load operations + in a mode that many bits wide and whose class is the same as that of MODE. + + This is right thing to do on most machines because it ensures that all bits + of the register are copied and prevents accesses to the registers in a + narrower mode, which some machines prohibit for floating-point registers. + + However, this default behavior is not correct on some machines, such as the + DEC Alpha, that store short integers in floating-point registers differently + than in integer registers. On those machines, the default widening will not + work correctly and you must define this macro to suppress that widening in + some cases. See the file `alpha.h' for details. + + Do not define this macro if you do not define `SECONDARY_MEMORY_NEEDED' or + if widening MODE to a mode that is `BITS_PER_WORD' bits wide is correct for + your machine. */ +/* #define SECONDARY_MEMORY_NEEDED_MODE(MODE) */ + +/* Normally the compiler avoids choosing registers that have been explicitly + mentioned in the rtl as spill registers (these registers are normally those + used to pass parameters and return values). However, some machines have so + few registers of certain classes that there would not be enough registers to + use as spill registers if this were done. + + Define `SMALL_REGISTER_CLASSES' to be an expression with a non-zero value on + these machines. When this macro has a non-zero value, the compiler allows + registers explicitly used in the rtl to be used as spill registers but + avoids extending the lifetime of these registers. + + It is always safe to define this macro with a non-zero value, but if you + unnecessarily define it, you will reduce the amount of optimizations that + can be performed in some cases. If you do not define this macro with a + non-zero value when it is required, the compiler will run out of spill + registers and print a fatal error message. For most machines, you should + not define this macro at all. */ +/* #define SMALL_REGISTER_CLASSES */ + +/* A C expression whose value is nonzero if pseudos that have been assigned to + registers of class CLASS would likely be spilled because registers of CLASS + are needed for spill registers. + + The default value of this macro returns 1 if CLASS has exactly one register + and zero otherwise. On most machines, this default should be used. Only + define this macro to some other expression if pseudo allocated by + `local-alloc.c' end up in memory because their hard registers were needed + for spill registers. If this macro returns nonzero for those classes, those + pseudos will only be allocated by `global.c', which knows how to reallocate + the pseudo to another register. If there would not be another register + available for reallocation, you should not change the definition of this + macro since the only effect of such a definition would be to slow down + register allocation. */ +/* #define CLASS_LIKELY_SPILLED_P(CLASS) */ + +/* A C expression for the maximum number of consecutive registers of + class CLASS needed to hold a value of mode MODE. + + This is closely related to the macro `HARD_REGNO_NREGS'. In fact, the value + of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of + `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS. + + This macro helps control the handling of multiple-word values in + the reload pass. + + This declaration is required. */ +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* If defined, a C expression for a class that contains registers which the + compiler must always access in a mode that is the same size as the mode in + which it loaded the register. + + For the example, loading 32-bit integer or floating-point objects into + floating-point registers on the Alpha extends them to 64-bits. Therefore + loading a 64-bit object and then storing it as a 32-bit object does not + store the low-order 32-bits, as would be the case for a normal register. + Therefore, `alpha.h' defines this macro as `FLOAT_REGS'. */ +/* #define CLASS_CANNOT_CHANGE_SIZE */ + +/* A C expression that defines the machine-dependent operand constraint letters + (`I', `J', `K', .. 'P') that specify particular ranges of integer values. + If C is one of those letters, the expression should check that VALUE, an + integer, is in the appropriate range and return 1 if so, 0 otherwise. If C + is not one of those letters, the value should be 0 regardless of VALUE. */ +#define CONST_OK_FOR_LETTER_P(VALUE, C) \ + ( (C) == 'I' ? (VALUE) >= 0 && (VALUE) <= 3 \ + : (C) == 'J' ? exact_log2 (VALUE) != -1 \ + : (C) == 'K' ? exact_log2 (~(VALUE)) != -1 \ + : (C) == 'L' ? (VALUE) >= 0 && (VALUE) <= 255 \ + : (C) == 'M' ? (VALUE) >= -255 && (VALUE) <= 0 \ + : (C) == 'N' ? (VALUE) >= -3 && (VALUE) <= 0 \ + : (C) == 'O' ? (VALUE) >= 1 && (VALUE) <= 4 \ + : (C) == 'P' ? (VALUE) >= -4 && (VALUE) <= -1 \ + : 0 ) + +/* A C expression that defines the machine-dependent operand constraint letters + (`G', `H') that specify particular ranges of `const_double' values. + + If C is one of those letters, the expression should check that VALUE, an RTX + of code `const_double', is in the appropriate range and return 1 if so, 0 + otherwise. If C is not one of those letters, the value should be 0 + regardless of VALUE. + + `const_double' is used for all floating-point constants and for `DImode' + fixed-point constants. A given letter can accept either or both kinds of + values. It can use `GET_MODE' to distinguish between these kinds. */ +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 + +/* A C expression that defines the optional machine-dependent constraint + letters (`Q', `R', `S', `T', `U') that can be used to segregate specific + types of operands, usually memory references, for the target machine. + Normally this macro will not be defined. If it is required for a particular + target machine, it should return 1 if VALUE corresponds to the operand type + represented by the constraint letter C. If C is not defined as an extra + constraint, the value returned should be 0 regardless of VALUE. + + For example, on the ROMP, load instructions cannot have their output in r0 + if the memory reference contains a symbolic address. Constraint letter `Q' + is defined as representing a memory address that does *not* contain a + symbolic address. An alternative is specified with a `Q' constraint on the + input and `r' on the output. The next alternative specifies `m' on the + input and a register class that does not include r0 on the output. */ +#define EXTRA_CONSTRAINT(VALUE, C) \ + stormy16_extra_constraint_p (VALUE, C) + + +/* Basic Stack Layout */ + +/* Define this macro if pushing a word onto the stack moves the stack pointer + to a smaller address. + + When we say, "define this macro if ...," it means that the compiler checks + this macro only with `#ifdef' so the precise definition used does not + matter. */ +/* #define STACK_GROWS_DOWNWARD */ + +/* We want to use post-increment instructions to push things on the stack, + because we don't have any pre-increment ones. */ +#define STACK_PUSH_CODE POST_INC + +/* Define this macro if the addresses of local variable slots are at negative + offsets from the frame pointer. */ +/* #define FRAME_GROWS_DOWNWARD */ + +/* Define this macro if successive arguments to a function occupy decreasing + addresses on the stack. */ +#define ARGS_GROW_DOWNWARD 1 + +/* Offset from the frame pointer to the first local variable slot to be + allocated. + + If `FRAME_GROWS_DOWNWARD', find the next slot's offset by + subtracting the first slot's length from `STARTING_FRAME_OFFSET'. + Otherwise, it is found by adding the length of the first slot to + the value `STARTING_FRAME_OFFSET'. */ +#define STARTING_FRAME_OFFSET 0 + +/* Offset from the stack pointer register to the first location at which + outgoing arguments are placed. If not specified, the default value of zero + is used. This is the proper value for most machines. + + If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first + location at which outgoing arguments are placed. */ +/* #define STACK_POINTER_OFFSET */ + +/* Offset from the argument pointer register to the first argument's address. + On some machines it may depend on the data type of the function. + + If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first + argument's address. */ +#define FIRST_PARM_OFFSET(FUNDECL) 0 + +/* Offset from the stack pointer register to an item dynamically allocated on + the stack, e.g., by `alloca'. + + The default value for this macro is `STACK_POINTER_OFFSET' plus the length + of the outgoing arguments. The default is correct for most machines. See + `function.c' for details. */ +/* #define STACK_DYNAMIC_OFFSET(FUNDECL) */ + +/* A C expression whose value is RTL representing the address in a stack frame + where the pointer to the caller's frame is stored. Assume that FRAMEADDR is + an RTL expression for the address of the stack frame itself. + + If you don't define this macro, the default is to return the value of + FRAMEADDR--that is, the stack frame address is also the address of the stack + word that points to the previous frame. */ +/* #define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) */ + +/* If defined, a C expression that produces the machine-specific code to setup + the stack so that arbitrary frames can be accessed. For example, on the + Sparc, we must flush all of the register windows to the stack before we can + access arbitrary stack frames. This macro will seldom need to be defined. */ +/* #define SETUP_FRAME_ADDRESSES() */ + +/* A C expression whose value is RTL representing the value of the return + address for the frame COUNT steps up from the current frame, after the + prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame + pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is + defined. + + The value of the expression must always be the correct address when COUNT is + zero, but may be `NULL_RTX' if there is not way to determine the return + address of other frames. */ +#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \ + ((COUNT) == 0 \ + ? gen_rtx_MEM (Pmode, arg_pointer_rtx) \ + : NULL_RTX) + +/* Define this if the return address of a particular stack frame is + accessed from the frame pointer of the previous stack frame. */ +/* #define RETURN_ADDR_IN_PREVIOUS_FRAME */ + +/* A C expression whose value is RTL representing the location of the incoming + return address at the beginning of any function, before the prologue. This + RTL is either a `REG', indicating that the return value is saved in `REG', + or a `MEM' representing a location in the stack. + + You only need to define this macro if you want to support call frame + debugging information like that provided by DWARF 2. */ +#define INCOMING_RETURN_ADDR_RTX \ + gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-4))) + +/* A C expression whose value is an integer giving the offset, in bytes, from + the value of the stack pointer register to the top of the stack frame at the + beginning of any function, before the prologue. The top of the frame is + defined to be the value of the stack pointer in the previous frame, just + before the call instruction. + + You only need to define this macro if you want to support call frame + debugging information like that provided by DWARF 2. */ +#define INCOMING_FRAME_SP_OFFSET (stormy16_interrupt_function_p () ? 6 : 4) + + +/* Stack Checking. */ + +/* A nonzero value if stack checking is done by the configuration files in a + machine-dependent manner. You should define this macro if stack checking is + require by the ABI of your machine or if you would like to have to stack + checking in some more efficient way than GNU CC's portable approach. The + default value of this macro is zero. */ +/* #define STACK_CHECK_BUILTIN */ + +/* An integer representing the interval at which GNU CC must generate stack + probe instructions. You will normally define this macro to be no larger + than the size of the "guard pages" at the end of a stack area. The default + value of 4096 is suitable for most systems. */ +/* #define STACK_CHECK_PROBE_INTERVAL */ + +/* A integer which is nonzero if GNU CC should perform the stack probe as a + load instruction and zero if GNU CC should use a store instruction. The + default is zero, which is the most efficient choice on most systems. */ +/* #define STACK_CHECK_PROBE_LOAD */ + +/* The number of bytes of stack needed to recover from a stack overflow, for + languages where such a recovery is supported. The default value of 75 words + should be adequate for most machines. */ +/* #define STACK_CHECK_PROTECT */ + +/* The maximum size of a stack frame, in bytes. GNU CC will generate probe + instructions in non-leaf functions to ensure at least this many bytes of + stack are available. If a stack frame is larger than this size, stack + checking will not be reliable and GNU CC will issue a warning. The default + is chosen so that GNU CC only generates one instruction on most systems. + You should normally not change the default value of this macro. */ +/* #define STACK_CHECK_MAX_FRAME_SIZE */ + +/* GNU CC uses this value to generate the above warning message. It represents + the amount of fixed frame used by a function, not including space for any + callee-saved registers, temporaries and user variables. You need only + specify an upper bound for this amount and will normally use the default of + four words. */ +/* #define STACK_CHECK_FIXED_FRAME_SIZE */ + +/* The maximum size, in bytes, of an object that GNU CC will place in the fixed + area of the stack frame when the user specifies `-fstack-check'. GNU CC + computed the default from the values of the above macros and you will + normally not need to override that default. */ +/* #define STACK_CHECK_MAX_VAR_SIZE */ + + +/* Register That Address the Stack Frame. */ + +/* The register number of the stack pointer register, which must also be a + fixed register according to `FIXED_REGISTERS'. On most machines, the + hardware determines which register this is. */ +#define STACK_POINTER_REGNUM 15 + +/* The register number of the frame pointer register, which is used to access + automatic variables in the stack frame. On some machines, the hardware + determines which register this is. On other machines, you can choose any + register you wish for this purpose. */ +#define FRAME_POINTER_REGNUM 17 + +/* On some machines the offset between the frame pointer and starting offset of + the automatic variables is not known until after register allocation has + been done (for example, because the saved registers are between these two + locations). On those machines, define `FRAME_POINTER_REGNUM' the number of + a special, fixed register to be used internally until the offset is known, + and define `HARD_FRAME_POINTER_REGNUM' to be actual the hard register number + used for the frame pointer. + + You should define this macro only in the very rare circumstances when it is + not possible to calculate the offset between the frame pointer and the + automatic variables until after register allocation has been completed. + When this macro is defined, you must also indicate in your definition of + `ELIMINABLE_REGS' how to eliminate `FRAME_POINTER_REGNUM' into either + `HARD_FRAME_POINTER_REGNUM' or `STACK_POINTER_REGNUM'. + + Do not define this macro if it would be the same as `FRAME_POINTER_REGNUM'. */ +#define HARD_FRAME_POINTER_REGNUM 13 + +/* The register number of the arg pointer register, which is used to access the + function's argument list. On some machines, this is the same as the frame + pointer register. On some machines, the hardware determines which register + this is. On other machines, you can choose any register you wish for this + purpose. If this is not the same register as the frame pointer register, + then you must mark it as a fixed register according to `FIXED_REGISTERS', or + arrange to be able to eliminate it. */ +#define ARG_POINTER_REGNUM 18 + +/* The register number of the return address pointer register, which is used to + access the current function's return address from the stack. On some + machines, the return address is not at a fixed offset from the frame pointer + or stack pointer or argument pointer. This register can be defined to point + to the return address on the stack, and then be converted by + `ELIMINABLE_REGS' into either the frame pointer or stack pointer. + + Do not define this macro unless there is no other way to get the return + address from the stack. */ +/* #define RETURN_ADDRESS_POINTER_REGNUM */ + +/* Register numbers used for passing a function's static chain pointer. If + register windows are used, the register number as seen by the called + function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as + seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers + are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined. + + The static chain register need not be a fixed register. + + If the static chain is passed in memory, these macros should not be defined; + instead, the next two macros should be defined. */ +#define STATIC_CHAIN_REGNUM 12 +/* #define STATIC_CHAIN_INCOMING_REGNUM */ + +/* If the static chain is passed in memory, these macros provide rtx giving + `mem' expressions that denote where they are stored. `STATIC_CHAIN' and + `STATIC_CHAIN_INCOMING' give the locations as seen by the calling and called + functions, respectively. Often the former will be at an offset from the + stack pointer and the latter at an offset from the frame pointer. + + The variables `stack_pointer_rtx', `frame_pointer_rtx', and + `arg_pointer_rtx' will have been initialized prior to the use of these + macros and should be used to refer to those items. + + If the static chain is passed in a register, the two previous + macros should be defined instead. */ +/* #define STATIC_CHAIN */ +/* #define STATIC_CHAIN_INCOMING */ + + +/* Eliminating the Frame Pointer and the Arg Pointer */ + +/* A C expression which is nonzero if a function must have and use a frame + pointer. This expression is evaluated in the reload pass. If its value is + nonzero the function will have a frame pointer. + + The expression can in principle examine the current function and decide + according to the facts, but on most machines the constant 0 or the constant + 1 suffices. Use 0 when the machine allows code to be generated with no + frame pointer, and doing so saves some time or space. Use 1 when there is + no possible advantage to avoiding a frame pointer. + + In certain cases, the compiler does not know how to produce valid code + without a frame pointer. The compiler recognizes those cases and + automatically gives the function a frame pointer regardless of what + `FRAME_POINTER_REQUIRED' says. You don't need to worry about them. + + In a function that does not require a frame pointer, the frame pointer + register can be allocated for ordinary usage, unless you mark it as a fixed + register. See `FIXED_REGISTERS' for more information. */ +#define FRAME_POINTER_REQUIRED 0 + +/* A C statement to store in the variable DEPTH_VAR the difference between the + frame pointer and the stack pointer values immediately after the function + prologue. The value would be computed from information such as the result + of `get_frame_size ()' and the tables of registers `regs_ever_live' and + `call_used_regs'. + + If `ELIMINABLE_REGS' is defined, this macro will be not be used and need not + be defined. Otherwise, it must be defined even if `FRAME_POINTER_REQUIRED' + is defined to always be true; in that case, you may set DEPTH_VAR to + anything. */ +/* #define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) */ + +/* If defined, this macro specifies a table of register pairs used to eliminate + unneeded registers that point into the stack frame. If it is not defined, + the only elimination attempted by the compiler is to replace references to + the frame pointer with references to the stack pointer. + + The definition of this macro is a list of structure initializations, each of + which specifies an original and replacement register. +*/ + +#define ELIMINABLE_REGS \ +{ \ + {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ + {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ +} + +/* A C expression that returns non-zero if the compiler is allowed to try to + replace register number FROM with register number TO. This macro need only + be defined if `ELIMINABLE_REGS' is defined, and will usually be the constant + 1, since most of the cases preventing register elimination are things that + the compiler already knows about. */ + +#define CAN_ELIMINATE(FROM, TO) \ + ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \ + ? ! frame_pointer_needed \ + : 1) + +/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the + initial difference between the specified pair of registers. This macro must + be defined if `ELIMINABLE_REGS' is defined. */ +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + (OFFSET) = stormy16_initial_elimination_offset (FROM, TO) + +/* Define this macro if the `longjmp' function restores registers from the + stack frames, rather than from those saved specifically by `setjmp'. + Certain quantities must not be kept in registers across a call to `setjmp' + on such machines. */ +/* #define LONGJMP_RESTORE_FROM_STACK */ + + +/* Passing Function Arguments on the Stack */ + +/* Define this macro if an argument declared in a prototype as an integral type + smaller than `int' should actually be passed as an `int'. In addition to + avoiding errors in certain cases of mismatch, it also makes for better code + on certain machines. */ +#define PROMOTE_PROTOTYPES 1 + +/* A C expression that is the number of bytes actually pushed onto the stack + when an instruction attempts to push NPUSHED bytes. + + If the target machine does not have a push instruction, do not define this + macro. That directs GNU CC to use an alternate strategy: to allocate the + entire argument block and then store the arguments into it. + + On some machines, the definition + + #define PUSH_ROUNDING(BYTES) (BYTES) + + will suffice. But on other machines, instructions that appear to push one + byte actually push two bytes in an attempt to maintain alignment. Then the + definition should be + + #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1) */ +#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1) + +/* If defined, the maximum amount of space required for outgoing arguments will + be computed and placed into the variable + `current_function_outgoing_args_size'. No space will be pushed onto the + stack for each call; instead, the function prologue should increase the + stack frame size by this amount. + + Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not + proper. */ +/* #define ACCUMULATE_OUTGOING_ARGS */ + +/* Define this macro if functions should assume that stack space has been + allocated for arguments even when their values are passed in registers. + + The value of this macro is the size, in bytes, of the area reserved for + arguments passed in registers for the function represented by FNDECL. + + This space can be allocated by the caller, or be a part of the + machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says + which. */ +/* #define REG_PARM_STACK_SPACE(FNDECL) */ + +/* Define these macros in addition to the one above if functions might allocate + stack space for arguments even when their values are passed in registers. + These should be used when the stack space allocated for arguments in + registers is not a simple constant independent of the function declaration. + + The value of the first macro is the size, in bytes, of the area that we + should initially assume would be reserved for arguments passed in registers. + + The value of the second macro is the actual size, in bytes, of the area that + will be reserved for arguments passed in registers. This takes two + arguments: an integer representing the number of bytes of fixed sized + arguments on the stack, and a tree representing the number of bytes of + variable sized arguments on the stack. + + When these macros are defined, `REG_PARM_STACK_SPACE' will only be called + for libcall functions, the current function, or for a function being called + when it is known that such stack space must be allocated. In each case this + value can be easily computed. + + When deciding whether a called function needs such stack space, and how much + space to reserve, GNU CC uses these two macros instead of + `REG_PARM_STACK_SPACE'. */ +/* #define MAYBE_REG_PARM_STACK_SPACE */ +/* #define FINAL_REG_PARM_STACK_SPACE(CONST_SIZE, VAR_SIZE) */ + +/* Define this if it is the responsibility of the caller to allocate the area + reserved for arguments passed in registers. + + If `ACCUMULATE_OUTGOING_ARGS' is defined, this macro controls whether the + space for these arguments counts in the value of + `current_function_outgoing_args_size'. */ +/* #define OUTGOING_REG_PARM_STACK_SPACE */ + +/* Define this macro if `REG_PARM_STACK_SPACE' is defined, but the stack + parameters don't skip the area specified by it. + + Normally, when a parameter is not passed in registers, it is placed on the + stack beyond the `REG_PARM_STACK_SPACE' area. Defining this macro + suppresses this behavior and causes the parameter to be passed on the stack + in its natural location. */ +/* #define STACK_PARMS_IN_REG_PARM_AREA */ + +/* A C expression that should indicate the number of bytes of its own arguments + that a function pops on returning, or 0 if the function pops no arguments + and the caller must therefore pop them all after the function returns. + + FUNDECL is a C variable whose value is a tree node that describes the + function in question. Normally it is a node of type `FUNCTION_DECL' that + describes the declaration of the function. From this it is possible to + obtain the DECL_MACHINE_ATTRIBUTES of the function. + + FUNTYPE is a C variable whose value is a tree node that describes the + function in question. Normally it is a node of type `FUNCTION_TYPE' that + describes the data type of the function. From this it is possible to obtain + the data types of the value and arguments (if known). + + When a call to a library function is being considered, FUNTYPE will contain + an identifier node for the library function. Thus, if you need to + distinguish among various library functions, you can do so by their names. + Note that "library function" in this context means a function used to + perform arithmetic, whose name is known specially in the compiler and was + not mentioned in the C code being compiled. + + STACK-SIZE is the number of bytes of arguments passed on the stack. If a + variable number of bytes is passed, it is zero, and argument popping will + always be the responsibility of the calling function. + + On the Vax, all functions always pop their arguments, so the definition of + this macro is STACK-SIZE. On the 68000, using the standard calling + convention, no functions pop their arguments, so the value of the macro is + always 0 in this case. But an alternative calling convention is available + in which functions that take a fixed number of arguments pop them but other + functions (such as `printf') pop nothing (the caller pops all). When this + convention is in use, FUNTYPE is examined to determine whether a function + takes a fixed number of arguments. */ +#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 + + +/* Function Arguments in Registers */ + +#define NUM_ARGUMENT_REGISTERS 8 +#define FIRST_ARGUMENT_REGISTER 2 + +#define STORMY16_WORD_SIZE(TYPE, MODE) \ + ((((TYPE) ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \ + + 1) \ + / 2) + +/* A C expression that controls whether a function argument is passed in a + register, and which register. + + The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes + (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) + all of the previous arguments so far passed in registers; MODE, the + machine mode of the argument; TYPE, the data type of the argument + as a tree node or 0 if that is not known (which happens for C + support library functions); and NAMED, which is 1 for an ordinary + argument and 0 for nameless arguments that correspond to `...' in + the called function's prototype. + + The value of the expression should either be a `reg' RTX for the hard + register in which to pass the argument, or zero to pass the argument on the + stack. + + For machines like the Vax and 68000, where normally all arguments are + pushed, zero suffices as a definition. + + The usual way to make the ANSI library `stdarg.h' work on a machine where + some arguments are usually passed in registers, is to cause nameless + arguments to be passed on the stack instead. This is done by making + `FUNCTION_ARG' return 0 whenever NAMED is 0. + + You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of + this macro to determine if this argument is of a type that must be passed in + the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG' + returns non-zero for such an argument, the compiler will abort. If + `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the + stack and then loaded into a register. */ +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ + ((MODE) == VOIDmode ? const0_rtx \ + : (CUM) + STORMY16_WORD_SIZE (TYPE, MODE) > NUM_ARGUMENT_REGISTERS ? 0 \ + : gen_rtx_REG (MODE, (CUM) + 2)) + +/* Define this macro if the target machine has "register windows", so that the + register in which a function sees an arguments is not necessarily the same + as the one in which the caller passed the argument. + + For such machines, `FUNCTION_ARG' computes the register in which the caller + passes the value, and `FUNCTION_INCOMING_ARG' should be defined in a similar + fashion to tell the function being called where the arguments will arrive. + + If `FUNCTION_INCOMING_ARG' is not defined, `FUNCTION_ARG' serves both + purposes. */ +/* #define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) */ + +/* A C expression for the number of words, at the beginning of an argument, + must be put in registers. The value must be zero for arguments that are + passed entirely in registers or that are entirely pushed on the stack. + + On some machines, certain arguments must be passed partially in registers + and partially in memory. On these machines, typically the first N words of + arguments are passed in registers, and the rest on the stack. If a + multi-word argument (a `double' or a structure) crosses that boundary, its + first few words must be passed in registers and the rest must be pushed. + This macro tells the compiler when this occurs, and how many of the words + should go in registers. + + `FUNCTION_ARG' for these arguments should return the first register to be + used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for + the called function. */ +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0 + +/* A C expression that indicates when an argument must be passed by reference. + If nonzero for an argument, a copy of that argument is made in memory and a + pointer to the argument is passed instead of the argument itself. The + pointer is passed in whatever way is appropriate for passing a pointer to + that type. + + On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable + definition of this macro might be + #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \ + MUST_PASS_IN_STACK (MODE, TYPE) */ +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0 + +/* If defined, a C expression that indicates when it is more + desirable to keep an argument passed by invisible reference as a + reference, rather than copying it to a pseudo register. */ +/* #define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) */ + +/* If defined, a C expression that indicates when it is the called function's + responsibility to make a copy of arguments passed by invisible reference. + Normally, the caller makes a copy and passes the address of the copy to the + routine being called. When FUNCTION_ARG_CALLEE_COPIES is defined and is + nonzero, the caller does not make a copy. Instead, it passes a pointer to + the "live" value. The called function must not modify this value. If it + can be determined that the value won't be modified, it need not make a copy; + otherwise a copy must be made. */ +/* #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) */ + +/* A C type for declaring a variable that is used as the first argument of + `FUNCTION_ARG' and other related values. For some target machines, the type + `int' suffices and can hold the number of bytes of argument so far. + + There is no need to record in `CUMULATIVE_ARGS' anything about the arguments + that have been passed on the stack. The compiler has other variables to + keep track of that. For target machines on which all arguments are passed + on the stack, there is no need to store anything in `CUMULATIVE_ARGS'; + however, the data structure must exist and should not be empty, so use + `int'. + + For this platform, the value of CUMULATIVE_ARGS is the number of words + of arguments that have been passed in registers so far. */ +typedef int CUMULATIVE_ARGS; + +/* A C statement (sans semicolon) for initializing the variable CUM for the + state at the beginning of the argument list. The variable has type + `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type + of the function which will receive the args, or 0 if the args are to a + compiler support library function. The value of INDIRECT is nonzero when + processing an indirect call, for example a call through a function pointer. + The value of INDIRECT is zero for a call to an explicitly named function, a + library function call, or when `INIT_CUMULATIVE_ARGS' is used to find + arguments for the function being compiled. + + When processing a call to a compiler support library function, LIBNAME + identifies which one. It is a `symbol_ref' rtx which contains the name of + the function, as a string. LIBNAME is 0 when an ordinary C function call is + being processed. Thus, each time this macro is called, either LIBNAME or + FNTYPE is nonzero, but never both of them at once. */ +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) (CUM) = 0 + +/* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of finding the + arguments for the function being compiled. If this macro is undefined, + `INIT_CUMULATIVE_ARGS' is used instead. + + The value passed for LIBNAME is always 0, since library routines with + special calling conventions are never compiled with GNU CC. The argument + LIBNAME exists for symmetry with `INIT_CUMULATIVE_ARGS'. */ +/* #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) */ + +/* A C statement (sans semicolon) to update the summarizer variable CUM to + advance past an argument in the argument list. The values MODE, TYPE and + NAMED describe that argument. Once this is done, the variable CUM is + suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. + + This macro need not do anything if the argument in question was passed on + the stack. The compiler knows how to track the amount of stack space used + for arguments without any special help. */ +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM) = stormy16_function_arg_advance (CUM, MODE, TYPE, NAMED)) + +/* If defined, a C expression which determines whether, and in which direction, + to pad out an argument with extra space. The value should be of type `enum + direction': either `upward' to pad above the argument, `downward' to pad + below, or `none' to inhibit padding. + + The *amount* of padding is always just enough to reach the next multiple of + `FUNCTION_ARG_BOUNDARY'; this macro does not control it. + + This macro has a default definition which is right for most systems. For + little-endian machines, the default is to pad upward. For big-endian + machines, the default is to pad downward for an argument of constant size + shorter than an `int', and upward otherwise. */ +/* #define FUNCTION_ARG_PADDING(MODE, TYPE) */ + +/* If defined, a C expression that gives the alignment boundary, in bits, of an + argument with the specified mode and type. If it is not defined, + `PARM_BOUNDARY' is used for all arguments. */ +/* #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) */ + +/* A C expression that is nonzero if REGNO is the number of a hard register in + which function arguments are sometimes passed. This does *not* include + implicit arguments such as the static chain and the structure-value address. + On many machines, no registers can be used for this purpose since all + function arguments are pushed on the stack. */ +#define FUNCTION_ARG_REGNO_P(REGNO) \ + ((REGNO) >= FIRST_ARGUMENT_REGISTER \ + && (REGNO) < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS) + + +/* How Scalar Function Values are Returned */ + +/* The number of the hard register that is used to return a scalar value from a + function call. */ +#define RETURN_VALUE_REGNUM FIRST_ARGUMENT_REGISTER + +/* Define this macro if `-traditional' should not cause functions declared to + return `float' to convert the value to `double'. */ +/* #define TRADITIONAL_RETURN_FLOAT */ + +/* A C expression to create an RTX representing the place where a function + returns a value of data type VALTYPE. VALTYPE is a tree node representing a + data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to + represent that type. On many machines, only the mode is relevant. + (Actually, on most machines, scalar values are returned in the same place + regardless of mode). + + If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion + rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type. + + If the precise function being called is known, FUNC is a tree node + (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it + possible to use a different value-returning convention for specific + functions when all their calls are known. + + `FUNCTION_VALUE' is not used for return vales with aggregate data types, + because these are returned in another way. See `STRUCT_VALUE_REGNUM' and + related macros, below. */ +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + stormy16_function_value (VALTYPE, FUNC) + + +/* Define this macro if the target machine has "register windows" so that the + register in which a function returns its value is not the same as the one in + which the caller sees the value. + + For such machines, `FUNCTION_VALUE' computes the register in which the + caller will see the value. `FUNCTION_OUTGOING_VALUE' should be defined in a + similar fashion to tell the function where to put the value. + + If `FUNCTION_OUTGOING_VALUE' is not defined, `FUNCTION_VALUE' serves both + purposes. + + `FUNCTION_OUTGOING_VALUE' is not used for return vales with aggregate data + types, because these are returned in another way. See `STRUCT_VALUE_REGNUM' + and related macros, below. */ +/* #define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) */ + +/* A C expression to create an RTX representing the place where a library + function returns a value of mode MODE. + + Note that "library function" in this context means a compiler support + routine, used to perform arithmetic, whose name is known specially by the + compiler and was not mentioned in the C code being compiled. + + The definition of `LIBRARY_VALUE' need not be concerned aggregate data + types, because none of the library functions returns such types. */ +#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, RETURN_VALUE_REGNUM) + +/* A C expression that is nonzero if REGNO is the number of a hard register in + which the values of called function may come back. + + A register whose use for returning values is limited to serving as the + second of a pair (for a value of type `double', say) need not be recognized + by this macro. So for most machines, this definition suffices: + + #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN) + + If the machine has register windows, so that the caller and the called + function use different registers for the return value, this macro should + recognize only the caller's register numbers. */ +#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RETURN_VALUE_REGNUM) + +/* Define this macro if `untyped_call' and `untyped_return' need more space + than is implied by `FUNCTION_VALUE_REGNO_P' for saving and restoring an + arbitrary return value. */ +/* #define APPLY_RESULT_SIZE */ + + +/* How Large Values are Returned */ + +/* A C expression which can inhibit the returning of certain function values in + registers, based on the type of value. A nonzero value says to return the + function value in memory, just as large structures are always returned. + Here TYPE will be a C expression of type `tree', representing the data type + of the value. + + Note that values of mode `BLKmode' must be explicitly handled by this macro. + Also, the option `-fpcc-struct-return' takes effect regardless of this + macro. On most systems, it is possible to leave the macro undefined; this + causes a default definition to be used, whose value is the constant 1 for + `BLKmode' values, and 0 otherwise. + + Do not use this macro to indicate that structures and unions should always + be returned in memory. You should instead use `DEFAULT_PCC_STRUCT_RETURN' + to indicate this. */ +#define RETURN_IN_MEMORY(TYPE) \ + (int_size_in_bytes (TYPE) > UNITS_PER_WORD * NUM_ARGUMENT_REGISTERS) + +/* Define this macro to be 1 if all structure and union return values must be + in memory. Since this results in slower code, this should be defined only + if needed for compatibility with other compilers or with an ABI. If you + define this macro to be 0, then the conventions used for structure and union + return values are decided by the `RETURN_IN_MEMORY' macro. + + If not defined, this defaults to the value 1. */ +/* #define DEFAULT_PCC_STRUCT_RETURN */ + +/* If the structure value address is passed in a register, then + `STRUCT_VALUE_REGNUM' should be the number of that register. */ +/* #define STRUCT_VALUE_REGNUM */ + +/* If the structure value address is not passed in a register, define + `STRUCT_VALUE' as an expression returning an RTX for the place where the + address is passed. If it returns 0, the address is passed as an "invisible" + first argument. */ +#define STRUCT_VALUE 0 + +/* On some architectures the place where the structure value address is found + by the called function is not the same place that the caller put it. This + can be due to register windows, or it could be because the function prologue + moves it to a different place. + + If the incoming location of the structure value address is in a register, + define this macro as the register number. */ +/* #define STRUCT_VALUE_INCOMING_REGNUM */ + +/* If the incoming location is not a register, then you should define + `STRUCT_VALUE_INCOMING' as an expression for an RTX for where the called + function should find the value. If it should find the value on the stack, + define this to create a `mem' which refers to the frame pointer. A + definition of 0 means that the address is passed as an "invisible" first + argument. */ +/* #define STRUCT_VALUE_INCOMING */ + +/* Define this macro if the usual system convention on the target machine for + returning structures and unions is for the called function to return the + address of a static variable containing the value. + + Do not define this if the usual system convention is for the caller to pass + an address to the subroutine. + + This macro has effect in `-fpcc-struct-return' mode, but it does nothing + when you use `-freg-struct-return' mode. */ +/* #define PCC_STATIC_STRUCT_RETURN */ + + +/* Caller-Saves Register Allocation */ + +/* Define this macro if function calls on the target machine do not preserve + any registers; in other words, if `CALL_USED_REGISTERS' has 1 for all + registers. This macro enables `-fcaller-saves' by default. Eventually that + option will be enabled by default on all machines and both the option and + this macro will be eliminated. */ +/* #define DEFAULT_CALLER_SAVES */ + +/* A C expression to determine whether it is worthwhile to consider placing a + pseudo-register in a call-clobbered hard register and saving and restoring + it around each function call. The expression should be 1 when this is worth + doing, and 0 otherwise. + + If you don't define this macro, a default is used which is good on most + machines: `4 * CALLS < REFS'. */ +/* #define CALLER_SAVE_PROFITABLE(REFS, CALLS) */ + + +/* Function Entry and Exit */ + +/* Define this macro as a C expression that is nonzero if the return + instruction or the function epilogue ignores the value of the stack pointer; + in other words, if it is safe to delete an instruction to adjust the stack + pointer before a return from the function. + + Note that this macro's value is relevant only for functions for which frame + pointers are maintained. It is never safe to delete a final stack + adjustment in a function that has no frame pointer, and the compiler knows + this regardless of `EXIT_IGNORE_STACK'. */ +/* #define EXIT_IGNORE_STACK */ + +/* Define this macro as a C expression that is nonzero for registers + are used by the epilogue or the `return' pattern. The stack and + frame pointer registers are already be assumed to be used as + needed. */ +#define EPILOGUE_USES(REGNO) \ + stormy16_epilogue_uses (REGNO) + +/* Define this macro if the function epilogue contains delay slots to which + instructions from the rest of the function can be "moved". The definition + should be a C expression whose value is an integer representing the number + of delay slots there. */ +/* #define DELAY_SLOTS_FOR_EPILOGUE */ + +/* A C expression that returns 1 if INSN can be placed in delay slot number N + of the epilogue. + + The argument N is an integer which identifies the delay slot now being + considered (since different slots may have different rules of eligibility). + It is never negative and is always less than the number of epilogue delay + slots (what `DELAY_SLOTS_FOR_EPILOGUE' returns). If you reject a particular + insn for a given delay slot, in principle, it may be reconsidered for a + subsequent delay slot. Also, other insns may (at least in principle) be + considered for the so far unfilled delay slot. + + The insns accepted to fill the epilogue delay slots are put in an + RTL list made with `insn_list' objects, stored in the variable + `current_function_epilogue_delay_list'. The insn for the first + delay slot comes first in the list. Your definition of the macro + `FUNCTION_EPILOGUE' should fill the delay slots by outputting the + insns in this list, usually by calling `final_scan_insn'. + + You need not define this macro if you did not define + `DELAY_SLOTS_FOR_EPILOGUE'. */ +/* #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) */ + +/* A C compound statement that outputs the assembler code for a thunk function, + used to implement C++ virtual function calls with multiple inheritance. The + thunk acts as a wrapper around a virtual function, adjusting the implicit + object parameter before handing control off to the real function. + + First, emit code to add the integer DELTA to the location that contains the + incoming first argument. Assume that this argument contains a pointer, and + is the one used to pass the `this' pointer in C++. This is the incoming + argument *before* the function prologue, e.g. `%o0' on a sparc. The + addition must preserve the values of all other incoming arguments. + + After the addition, emit code to jump to FUNCTION, which is a + `FUNCTION_DECL'. This is a direct pure jump, not a call, and does not touch + the return address. Hence returning from FUNCTION will return to whoever + called the current `thunk'. + + The effect must be as if FUNCTION had been called directly with the adjusted + first argument. This macro is responsible for emitting all of the code for + a thunk function; `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' are not + invoked. + + The THUNK_FNDECL is redundant. (DELTA and FUNCTION have already been + extracted from it.) It might possibly be useful on some targets, but + probably not. + + If you do not define this macro, the target-independent code in the C++ + frontend will generate a less efficient heavyweight thunk that calls + FUNCTION instead of jumping to it. The generic approach does not support + varargs. */ +#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ +{ \ + fprintf (FILE, "\tadd r2,#0x%x\n", (DELTA) & 0xFFFF); \ + fputs ("\tjmpf ", FILE); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (function), 0), 0)); \ + putc ('\n', FILE); \ +} + + +/* Generating Code for Profiling. */ + +/* A C statement or compound statement to output to FILE some assembler code to + call the profiling subroutine `mcount'. Before calling, the assembler code + must load the address of a counter variable into a register where `mcount' + expects to find the address. The name of this variable is `LP' followed by + the number LABELNO, so you would generate the name using `LP%d' in a + `fprintf'. + + The details of how the address should be passed to `mcount' are determined + by your operating system environment, not by GNU CC. To figure them out, + compile a small program for profiling using the system's installed C + compiler and look at the assembler code that results. + + This declaration must be present, but it can be an abort if profiling is + not implemented. */ + +#define FUNCTION_PROFILER(FILE, LABELNO) abort () + +/* Define this macro if the code for function profiling should come before the + function prologue. Normally, the profiling code comes after. */ +/* #define PROFILE_BEFORE_PROLOGUE */ + +/* A C statement or compound statement to output to FILE some assembler code to + initialize basic-block profiling for the current object module. The global + compile flag `profile_block_flag' distingishes two profile modes. + + profile_block_flag != 2' + Output code to call the subroutine `__bb_init_func' once per + object module, passing it as its sole argument the address of + a block allocated in the object module. + + The name of the block is a local symbol made with this + statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, + you can take a short cut in the definition of this macro and + use the name that you know will result. + + The first word of this block is a flag which will be nonzero + if the object module has already been initialized. So test + this word first, and do not call `__bb_init_func' if the flag + is nonzero. BLOCK_OR_LABEL contains a unique number which + may be used to generate a label as a branch destination when + `__bb_init_func' will not be called. + + Described in assembler language, the code to be output looks + like: + + cmp (LPBX0),0 + bne local_label + parameter1 <- LPBX0 + call __bb_init_func + local_label: + + profile_block_flag == 2' + Output code to call the subroutine `__bb_init_trace_func' and + pass two parameters to it. The first parameter is the same as + for `__bb_init_func'. The second parameter is the number of + the first basic block of the function as given by + BLOCK_OR_LABEL. Note that `__bb_init_trace_func' has to be + called, even if the object module has been initialized + already. + + Described in assembler language, the code to be output looks + like: + parameter1 <- LPBX0 + parameter2 <- BLOCK_OR_LABEL + call __bb_init_trace_func */ +/* #define FUNCTION_BLOCK_PROFILER (FILE, LABELNO) */ + +/* A C statement or compound statement to output to FILE some assembler code to + increment the count associated with the basic block number BLOCKNO. The + global compile flag `profile_block_flag' distingishes two profile modes. + + profile_block_flag != 2' + Output code to increment the counter directly. Basic blocks + are numbered separately from zero within each compilation. + The count associated with block number BLOCKNO is at index + BLOCKNO in a vector of words; the name of this array is a + local symbol made with this statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, + you can take a short cut in the definition of this macro and + use the name that you know will result. + + Described in assembler language, the code to be output looks + like: + + inc (LPBX2+4*BLOCKNO) + + profile_block_flag == 2' + Output code to initialize the global structure `__bb' and + call the function `__bb_trace_func', which will increment the + counter. + + `__bb' consists of two words. In the first word, the current + basic block number, as given by BLOCKNO, has to be stored. In + the second word, the address of a block allocated in the + object module has to be stored. The address is given by the + label created with this statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + + Described in assembler language, the code to be output looks + like: + move BLOCKNO -> (__bb) + move LPBX0 -> (__bb+4) + call __bb_trace_func */ +/* #define BLOCK_PROFILER(FILE, BLOCKNO) */ + +/* A C statement or compound statement to output to FILE assembler + code to call function `__bb_trace_ret'. The assembler code should + only be output if the global compile flag `profile_block_flag' == + 2. This macro has to be used at every place where code for + returning from a function is generated (e.g. `FUNCTION_EPILOGUE'). + Although you have to write the definition of `FUNCTION_EPILOGUE' + as well, you have to define this macro to tell the compiler, that + the proper call to `__bb_trace_ret' is produced. */ +/* #define FUNCTION_BLOCK_PROFILER_EXIT(FILE) */ + +/* A C statement or compound statement to save all registers, which may be + clobbered by a function call, including condition codes. The `asm' + statement will be mostly likely needed to handle this task. Local labels in + the assembler code can be concatenated with the string ID, to obtain a + unique lable name. + + Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or + `FUNCTION_EPILOGUE' must be saved in the macros `FUNCTION_BLOCK_PROFILER', + `FUNCTION_BLOCK_PROFILER_EXIT' and `BLOCK_PROFILER' prior calling + `__bb_init_trace_func', `__bb_trace_ret' and `__bb_trace_func' respectively. */ +/* #define MACHINE_STATE_SAVE(ID) */ + +/* A C statement or compound statement to restore all registers, including + condition codes, saved by `MACHINE_STATE_SAVE'. + + Registers or condition codes clobbered by `FUNCTION_PROLOGUE' or + `FUNCTION_EPILOGUE' must be restored in the macros + `FUNCTION_BLOCK_PROFILER', `FUNCTION_BLOCK_PROFILER_EXIT' and + `BLOCK_PROFILER' after calling `__bb_init_trace_func', `__bb_trace_ret' and + `__bb_trace_func' respectively. */ +/* #define MACHINE_STATE_RESTORE(ID) */ + +/* A C function or functions which are needed in the library to support block + profiling. */ +/* #define BLOCK_PROFILER_CODE */ + + +/* If the target has particular reasons why a function cannot be inlined, + it may define the TARGET_CANNOT_INLINE_P. This macro takes one argument, + the DECL describing the function. The function should NULL if the function + *can* be inlined. Otherwise it should return a pointer to a string containing + a message describing why the function could not be inlined. The message will + displayed if the '-Winline' command line switch has been given. If the message + contains a '%s' sequence, this will be replaced by the name of the function. */ +/* #define TARGET_CANNOT_INLINE_P(FN_DECL) stormy16_cannot_inline_p (FN_DECL) */ + +/* Implementing the Varargs Macros. */ + +/* If defined, is a C expression that produces the machine-specific code for a + call to `__builtin_saveregs'. This code will be moved to the very beginning + of the function, before any parameter access are made. The return value of + this function should be an RTX that contains the value to use as the return + of `__builtin_saveregs'. + + If this macro is not defined, the compiler will output an ordinary call to + the library function `__builtin_saveregs'. */ +/* #define EXPAND_BUILTIN_SAVEREGS() */ + +/* This macro offers an alternative to using `__builtin_saveregs' and defining + the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register + arguments into the stack so that all the arguments appear to have been + passed consecutively on the stack. Once this is done, you can use the + standard implementation of varargs that works for machines that pass all + their arguments on the stack. + + The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing + the values that obtain after processing of the named arguments. The + arguments MODE and TYPE describe the last named argument--its machine mode + and its data type as a tree node. + + The macro implementation should do two things: first, push onto the stack + all the argument registers *not* used for the named arguments, and second, + store the size of the data thus pushed into the `int'-valued variable whose + name is supplied as the argument PRETEND_ARGS_SIZE. The value that you + store here will serve as additional offset for setting up the stack frame. + + Because you must generate code to push the anonymous arguments at compile + time without knowing their data types, `SETUP_INCOMING_VARARGS' is only + useful on machines that have just a single category of argument register and + use it uniformly for all data types. + + If the argument SECOND_TIME is nonzero, it means that the arguments of the + function are being analyzed for the second time. This happens for an inline + function, which is not actually compiled until the end of the source file. + The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in + this case. */ +#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \ + if (! SECOND_TIME) \ + stormy16_setup_incoming_varargs (ARGS_SO_FAR, MODE, TYPE, & PRETEND_ARGS_SIZE) + +/* Define this macro if the location where a function argument is passed + depends on whether or not it is a named argument. + + This macro controls how the NAMED argument to `FUNCTION_ARG' is set for + varargs and stdarg functions. With this macro defined, the NAMED argument + is always true for named arguments, and false for unnamed arguments. If + this is not defined, but `SETUP_INCOMING_VARARGS' is defined, then all + arguments are treated as named. Otherwise, all named arguments except the + last are treated as named. */ +/* #define STRICT_ARGUMENT_NAMING 1 */ + +/* Build up the stdarg/varargs va_list type tree, assinging it to NODE. If not + defined, it is assumed that va_list is a void * pointer. */ +#define BUILD_VA_LIST_TYPE(NODE) \ + ((NODE) = stormy16_build_va_list ()) + +/* Implement the stdarg/varargs va_start macro. STDARG_P is non-zero if this + is stdarg.h instead of varargs.h. VALIST is the tree of the va_list + variable to initialize. NEXTARG is the machine independent notion of the + 'next' argument after the variable arguments. If not defined, a standard + implementation will be defined that works for arguments passed on the stack. */ +#define EXPAND_BUILTIN_VA_START(STDARG_P, VALIST, NEXTARG) \ + stormy16_expand_builtin_va_start (STDARG_P, VALIST, NEXTARG) + +/* Implement the stdarg/varargs va_arg macro. VALIST is the variable of type + va_list as a tree, TYPE is the type passed to va_arg. */ +#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \ + stormy16_expand_builtin_va_arg (VALIST, TYPE) + +/* Implement the stdarg/varargs va_end macro. VALIST is the variable of type + va_list as a tree. */ +/* #define EXPAND_BUILTIN_VA_END(VALIST) */ + + +/* Trampolines for Nested Functions. */ + +/* A C statement to output, on the stream FILE, assembler code for a block of + data that contains the constant parts of a trampoline. This code should not + include a label--the label is taken care of automatically. */ +/* #define TRAMPOLINE_TEMPLATE(FILE) */ + +/* The name of a subroutine to switch to the section in which the trampoline + template is to be placed. The default is a value of `readonly_data_section', + which places the trampoline in the section containing read-only data. */ +/* #define TRAMPOLINE_SECTION */ + +/* A C expression for the size in bytes of the trampoline, as an integer. */ +#define TRAMPOLINE_SIZE 8 + +/* Alignment required for trampolines, in bits. + + If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for + aligning trampolines. */ +#define TRAMPOLINE_ALIGNMENT 16 + +/* A C statement to initialize the variable parts of a trampoline. ADDR is an + RTX for the address of the trampoline; FNADDR is an RTX for the address of + the nested function; STATIC_CHAIN is an RTX for the static chain value that + should be passed to the function when it is called. */ +#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \ + stormy16_initialize_trampoline (ADDR, FNADDR, STATIC_CHAIN) + +/* A C expression to allocate run-time space for a trampoline. The expression + value should be an RTX representing a memory reference to the space for the + trampoline. + + If this macro is not defined, by default the trampoline is allocated as a + stack slot. This default is right for most machines. The exceptions are + machines where it is impossible to execute instructions in the stack area. + On such machines, you may have to implement a separate stack, using this + macro in conjunction with `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE'. + + FP points to a data structure, a `struct function', which describes the + compilation status of the immediate containing function of the function + which the trampoline is for. Normally (when `ALLOCATE_TRAMPOLINE' is not + defined), the stack slot for the trampoline is in the stack frame of this + containing function. Other allocation strategies probably must do something + analogous with this information. */ +/* #define ALLOCATE_TRAMPOLINE(FP) */ + +/* Implementing trampolines is difficult on many machines because they have + separate instruction and data caches. Writing into a stack location fails + to clear the memory in the instruction cache, so when the program jumps to + that location, it executes the old contents. + + Here are two possible solutions. One is to clear the relevant parts of the + instruction cache whenever a trampoline is set up. The other is to make all + trampolines identical, by having them jump to a standard subroutine. The + former technique makes trampoline execution faster; the latter makes + initialization faster. + + To clear the instruction cache when a trampoline is initialized, define the + following macros which describe the shape of the cache. */ + +/* The total size in bytes of the cache. */ +/* #define INSN_CACHE_SIZE */ + +/* The length in bytes of each cache line. The cache is divided into cache + lines which are disjoint slots, each holding a contiguous chunk of data + fetched from memory. Each time data is brought into the cache, an entire + line is read at once. The data loaded into a cache line is always aligned + on a boundary equal to the line size. */ +/* #define INSN_CACHE_LINE_WIDTH */ + +/* The number of alternative cache lines that can hold any particular memory + location. */ +/* #define INSN_CACHE_DEPTH */ + +/* Alternatively, if the machine has system calls or instructions to clear the + instruction cache directly, you can define the following macro. */ + +/* If defined, expands to a C expression clearing the *instruction cache* in + the specified interval. If it is not defined, and the macro INSN_CACHE_SIZE + is defined, some generic code is generated to clear the cache. The + definition of this macro would typically be a series of `asm' statements. + Both BEG and END are both pointer expressions. */ +/* #define CLEAR_INSN_CACHE (BEG, END) */ + +/* To use a standard subroutine, define the following macro. In addition, you + must make sure that the instructions in a trampoline fill an entire cache + line with identical instructions, or else ensure that the beginning of the + trampoline code is always aligned at the same point in its cache line. Look + in `m68k.h' as a guide. */ + +/* Define this macro if trampolines need a special subroutine to do their work. + The macro should expand to a series of `asm' statements which will be + compiled with GNU CC. They go in a library function named + `__transfer_from_trampoline'. + + If you need to avoid executing the ordinary prologue code of a compiled C + function when you jump to the subroutine, you can do so by placing a special + label of your own in the assembler code. Use one `asm' statement to + generate an assembler label, and another to make the label global. Then + trampolines can use that label to jump directly to your special assembler + code. */ +/* #define TRANSFER_FROM_TRAMPOLINE */ + + +/* Implicit Calls to Library Routines */ + +/* A C string constant giving the name of the function to call for + multiplication of one signed full-word by another. If you do not define + this macro, the default name is used, which is `__mulsi3', a function + defined in `libgcc.a'. */ +/* #define MULSI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for division of + one signed full-word by another. If you do not define this macro, the + default name is used, which is `__divsi3', a function defined in `libgcc.a'. */ +/* #define DIVSI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for division of + one unsigned full-word by another. If you do not define this macro, the + default name is used, which is `__udivsi3', a function defined in + `libgcc.a'. */ +/* #define UDIVSI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for the + remainder in division of one signed full-word by another. If you do not + define this macro, the default name is used, which is `__modsi3', a function + defined in `libgcc.a'. */ +/* #define MODSI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for the + remainder in division of one unsigned full-word by another. If you do not + define this macro, the default name is used, which is `__umodsi3', a + function defined in `libgcc.a'. */ +/* #define UMODSI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for + multiplication of one signed double-word by another. If you do not define + this macro, the default name is used, which is `__muldi3', a function + defined in `libgcc.a'. */ +/* #define MULDI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for division of + one signed double-word by another. If you do not define this macro, the + default name is used, which is `__divdi3', a function defined in `libgcc.a'. */ +/* #define DIVDI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for division of + one unsigned full-word by another. If you do not define this macro, the + default name is used, which is `__udivdi3', a function defined in + `libgcc.a'. */ +/* #define UDIVDI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for the + remainder in division of one signed double-word by another. If you do not + define this macro, the default name is used, which is `__moddi3', a function + defined in `libgcc.a'. */ +/* #define MODDI3_LIBCALL */ + +/* A C string constant giving the name of the function to call for the + remainder in division of one unsigned full-word by another. If you do not + define this macro, the default name is used, which is `__umoddi3', a + function defined in `libgcc.a'. */ +/* #define UMODDI3_LIBCALL */ + +/* Define this macro as a C statement that declares additional library routines + renames existing ones. `init_optabs' calls this macro after initializing all + the normal library routines. */ +/* #define INIT_TARGET_OPTABS */ + +/* The value of `EDOM' on the target machine, as a C integer constant + expression. If you don't define this macro, GNU CC does not attempt to + deposit the value of `EDOM' into `errno' directly. Look in + `/usr/include/errno.h' to find the value of `EDOM' on your system. + + If you do not define `TARGET_EDOM', then compiled code reports domain errors + by calling the library function and letting it report the error. If + mathematical functions on your system use `matherr' when there is an error, + then you should leave `TARGET_EDOM' undefined so that `matherr' is used + normally. */ +/* #define TARGET_EDOM */ + +/* Define this macro as a C expression to create an rtl expression that refers + to the global "variable" `errno'. (On certain systems, `errno' may not + actually be a variable.) If you don't define this macro, a reasonable + default is used. */ +/* #define GEN_ERRNO_RTX */ + +/* Define this macro if GNU CC should generate calls to the System V (and ANSI + C) library functions `memcpy' and `memset' rather than the BSD functions + `bcopy' and `bzero'. + + Defined in svr4.h. */ +#define TARGET_MEM_FUNCTIONS + +/* Define this macro if only `float' arguments cannot be passed to library + routines (so they must be converted to `double'). This macro affects both + how library calls are generated and how the library routines in `libgcc1.c' + accept their arguments. It is useful on machines where floating and fixed + point arguments are passed differently, such as the i860. */ +/* #define LIBGCC_NEEDS_DOUBLE */ + +/* Define this macro to override the type used by the library routines to pick + up arguments of type `float'. (By default, they use a union of `float' and + `int'.) + + The obvious choice would be `float'--but that won't work with traditional C + compilers that expect all arguments declared as `float' to arrive as + `double'. To avoid this conversion, the library routines ask for the value + as some other type and then treat it as a `float'. + + On some systems, no other type will work for this. For these systems, you + must use `LIBGCC_NEEDS_DOUBLE' instead, to force conversion of the values + `double' before they are passed. */ +/* #define FLOAT_ARG_TYPE */ + +/* Define this macro to override the way library routines redesignate a `float' + argument as a `float' instead of the type it was passed as. The default is + an expression which takes the `float' field of the union. */ +/* #define FLOATIFY(PASSED_VALUE) */ + +/* Define this macro to override the type used by the library routines to + return values that ought to have type `float'. (By default, they use + `int'.) + + The obvious choice would be `float'--but that won't work with traditional C + compilers gratuitously convert values declared as `float' into `double'. */ +/* #define FLOAT_VALUE_TYPE */ + +/* Define this macro to override the way the value of a `float'-returning + library routine should be packaged in order to return it. These functions + are actually declared to return type `FLOAT_VALUE_TYPE' (normally `int'). + + These values can't be returned as type `float' because traditional C + compilers would gratuitously convert the value to a `double'. + + A local variable named `intify' is always available when the macro `INTIFY' + is used. It is a union of a `float' field named `f' and a field named `i' + whose type is `FLOAT_VALUE_TYPE' or `int'. + + If you don't define this macro, the default definition works by copying the + value through that union. */ +/* #define INTIFY(FLOAT_VALUE) */ + +/* Define this macro as the name of the data type corresponding to `SImode' in + the system's own C compiler. + + You need not define this macro if that type is `long int', as it usually is. */ +/* #define nongcc_SI_type */ + +/* Define this macro as the name of the data type corresponding to the + word_mode in the system's own C compiler. + + You need not define this macro if that type is `long int', as it usually is. */ +/* #define nongcc_word_type */ + +/* Define these macros to supply explicit C statements to carry out various + arithmetic operations on types `float' and `double' in the library routines + in `libgcc1.c'. See that file for a full list of these macros and their + arguments. + + On most machines, you don't need to define any of these macros, because the + C compiler that comes with the system takes care of doing them. */ +/* #define perform_... */ + +/* Define this macro to generate code for Objective C message sending using the + calling convention of the NeXT system. This calling convention involves + passing the object, the selector and the method arguments all at once to the + method-lookup library function. + + The default calling convention passes just the object and the selector to + the lookup function, which returns a pointer to the method. */ +/* #define NEXT_OBJC_RUNTIME */ + + +/* Addressing Modes */ + +/* Define this macro if the machine supports post-increment addressing. */ +#define HAVE_POST_INCREMENT 1 + +/* Similar for other kinds of addressing. */ +/* #define HAVE_PRE_INCREMENT 1 */ +/* #define HAVE_POST_DECREMENT 1 */ +#define HAVE_PRE_DECREMENT 1 + +/* A C expression that is 1 if the RTX X is a constant which is a valid + address. On most machines, this can be defined as `CONSTANT_P (X)', but a + few machines are more restrictive in which constant addresses are supported. + + `CONSTANT_P' accepts integer-values expressions whose values are not + explicitly known, such as `symbol_ref', `label_ref', and `high' expressions + and `const' arithmetic expressions, in addition to `const_int' and + `const_double' expressions. */ +#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X) + +/* A number, the maximum number of registers that can appear in a valid memory + address. Note that it is up to you to specify a value equal to the maximum + number that `GO_IF_LEGITIMATE_ADDRESS' would ever accept. */ +#define MAX_REGS_PER_ADDRESS 1 + +/* A C compound statement with a conditional `goto LABEL;' executed if X (an + RTX) is a legitimate memory address on the target machine for a memory + operand of mode MODE. + + It usually pays to define several simpler macros to serve as subroutines for + this one. Otherwise it may be too complicated to understand. + + This macro must exist in two variants: a strict variant and a non-strict + one. The strict variant is used in the reload pass. It must be defined so + that any pseudo-register that has not been allocated a hard register is + considered a memory reference. In contexts where some kind of register is + required, a pseudo-register with no hard register must be rejected. + + The non-strict variant is used in other passes. It must be defined to + accept all pseudo-registers in every context where some kind of register is + required. + + Compiler source files that want to use the strict variant of this macro + define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT' + conditional to define the strict variant in that case and the non-strict + variant otherwise. + + Subroutines to check for acceptable registers for various purposes (one for + base registers, one for index registers, and so on) are typically among the + subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these + subroutine macros need have two variants; the higher levels of macros may be + the same whether strict or not. + + Normally, constant addresses which are the sum of a `symbol_ref' and an + integer are stored inside a `const' RTX to mark them as constant. + Therefore, there is no need to recognize such sums specifically as + legitimate addresses. Normally you would simply recognize any `const' as + legitimate. + + Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that + are not marked with `const'. It assumes that a naked `plus' indicates + indexing. If so, then you *must* reject such naked constant sums as + illegitimate addresses, so that none of them will be given to + `PRINT_OPERAND_ADDRESS'. + + On some machines, whether a symbolic address is legitimate depends on the + section that the address refers to. On these machines, define the macro + `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and + then check for it here. When you see a `const', you will have to look + inside it to find the `symbol_ref' in order to determine the section. + + The best way to modify the name string is by adding text to the beginning, + with suitable punctuation to prevent any ambiguity. Allocate the new name + in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to + remove and decode the added text and output the name accordingly, and define + `STRIP_NAME_ENCODING' to access the original name string. + + You can check the information stored here into the `symbol_ref' in the + definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and + `PRINT_OPERAND_ADDRESS'. */ +#ifdef REG_OK_STRICT +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ +do { \ + if (stormy16_legitimate_address_p (MODE, X, 1)) \ + goto LABEL; \ +} while (0) +#else +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ +do { \ + if (stormy16_legitimate_address_p (MODE, X, 0)) \ + goto LABEL; \ +} while (0) +#endif +/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for + use as a base register. For hard registers, it should always accept those + which the hardware permits and reject the others. Whether the macro accepts + or rejects pseudo registers must be controlled by `REG_OK_STRICT' as + described above. This usually requires two variant definitions, of which + `REG_OK_STRICT' controls the one actually used. */ +#ifdef REG_OK_STRICT +#define REG_OK_FOR_BASE_P(X) \ + (REGNO_OK_FOR_BASE_P (REGNO (X)) && (REGNO (X) < FIRST_PSEUDO_REGISTER)) +#else +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#endif + +/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for + use as an index register. + + The difference between an index register and a base register is that the + index register may be scaled. If an address involves the sum of two + registers, neither one of them scaled, then either one may be labeled the + "base" and the other the "index"; but whichever labeling is used must fit + the machine's constraints of which registers may serve in each capacity. + The compiler will try both labelings, looking for one that is valid, and + will reload one or both registers only if neither labeling works. */ +#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) + +/* A C compound statement that attempts to replace X with a valid memory + address for an operand of mode MODE. WIN will be a C statement label + elsewhere in the code; the macro definition may use + + GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); + + to avoid further processing if the address has become legitimate. + + X will always be the result of a call to `break_out_memory_refs', and OLDX + will be the operand that was given to that function to produce X. + + The code generated by this macro should not alter the substructure of X. If + it transforms X into a more legitimate form, it should assign X (which will + always be a C variable) a new value. + + It is not necessary for this macro to come up with a legitimate address. + The compiler has standard ways of doing so in all cases. In fact, it is + safe for this macro to do nothing. But often a machine-dependent strategy + can generate better code. */ +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) + +/* A C statement or compound statement with a conditional `goto LABEL;' + executed if memory address X (an RTX) can have different meanings depending + on the machine mode of the memory reference it is used for or if the address + is valid for some modes but not others. + + Autoincrement and autodecrement addresses typically have mode-dependent + effects because the amount of the increment or decrement is the size of the + operand being addressed. Some machines have other mode-dependent addresses. + Many RISC machines have no mode-dependent addresses. + + You may assume that ADDR is a valid address for the machine. + + On this chip, this is true if the address is valid with an offset + of 0 but not of 6, because in that case it cannot be used as an + address for DImode or DFmode, or if the address is a post-increment + or pre-decrement address. +*/ +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ + if (stormy16_mode_dependent_address_p (ADDR)) \ + goto LABEL + +/* A C expression that is nonzero if X is a legitimate constant for an + immediate operand on the target machine. You can assume that X satisfies + `CONSTANT_P', so you need not check this. In fact, `1' is a suitable + definition for this macro on machines where anything `CONSTANT_P' is valid. */ +#define LEGITIMATE_CONSTANT_P(X) 1 + + +/* Condition Code Status */ + +/* C code for a data type which is used for declaring the `mdep' component of + `cc_status'. It defaults to `int'. + + This macro is not used on machines that do not use `cc0'. */ +/* #define CC_STATUS_MDEP */ + +/* A C expression to initialize the `mdep' field to "empty". The default + definition does nothing, since most machines don't use the field anyway. If + you want to use the field, you should probably define this macro to + initialize it. + + This macro is not used on machines that do not use `cc0'. */ +/* #define CC_STATUS_MDEP_INIT */ + +/* A C compound statement to set the components of `cc_status' appropriately + for an insn INSN whose body is EXP. It is this macro's responsibility to + recognize insns that set the condition code as a byproduct of other activity + as well as those that explicitly set `(cc0)'. + + This macro is not used on machines that do not use `cc0'. + + If there are insns that do not set the condition code but do alter other + machine registers, this macro must check to see whether they invalidate the + expressions that the condition code is recorded as reflecting. For example, + on the 68000, insns that store in address registers do not set the condition + code, which means that usually `NOTICE_UPDATE_CC' can leave `cc_status' + unaltered for such insns. But suppose that the previous insn set the + condition code based on location `a4@(102)' and the current insn stores a + new value in `a4'. Although the condition code is not changed by this, it + will no longer be true that it reflects the contents of `a4@(102)'. + Therefore, `NOTICE_UPDATE_CC' must alter `cc_status' in this case to say + that nothing is known about the condition code value. + + The definition of `NOTICE_UPDATE_CC' must be prepared to deal with the + results of peephole optimization: insns whose patterns are `parallel' RTXs + containing various `reg', `mem' or constants which are just the operands. + The RTL structure of these insns is not sufficient to indicate what the + insns actually do. What `NOTICE_UPDATE_CC' should do when it sees one is + just to run `CC_STATUS_INIT'. + + A possible definition of `NOTICE_UPDATE_CC' is to call a function that looks + at an attribute named, for example, `cc'. This avoids having detailed + information about patterns in two places, the `md' file and in + `NOTICE_UPDATE_CC'. */ +/* #define NOTICE_UPDATE_CC(EXP, INSN) */ + +/* A list of names to be used for additional modes for condition code values in + registers. These names are added to `enum machine_mode' and all have class + `MODE_CC'. By convention, they should start with `CC' and end with `mode'. + + You should only define this macro if your machine does not use `cc0' and + only if additional modes are required. */ +/* #define EXTRA_CC_MODES */ + +/* Returns a mode from class `MODE_CC' to be used when comparison operation + code OP is applied to rtx X and Y. For example, on the Sparc, + `SELECT_CC_MODE' is defined as (see *note Jump Patterns::. for a + description of the reason for this definition) + + #define SELECT_CC_MODE(OP,X,Y) \ + (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ + ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ + : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ + || GET_CODE (X) == NEG) \ + ? CC_NOOVmode : CCmode)) + + You need not define this macro if `EXTRA_CC_MODES' is not defined. */ +/* #define SELECT_CC_MODE(OP, X, Y) */ + +/* One some machines not all possible comparisons are defined, but you can + convert an invalid comparison into a valid one. For example, the Alpha does + not have a `GT' comparison, but you can use an `LT' comparison instead and + swap the order of the operands. + + On such machines, define this macro to be a C statement to do any required + conversions. CODE is the initial comparison code and OP0 and OP1 are the + left and right operands of the comparison, respectively. You should modify + CODE, OP0, and OP1 as required. + + GNU CC will not assume that the comparison resulting from this macro is + valid but will see if the resulting insn matches a pattern in the `md' file. + + You need not define this macro if it would never change the comparison code + or operands. */ +/* #define CANONICALIZE_COMPARISON(CODE, OP0, OP1) */ + +/* A C expression whose value is one if it is always safe to reverse a + comparison whose mode is MODE. If `SELECT_CC_MODE' can ever return MODE for + a floating-point inequality comparison, then `REVERSIBLE_CC_MODE (MODE)' + must be zero. + + You need not define this macro if it would always returns zero or if the + floating-point format is anything other than `IEEE_FLOAT_FORMAT'. For + example, here is the definition used on the Sparc, where floating-point + inequality comparisons are always given `CCFPEmode': + + #define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) */ +/* #define REVERSIBLE_CC_MODE(MODE) */ + + +/* Describing Relative Costs of Operations */ + +/* A part of a C `switch' statement that describes the relative costs of + constant RTL expressions. It must contain `case' labels for expression + codes `const_int', `const', `symbol_ref', `label_ref' and `const_double'. + Each case must ultimately reach a `return' statement to return the relative + cost of the use of that kind of constant value in an expression. The cost + may depend on the precise value of the constant, which is available for + examination in X, and the rtx code of the expression in which it is + contained, found in OUTER_CODE. + + CODE is the expression code--redundant, since it can be obtained with + `GET_CODE (X)'. */ +/* #define CONST_COSTS(X, CODE, OUTER_CODE) */ + +/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. This can be + used, for example, to indicate how costly a multiply instruction is. In + writing this macro, you can use the construct `COSTS_N_INSNS (N)' to specify + a cost equal to N fast instructions. OUTER_CODE is the code of the + expression in which X is contained. + + This macro is optional; do not define it if the default cost assumptions are + adequate for the target machine. */ +/* #define RTX_COSTS(X, CODE, OUTER_CODE) */ + +/* An expression giving the cost of an addressing mode that contains ADDRESS. + If not defined, the cost is computed from the ADDRESS expression and the + `CONST_COSTS' values. + + For most CISC machines, the default cost is a good approximation of the true + cost of the addressing mode. However, on RISC machines, all instructions + normally have the same length and execution time. Hence all addresses will + have equal costs. + + In cases where more than one form of an address is known, the form with the + lowest cost will be used. If multiple forms have the same, lowest, cost, + the one that is the most complex will be used. + + For example, suppose an address that is equal to the sum of a register and a + constant is used twice in the same basic block. When this macro is not + defined, the address will be computed in a register and memory references + will be indirect through that register. On machines where the cost of the + addressing mode containing the sum is no higher than that of a simple + indirect reference, this will produce an additional instruction and possibly + require an additional register. Proper specification of this macro + eliminates this overhead for such machines. + + Similar use of this macro is made in strength reduction of loops. + + ADDRESS need not be valid as an address. In such a case, the cost is not + relevant and can be any value; invalid addresses need not be assigned a + different cost. + + On machines where an address involving more than one register is as cheap as + an address computation involving only one register, defining `ADDRESS_COST' + to reflect this can cause two registers to be live over a region of code + where only one would have been if `ADDRESS_COST' were not defined in that + manner. This effect should be considered in the definition of this macro. + Equivalent costs should probably only be given to addresses with different + numbers of registers on machines with lots of registers. + + This macro will normally either not be defined or be defined as a constant. */ +/* #define ADDRESS_COST(ADDRESS) */ + +/* A C expression for the cost of moving data of mode MODE from a + register in class FROM to one in class TO. The classes are + expressed using the enumeration values such as `GENERAL_REGS'. A + value of 4 is the default; other values are interpreted relative to + that. + + It is not required that the cost always equal 2 when FROM is the same as TO; + on some machines it is expensive to move between registers if they are not + general registers. + + If reload sees an insn consisting of a single `set' between two hard + registers, and if `REGISTER_MOVE_COST' applied to their classes returns a + value of 2, reload does not check to ensure that the constraints of the insn + are met. Setting a cost of other than 2 will allow reload to verify that + the constraints are met. You should do this if the `movM' pattern's + constraints do not allow such copying. */ +#define REGISTER_MOVE_COST(MODE, FROM, TO) 2 + +/* A C expression for the cost of moving data of mode M between a register and + memory. A value of 2 is the default; this cost is relative to those in + `REGISTER_MOVE_COST'. + + If moving between registers and memory is more expensive than between two + registers, you should define this macro to express the relative cost. */ +#define MEMORY_MOVE_COST(M,C,I) 5 + +/* A C expression for the cost of a branch instruction. A value of 1 is the + default; other values are interpreted relative to that. */ + +#define BRANCH_COST 5 + +/* Here are additional macros which do not specify precise relative costs, but + only that certain actions are more expensive than GNU CC would ordinarily + expect. */ + +/* Define this macro as a C expression which is nonzero if accessing less than + a word of memory (i.e. a `char' or a `short') is no faster than accessing a + word of memory, i.e., if such access require more than one instruction or if + there is no difference in cost between byte and (aligned) word loads. + + When this macro is not defined, the compiler will access a field by finding + the smallest containing object; when it is defined, a fullword load will be + used if alignment permits. Unless bytes accesses are faster than word + accesses, using word accesses is preferable since it may eliminate + subsequent memory access if subsequent accesses occur to other fields in the + same word of the structure, but to different bytes. */ +#define SLOW_BYTE_ACCESS 0 + +/* Define this macro if zero-extension (of a `char' or `short' to an `int') can + be done faster if the destination is a register that is known to be zero. + + If you define this macro, you must have instruction patterns that recognize + RTL structures like this: + + (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...) + + and likewise for `HImode'. */ +#define SLOW_ZERO_EXTEND 0 + +/* Define this macro to be the value 1 if unaligned accesses have a cost many + times greater than aligned accesses, for example if they are emulated in a + trap handler. + + When this macro is non-zero, the compiler will act as if `STRICT_ALIGNMENT' + were non-zero when generating code for block moves. This can cause + significantly more instructions to be produced. Therefore, do not set this + macro non-zero if unaligned accesses only add a cycle or two to the time for + a memory access. + + If the value of this macro is always zero, it need not be defined. */ +/* #define SLOW_UNALIGNED_ACCESS */ + +/* Define this macro to inhibit strength reduction of memory addresses. (On + some machines, such strength reduction seems to do harm rather than good.) */ +/* #define DONT_REDUCE_ADDR */ + +/* The number of scalar move insns which should be generated instead of a + string move insn or a library call. Increasing the value will always make + code faster, but eventually incurs high cost in increased code size. + + If you don't define this, a reasonable default is used. */ +/* #define MOVE_RATIO */ + +/* Define this macro if it is as good or better to call a constant function + address than to call an address kept in a register. */ +#define NO_FUNCTION_CSE + +/* Define this macro if it is as good or better for a function to call itself + with an explicit address than to call an address kept in a register. */ +#define NO_RECURSIVE_FUNCTION_CSE + +/* A C statement (sans semicolon) to update the integer variable COST based on + the relationship between INSN that is dependent on DEP_INSN through the + dependence LINK. The default is to make no adjustment to COST. This can be + used for example to specify to the scheduler that an output- or + anti-dependence does not incur the same cost as a data-dependence. */ +/* #define ADJUST_COST(INSN, LINK, DEP_INSN, COST) */ + +/* A C statement (sans semicolon) to update the integer scheduling + priority `INSN_PRIORITY(INSN)'. Reduce the priority to execute + the INSN earlier, increase the priority to execute INSN later. + Do not define this macro if you do not need to adjust the + scheduling priorities of insns. */ +/* #define ADJUST_PRIORITY (INSN) */ + + +/* Dividing the output into sections. */ + +/* A C expression whose value is a string containing the assembler operation + that should precede instructions and read-only data. Normally `".text"' is + right. */ +#define TEXT_SECTION_ASM_OP ".text" + +/* A C expression whose value is a string containing the assembler operation to + identify the following data as writable initialized data. Normally + `".data"' is right. */ +#define DATA_SECTION_ASM_OP ".data" + +/* if defined, a C expression whose value is a string containing the assembler + operation to identify the following data as shared data. If not defined, + `DATA_SECTION_ASM_OP' will be used. */ +/* #define SHARED_SECTION_ASM_OP */ + +/* If defined, a C expression whose value is a string containing the + assembler operation to identify the following data as + uninitialized global data. If not defined, and neither + `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined, + uninitialized global data will be output in the data section if + `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be + used. */ +#define BSS_SECTION_ASM_OP ".bss" + +/* If defined, a C expression whose value is a string containing the + assembler operation to identify the following data as + uninitialized global shared data. If not defined, and + `BSS_SECTION_ASM_OP' is, the latter will be used. */ +/* #define SHARED_BSS_SECTION_ASM_OP */ + +/* Define the pseudo-ops used to switch to the .ctors and .dtors sections. + There are no shared libraries on this target so these sections need + not be writable. + + Defined in elfos.h. */ + +#undef CTORS_SECTION_ASM_OP +#undef DTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"a\"" +#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"a\"" + +/* A list of names for sections other than the standard two, which are + `in_text' and `in_data'. You need not define this macro on a system with no + other sections (that GCC needs to use). + + Defined in svr4.h. */ +/* #define EXTRA_SECTIONS */ + +/* One or more functions to be defined in `varasm.c'. These functions should + do jobs analogous to those of `text_section' and `data_section', for your + additional sections. Do not define this macro if you do not define + `EXTRA_SECTIONS'. + + Defined in svr4.h. */ +/* #define EXTRA_SECTION_FUNCTIONS */ + +/* On most machines, read-only variables, constants, and jump tables are placed + in the text section. If this is not the case on your machine, this macro + should be defined to be the name of a function (either `data_section' or a + function defined in `EXTRA_SECTIONS') that switches to the section to be + used for read-only items. + + If these items should be placed in the text section, this macro should not + be defined. */ +/* #define READONLY_DATA_SECTION */ + +/* A C statement or statements to switch to the appropriate section for output + of EXP. You can assume that EXP is either a `VAR_DECL' node or a constant + of some sort. RELOC indicates whether the initial value of EXP requires + link-time relocations. Select the section by calling `text_section' or one + of the alternatives for other sections. + + Do not define this macro if you put all read-only variables and constants in + the read-only data section (usually the text section). + + Defined in svr4.h. */ +/* #define SELECT_SECTION(EXP, RELOC) */ + +/* A C statement or statements to switch to the appropriate section for output + of RTX in mode MODE. You can assume that RTX is some kind of constant in + RTL. The argument MODE is redundant except in the case of a `const_int' + rtx. Select the section by calling `text_section' or one of the + alternatives for other sections. + + Do not define this macro if you put all constants in the read-only data + section. + + Defined in svr4.h. */ +/* #define SELECT_RTX_SECTION(MODE, RTX) */ + +/* Define this macro if jump tables (for `tablejump' insns) should be output in + the text section, along with the assembler instructions. Otherwise, the + readonly data section is used. + + This macro is irrelevant if there is no separate readonly data section. */ +#define JUMP_TABLES_IN_TEXT_SECTION 1 + +/* Define this macro if references to a symbol must be treated differently + depending on something about the variable or function named by the symbol + (such as what section it is in). + + The macro definition, if any, is executed immediately after the rtl for DECL + has been created and stored in `DECL_RTL (DECL)'. The value of the rtl will + be a `mem' whose address is a `symbol_ref'. + + The usual thing for this macro to do is to record a flag in the `symbol_ref' + (such as `SYMBOL_REF_FLAG') or to store a modified name string in the + `symbol_ref' (if one bit is not enough information). */ +#define ENCODE_SECTION_INFO(DECL) stormy16_encode_section_info(DECL) + +/* Decode SYM_NAME and store the real name part in VAR, sans the characters + that encode section info. Define this macro if `ENCODE_SECTION_INFO' alters + the symbol's name string. */ +/* #define STRIP_NAME_ENCODING(VAR, SYM_NAME) */ + +/* A C statement to build up a unique section name, expressed as a + STRING_CST node, and assign it to `DECL_SECTION_NAME (DECL)'. + RELOC indicates whether the initial value of EXP requires + link-time relocations. If you do not define this macro, GNU CC + will use the symbol name prefixed by `.' as the section name. + + Defined in svr4.h. */ +/* #define UNIQUE_SECTION(DECL, RELOC) */ + + +/* Position Independent Code. */ + +/* The register number of the register used to address a table of static data + addresses in memory. In some cases this register is defined by a + processor's "application binary interface" (ABI). When this macro is + defined, RTL is generated for this register once, as with the stack pointer + and frame pointer registers. If this macro is not defined, it is up to the + machine-dependent files to allocate such a register (if necessary). */ +/* #define PIC_OFFSET_TABLE_REGNUM */ + +/* Define this macro if the register defined by `PIC_OFFSET_TABLE_REGNUM' is + clobbered by calls. Do not define this macro if `PPIC_OFFSET_TABLE_REGNUM' + is not defined. */ +/* #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED */ + +/* By generating position-independent code, when two different programs (A and + B) share a common library (libC.a), the text of the library can be shared + whether or not the library is linked at the same address for both programs. + In some of these environments, position-independent code requires not only + the use of different addressing modes, but also special code to enable the + use of these addressing modes. + + The `FINALIZE_PIC' macro serves as a hook to emit these special codes once + the function is being compiled into assembly code, but not before. (It is + not done before, because in the case of compiling an inline function, it + would lead to multiple PIC prologues being included in functions which used + inline functions and were compiled to assembly language.) */ +/* #define FINALIZE_PIC */ + +/* A C expression that is nonzero if X is a legitimate immediate operand on the + target machine when generating position independent code. You can assume + that X satisfies `CONSTANT_P', so you need not check this. You can also + assume FLAG_PIC is true, so you need not check it either. You need not + define this macro if all constants (including `SYMBOL_REF') can be immediate + operands when generating position independent code. */ +/* #define LEGITIMATE_PIC_OPERAND_P(X) */ + + +/* The Overall Framework of an Assembler File. */ + +/* A C expression which outputs to the stdio stream STREAM some appropriate + text to go at the start of an assembler file. + + Normally this macro is defined to output a line containing `#NO_APP', which + is a comment that has no effect on most assemblers but tells the GNU + assembler that it can save time by not checking for certain assembler + constructs. + + On systems that use SDB, it is necessary to output certain commands; see + `attasm.h'. + + Defined in svr4.h. */ +/* #define ASM_FILE_START(STREAM) */ + +/* A C expression which outputs to the stdio stream STREAM some appropriate + text to go at the end of an assembler file. + + If this macro is not defined, the default is to output nothing special at + the end of the file. Most systems don't require any definition. + + On systems that use SDB, it is necessary to output certain commands; see + `attasm.h'. + + Defined in svr4.h. */ +/* #define ASM_FILE_END(STREAM) */ + +/* A C statement to output assembler commands which will identify the object + file as having been compiled with GNU CC (or another GNU compiler). + + If you don't define this macro, the string `gcc_compiled.:' is output. This + string is calculated to define a symbol which, on BSD systems, will never be + defined for any other reason. GDB checks for the presence of this symbol + when reading the symbol table of an executable. + + On non-BSD systems, you must arrange communication with GDB in some other + fashion. If GDB is not used on your system, you can define this macro with + an empty body. + + Defined in svr4.h. */ +/* #define ASM_IDENTIFY_GCC(FILE) */ + +/* Like ASM_IDENTIFY_GCC, but used when dbx debugging is selected to emit + a stab the debugger uses to identify gcc as the compiler that is emitted + after the stabs for the filename, which makes it easier for GDB to parse. + + Defined in svr4.h. */ +/* #define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) */ + +/* A C string constant describing how to begin a comment in the target + assembler language. The compiler assumes that the comment will end at the + end of the line. */ +/* #define ASM_COMMENT_START */ + +/* A C string constant for text to be output before each `asm' statement or + group of consecutive ones. Normally this is `"#APP"', which is a comment + that has no effect on most assemblers but tells the GNU assembler that it + must check the lines that follow for all valid assembler constructs. */ +#define ASM_APP_ON "#APP\n" + +/* A C string constant for text to be output after each `asm' statement or + group of consecutive ones. Normally this is `"#NO_APP"', which tells the + GNU assembler to resume making the time-saving assumptions that are valid + for ordinary compiler output. */ +#define ASM_APP_OFF "#NO_APP\n" + +/* A C statement to output COFF information or DWARF debugging information + which indicates that filename NAME is the current source file to the stdio + stream STREAM. + + This macro need not be defined if the standard form of output for the file + format in use is appropriate. */ +/* #define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) */ + +/* A C statement to output DBX or SDB debugging information before code for + line number LINE of the current source file to the stdio stream STREAM. + + This macro need not be defined if the standard form of debugging information + for the debugger in use is appropriate. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) */ + +/* A C statement to output something to the assembler file to handle a `#ident' + directive containing the text STRING. If this macro is not defined, nothing + is output for a `#ident' directive. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_IDENT(STREAM, STRING) */ + +/* A C statement to output something to the assembler file to switch to section + NAME for object DECL which is either a `FUNCTION_DECL', a `VAR_DECL' or + `NULL_TREE'. Some target formats do not support arbitrary sections. Do not + define this macro in such cases. + + At present this macro is only used to support section attributes. When this + macro is undefined, section attributes are disabled. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME) */ + +/* A C statement to output any assembler statements which are required to + precede any Objective C object definitions or message sending. The + statement is executed only when compiling an Objective C program. */ +/* #define OBJC_PROLOGUE */ + + +/* Output of Data. */ + +/* A C statement to output to the stdio stream STREAM an assembler instruction + to assemble a floating-point constant of `TFmode', `DFmode', `SFmode', + `TQFmode', `HFmode', or `QFmode', respectively, whose value is VALUE. VALUE + will be a C expression of type `REAL_VALUE_TYPE'. Macros such as + `REAL_VALUE_TO_TARGET_DOUBLE' are useful for writing these definitions. */ + +/* This is how to output an assembler line defining a `double'. */ +#define ASM_OUTPUT_DOUBLE(STREAM,VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf ((STREAM), "\t.double %s\n", dstr); \ + } while (0) + +/* This is how to output an assembler line defining a `float' constant. */ +#define ASM_OUTPUT_FLOAT(STREAM,VALUE) \ +do { char dstr[30]; \ + REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \ + fprintf ((STREAM), "\t.float %s\n", dstr); \ + } while (0) + +/* #define ASM_OUTPUT_LONG_DOUBLE(STREAM, VALUE) */ +/* #define ASM_OUTPUT_THREE_QUARTER_FLOAT(STREAM, VALUE) */ +/* #define ASM_OUTPUT_SHORT_FLOAT(STREAM, VALUE) */ +/* #define ASM_OUTPUT_BYTE_FLOAT(STREAM, VALUE) */ + +/* A C statement to output to the stdio stream STREAM an assembler instruction + to assemble an integer of 16, 8, 4, 2 or 1 bytes, respectively, whose value + is VALUE. The argument EXP will be an RTL expression which represents a + constant value. Use `output_addr_const (STREAM, EXP)' to output this value + as an assembler expression. + + For sizes larger than `UNITS_PER_WORD', if the action of a macro would be + identical to repeatedly calling the macro corresponding to a size of + `UNITS_PER_WORD', once for each word, you need not define the macro. */ +/* #define ASM_OUTPUT_QUADRUPLE_INT(STREAM, EXP) */ +/* #define ASM_OUTPUT_DOUBLE_INT(STREAM, EXP) */ + +/* This is how to output an assembler line defining a `char' constant. */ +#define ASM_OUTPUT_CHAR(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.byte\t"); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an assembler line defining a `short' constant. */ +#define ASM_OUTPUT_SHORT(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.hword\t"); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* This is how to output an assembler line defining an `int' constant. + We also handle symbol output here. */ +#define ASM_OUTPUT_INT(FILE, VALUE) \ +do { \ + fprintf (FILE, "\t.word\t"); \ + output_addr_const (FILE, (VALUE)); \ + fprintf (FILE, "\n"); \ +} while (0) + +/* A C statement to output to the stdio stream STREAM an assembler instruction + to assemble a single byte containing the number VALUE. + + This declaration must be present. */ +#define ASM_OUTPUT_BYTE(STREAM, VALUE) \ + fprintf (STREAM, "\t%s\t0x%x\n", ASM_BYTE_OP, (VALUE)) + +/* A C string constant giving the pseudo-op to use for a sequence of + single-byte constants. If this macro is not defined, the default + is `"byte"'. + + Defined in svr4.h. */ +/* #define ASM_BYTE_OP */ + +/* A C statement to output to the stdio stream STREAM an assembler instruction + to assemble a string constant containing the LEN bytes at PTR. PTR will be + a C expression of type `char *' and LEN a C expression of type `int'. + + If the assembler has a `.ascii' pseudo-op as found in the Berkeley Unix + assembler, do not define the macro `ASM_OUTPUT_ASCII'. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) */ + +/* You may define this macro as a C expression. You should define the + expression to have a non-zero value if GNU CC should output the + constant pool for a function before the code for the function, or + a zero value if GNU CC should output the constant pool after the + function. If you do not define this macro, the usual case, GNU CC + will output the constant pool before the function. */ +/* #define CONSTANT_POOL_BEFORE_FUNCTION */ + +/* A C statement to output assembler commands to define the start of the + constant pool for a function. FUNNAME is a string giving the name of the + function. Should the return type of the function be required, it can be + obtained via FUNDECL. SIZE is the size, in bytes, of the constant pool that + will be written immediately after this call. + + If no constant-pool prefix is required, the usual case, this macro need not + be defined. */ +/* #define ASM_OUTPUT_POOL_PROLOGUE(FILE FUNNAME FUNDECL SIZE) */ + +/* A C statement (with or without semicolon) to output a constant in the + constant pool, if it needs special treatment. (This macro need not do + anything for RTL expressions that can be output normally.) + + The argument FILE is the standard I/O stream to output the assembler code + on. X is the RTL expression for the constant to output, and MODE is the + machine mode (in case X is a `const_int'). ALIGN is the required alignment + for the value X; you should output an assembler directive to force this much + alignment. + + The argument LABELNO is a number to use in an internal label for the address + of this pool entry. The definition of this macro is responsible for + outputting the label definition at the proper place. Here is how to do + this: + + ASM_OUTPUT_INTERNAL_LABEL (FILE, "LC", LABELNO); + + When you output a pool entry specially, you should end with a `goto' to the + label JUMPTO. This will prevent the same pool entry from being output a + second time in the usual manner. + + You need not define this macro if it would do nothing. */ +/* #define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, JUMPTO) */ + +/* Define this macro as a C expression which is nonzero if the constant EXP, of + type `tree', should be output after the code for a function. The compiler + will normally output all constants before the function; you need not define + this macro if this is OK. */ +/* #define CONSTANT_AFTER_FUNCTION_P(EXP) */ + +/* A C statement to output assembler commands to at the end of the constant + pool for a function. FUNNAME is a string giving the name of the function. + Should the return type of the function be required, you can obtain it via + FUNDECL. SIZE is the size, in bytes, of the constant pool that GNU CC wrote + immediately before this call. + + If no constant-pool epilogue is required, the usual case, you need not + define this macro. */ +/* #define ASM_OUTPUT_POOL_EPILOGUE (FILE FUNNAME FUNDECL SIZE) */ + +/* Define this macro as a C expression which is nonzero if C is used as a + logical line separator by the assembler. + + If you do not define this macro, the default is that only the character `;' + is treated as a logical line separator. */ +#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '|') + +/* These macros are provided by `real.h' for writing the definitions of + `ASM_OUTPUT_DOUBLE' and the like: */ + +/* These translate X, of type `REAL_VALUE_TYPE', to the target's floating point + representation, and store its bit pattern in the array of `long int' whose + address is L. The number of elements in the output array is determined by + the size of the desired target floating point data type: 32 bits of it go in + each `long int' array element. Each array element holds 32 bits of the + result, even if `long int' is wider than 32 bits on the host machine. + + The array element values are designed so that you can print them out using + `fprintf' in the order they should appear in the target machine's memory. */ +/* #define REAL_VALUE_TO_TARGET_SINGLE(X, L) */ +/* #define REAL_VALUE_TO_TARGET_DOUBLE(X, L) */ +/* #define REAL_VALUE_TO_TARGET_LONG_DOUBLE(X, L) */ + +/* This macro converts X, of type `REAL_VALUE_TYPE', to a decimal number and + stores it as a string into STRING. You must pass, as STRING, the address of + a long enough block of space to hold the result. + + The argument FORMAT is a `printf'-specification that serves as a suggestion + for how to format the output string. */ +/* #define REAL_VALUE_TO_DECIMAL(X, FORMAT, STRING) */ + + +/* Output of Uninitialized Variables. */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM the + assembler definition of a common-label named NAME whose size is SIZE bytes. + The variable ROUNDED is the size rounded up to whatever alignment the caller + wants. + + Use the expression `assemble_name (STREAM, NAME)' to output the name itself; + before and after that, output the additional assembler syntax for defining + the name, and a newline. + + This macro controls how the assembler definitions of uninitialized global + variables are output. */ +/* #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) */ + +/* Like `ASM_OUTPUT_COMMON' except takes the required alignment as a separate, + explicit argument. If you define this macro, it is used in place of + `ASM_OUTPUT_COMMON', and gives you more flexibility in handling the required + alignment of the variable. The alignment is specified as the number of + bits. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_ALIGNED_COMMON(STREAM, NAME, SIZE, ALIGNMENT) */ + +/* Like ASM_OUTPUT_ALIGNED_COMMON except that it takes an additional argument - + the DECL of the variable to be output, if there is one. This macro can be + called with DECL == NULL_TREE. If you define this macro, it is used in + place of both ASM_OUTPUT_COMMON and ASM_OUTPUT_ALIGNED_COMMON, and gives you + more flexibility in handling the destination of the variable. */ +/* #define ASM_OUTPUT_DECL_COMMON (STREAM, DECL, NAME, SIZE, ALIGNMENT) */ + +/* If defined, it is similar to `ASM_OUTPUT_COMMON', except that it is used + when NAME is shared. If not defined, `ASM_OUTPUT_COMMON' will be used. */ +/* #define ASM_OUTPUT_SHARED_COMMON(STREAM, NAME, SIZE, ROUNDED) */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM the + assembler definition of uninitialized global DECL named NAME whose size is + SIZE bytes. The variable ROUNDED is the size rounded up to whatever + alignment the caller wants. + + Try to use function `asm_output_bss' defined in `varasm.c' when defining + this macro. If unable, use the expression `assemble_name (STREAM, NAME)' to + output the name itself; before and after that, output the additional + assembler syntax for defining the name, and a newline. + + This macro controls how the assembler definitions of uninitialized global + variables are output. This macro exists to properly support languages like + `c++' which do not have `common' data. However, this macro currently is not + defined for all targets. If this macro and `ASM_OUTPUT_ALIGNED_BSS' are not + defined then `ASM_OUTPUT_COMMON' or `ASM_OUTPUT_ALIGNED_COMMON' or + `ASM_OUTPUT_DECL_COMMON' is used. */ +/* #define ASM_OUTPUT_BSS(STREAM, DECL, NAME, SIZE, ROUNDED) */ + +/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate, + explicit argument. If you define this macro, it is used in place of + `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required + alignment of the variable. The alignment is specified as the number of + bits. + + Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when + defining this macro. */ +/* #define ASM_OUTPUT_ALIGNED_BSS(STREAM, DECL, NAME, SIZE, ALIGNMENT) */ + +/* If defined, it is similar to `ASM_OUTPUT_BSS', except that it is used when + NAME is shared. If not defined, `ASM_OUTPUT_BSS' will be used. */ +/* #define ASM_OUTPUT_SHARED_BSS(STREAM, DECL, NAME, SIZE, ROUNDED) */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM the + assembler definition of a local-common-label named NAME whose size is SIZE + bytes. The variable ROUNDED is the size rounded up to whatever alignment + the caller wants. + + Use the expression `assemble_name (STREAM, NAME)' to output the name itself; + before and after that, output the additional assembler syntax for defining + the name, and a newline. + + This macro controls how the assembler definitions of uninitialized static + variables are output. */ +/* #define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) */ + +/* Like `ASM_OUTPUT_LOCAL' except takes the required alignment as a separate, + explicit argument. If you define this macro, it is used in place of + `ASM_OUTPUT_LOCAL', and gives you more flexibility in handling the required + alignment of the variable. The alignment is specified as the number of + bits. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGNMENT) */ + +/* Like `ASM_OUTPUT_ALIGNED_LOCAL' except that it takes an additional + parameter - the DECL of variable to be output, if there is one. + This macro can be called with DECL == NULL_TREE. If you define + this macro, it is used in place of `ASM_OUTPUT_LOCAL' and + `ASM_OUTPUT_ALIGNED_LOCAL', and gives you more flexibility in + handling the destination of the variable. */ +/* #define ASM_OUTPUT_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) */ + +/* If defined, it is similar to `ASM_OUTPUT_LOCAL', except that it is used when + NAME is shared. If not defined, `ASM_OUTPUT_LOCAL' will be used. */ +/* #define ASM_OUTPUT_SHARED_LOCAL (STREAM, NAME, SIZE, ROUNDED) */ + + +/* Output and Generation of Labels. */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM the + assembler definition of a label named NAME. Use the expression + `assemble_name (STREAM, NAME)' to output the name itself; before and after + that, output the additional assembler syntax for defining the name, and a + newline. */ +#define ASM_OUTPUT_LABEL(STREAM, NAME) \ +do { \ + assemble_name (STREAM, NAME); \ + fputs (":\n", STREAM); \ +} while (0) + +/* A C statement to output to the stdio stream STREAM the assembler + definition of a symbol named SYMBOL. */ +#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL) \ + do { \ + if (SYMBOL_REF_FLAG (SYMBOL)) \ + { \ + fputs ("@fptr(", STREAM); \ + assemble_name (STREAM, XSTR (SYMBOL, 0)); \ + fputc (')', STREAM); \ + } \ + else \ + assemble_name (STREAM, XSTR (SYMBOL, 0)); \ + } while (0) + +/* A C statement (sans semicolon) to output to the stdio stream STREAM any text + necessary for declaring the name NAME of a function which is being defined. + This macro is responsible for outputting the label definition (perhaps using + `ASM_OUTPUT_LABEL'). The argument DECL is the `FUNCTION_DECL' tree node + representing the function. + + If this macro is not defined, then the function name is defined in the usual + manner as a label (by means of `ASM_OUTPUT_LABEL'). + + Defined in svr4.h. */ +/* #define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM any text + necessary for declaring the size of a function which is being defined. The + argument NAME is the name of the function. The argument DECL is the + `FUNCTION_DECL' tree node representing the function. + + If this macro is not defined, then the function size is not defined. + + Defined in svr4.h. */ +/* #define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM any text + necessary for declaring the name NAME of an initialized variable which is + being defined. This macro must output the label definition (perhaps using + `ASM_OUTPUT_LABEL'). The argument DECL is the `VAR_DECL' tree node + representing the variable. + + If this macro is not defined, then the variable name is defined in the usual + manner as a label (by means of `ASM_OUTPUT_LABEL'). + + Defined in svr4.h. */ +/* #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) */ + +/* A C statement (sans semicolon) to finish up declaring a variable name once + the compiler has processed its initializer fully and thus has had a chance + to determine the size of an array when controlled by an initializer. This + is used on systems where it's necessary to declare something about the size + of the object. + + If you don't define this macro, that is equivalent to defining it to do + nothing. + + Defined in svr4.h. */ +/* #define ASM_FINISH_DECLARE_OBJECT(STREAM, DECL, TOPLEVEL, ATEND) */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM some + commands that will make the label NAME global; that is, available for + reference from other files. Use the expression `assemble_name (STREAM, + NAME)' to output the name itself; before and after that, output the + additional assembler syntax for making that name global, and a newline. */ +#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \ +do { \ + fputs ("\t.globl ", STREAM); \ + assemble_name (STREAM, NAME); \ + fputs ("\n", STREAM); \ +} while (0) + +/* A C statement (sans semicolon) to output to the stdio stream STREAM some + commands that will make the label NAME weak; that is, available for + reference from other files but only used if no other definition is + available. Use the expression `assemble_name (STREAM, NAME)' to output the + name itself; before and after that, output the additional assembler syntax + for making that name weak, and a newline. + + If you don't define this macro, GNU CC will not support weak symbols and you + should not define the `SUPPORTS_WEAK' macro. + + Defined in svr4.h. */ +/* #define ASM_WEAKEN_LABEL */ + +/* A C expression which evaluates to true if the target supports weak symbols. + + If you don't define this macro, `defaults.h' provides a default definition. + If `ASM_WEAKEN_LABEL' is defined, the default definition is `1'; otherwise, + it is `0'. Define this macro if you want to control weak symbol support + with a compiler flag such as `-melf'. */ +/* #define SUPPORTS_WEAK */ + +/* A C statement (sans semicolon) to mark DECL to be emitted as a + public symbol such that extra copies in multiple translation units + will be discarded by the linker. Define this macro if your object + file format provides support for this concept, such as the `COMDAT' + section flags in the Microsoft Windows PE/COFF format, and this + support requires changes to DECL, such as putting it in a separate + section. + + Defined in svr4.h. */ +/* #define MAKE_DECL_ONE_ONLY */ + +/* A C expression which evaluates to true if the target supports one-only + semantics. + + If you don't define this macro, `varasm.c' provides a default definition. + If `MAKE_DECL_ONE_ONLY' is defined, the default definition is `1'; + otherwise, it is `0'. Define this macro if you want to control one-only + symbol support with a compiler flag, or if setting the `DECL_ONE_ONLY' flag + is enough to mark a declaration to be emitted as one-only. */ +/* #define SUPPORTS_ONE_ONLY */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM any text + necessary for declaring the name of an external symbol named NAME which is + referenced in this compilation but not defined. The value of DECL is the + tree node for the declaration. + + This macro need not be defined if it does not need to output anything. The + GNU assembler and most Unix assemblers don't require anything. */ +/* #define ASM_OUTPUT_EXTERNAL(STREAM, DECL, NAME) */ + +/* A C statement (sans semicolon) to output on STREAM an assembler pseudo-op to + declare a library function name external. The name of the library function + is given by SYMREF, which has type `rtx' and is a `symbol_ref'. + + This macro need not be defined if it does not need to output anything. The + GNU assembler and most Unix assemblers don't require anything. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM, SYMREF) */ + +/* A C statement (sans semicolon) to output to the stdio stream STREAM a + reference in assembler syntax to a label named NAME. This should add `_' to + the front of the name, if that is customary on your operating system, as it + is in most Berkeley Unix systems. This macro is used in `assemble_name'. */ +/* #define ASM_OUTPUT_LABELREF(STREAM, NAME) */ + +/* A C statement to output to the stdio stream STREAM a label whose name is + made from the string PREFIX and the number NUM. + + It is absolutely essential that these labels be distinct from the labels + used for user-level functions and variables. Otherwise, certain programs + will have name conflicts with internal labels. + + It is desirable to exclude internal labels from the symbol table of the + object file. Most assemblers have a naming convention for labels that + should be excluded; on many systems, the letter `L' at the beginning of a + label has this effect. You should find out what convention your system + uses, and follow it. + + The usual definition of this macro is as follows: + + fprintf (STREAM, "L%s%d:\n", PREFIX, NUM) + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) */ + +/* A C statement to store into the string STRING a label whose name is made + from the string PREFIX and the number NUM. + + This string, when output subsequently by `assemble_name', should produce the + output that `ASM_OUTPUT_INTERNAL_LABEL' would produce with the same PREFIX + and NUM. + + If the string begins with `*', then `assemble_name' will output the rest of + the string unchanged. It is often convenient for + `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way. If the string doesn't + start with `*', then `ASM_OUTPUT_LABELREF' gets to output the string, and + may change it. (Of course, `ASM_OUTPUT_LABELREF' is also part of your + machine description, so you should know what it does on your machine.) + + Defined in svr4.h. */ +/* #define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) */ + +/* A C expression to assign to OUTVAR (which is a variable of type `char *') a + newly allocated string made from the string NAME and the number NUMBER, with + some suitable punctuation added. Use `alloca' to get space for the string. + + The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce + an assembler label for an internal static variable whose name is NAME. + Therefore, the string must be such as to result in valid assembler code. + The argument NUMBER is different each time this macro is executed; it + prevents conflicts between similarly-named internal static variables in + different scopes. + + Ideally this string should not be a valid C identifier, to prevent any + conflict with the user's own symbols. Most assemblers allow periods or + percent signs in assembler symbols; putting at least one of these between + the name and the number will suffice. */ +#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER) \ +do { \ + (OUTVAR) = (char *) alloca (strlen ((NAME)) + 12); \ + sprintf ((OUTVAR), "%s.%ld", (NAME), (long)(NUMBER)); \ +} while (0) + +/* A C statement to output to the stdio stream STREAM assembler code which + defines (equates) the symbol NAME to have the value VALUE. + + If SET_ASM_OP is defined, a default definition is provided which is correct + for most systems. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_DEF(STREAM, NAME, VALUE) */ + +/* A C statement to output to the stdio stream STREAM assembler code which + defines (equates) the weak symbol NAME to have the value VALUE. + + Define this macro if the target only supports weak aliases; define + ASM_OUTPUT_DEF instead if possible. */ +/* #define ASM_OUTPUT_WEAK_ALIAS (STREAM, NAME, VALUE) */ + +/* Define this macro to override the default assembler names used for Objective + C methods. + + The default name is a unique method number followed by the name of the class + (e.g. `_1_Foo'). For methods in categories, the name of the category is + also included in the assembler name (e.g. `_1_Foo_Bar'). + + These names are safe on most systems, but make debugging difficult since the + method's selector is not present in the name. Therefore, particular systems + define other ways of computing names. + + BUF is an expression of type `char *' which gives you a buffer in which to + store the name; its length is as long as CLASS_NAME, CAT_NAME and SEL_NAME + put together, plus 50 characters extra. + + The argument IS_INST specifies whether the method is an instance method or a + class method; CLASS_NAME is the name of the class; CAT_NAME is the name of + the category (or NULL if the method is not in a category); and SEL_NAME is + the name of the selector. + + On systems where the assembler can handle quoted names, you can use this + macro to provide more human-readable names. */ +/* #define OBJC_GEN_METHOD_LABEL(BUF, IS_INST, CLASS_NAME, CAT_NAME, SEL_NAME) */ + + +/* Macros Controlling Initialization Routines. */ + +/* If defined, a C string constant for the assembler operation to identify the + following data as initialization code. If not defined, GNU CC will assume + such a section does not exist. When you are using special sections for + initialization and termination functions, this macro also controls how + `crtstuff.c' and `libgcc2.c' arrange to run the initialization functions. + + Defined in svr4.h. */ +/* #define INIT_SECTION_ASM_OP */ + +/* If defined, `main' will not call `__main' as described above. This macro + should be defined for systems that control the contents of the init section + on a symbol-by-symbol basis, such as OSF/1, and should not be defined + explicitly for systems that support `INIT_SECTION_ASM_OP'. */ +/* #define HAS_INIT_SECTION */ + +/* If defined, a C string constant for a switch that tells the linker that the + following symbol is an initialization routine. */ +/* #define LD_INIT_SWITCH */ + +/* If defined, a C string constant for a switch that tells the linker that the + following symbol is a finalization routine. */ +/* #define LD_FINI_SWITCH */ + +/* If defined, `main' will call `__main' despite the presence of + `INIT_SECTION_ASM_OP'. This macro should be defined for systems where the + init section is not actually run automatically, but is still useful for + collecting the lists of constructors and destructors. */ +/* #define INVOKE__main */ + +/* Define this macro as a C statement to output on the stream STREAM the + assembler code to arrange to call the function named NAME at initialization + time. + + Assume that NAME is the name of a C function generated automatically by the + compiler. This function takes no arguments. Use the function + `assemble_name' to output the name NAME; this performs any system-specific + syntactic transformations such as adding an underscore. + + If you don't define this macro, nothing special is output to arrange to call + the function. This is correct when the function will be called in some + other manner--for example, by means of the `collect2' program, which looks + through the symbol table to find these functions by their names. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_CONSTRUCTOR(STREAM, NAME) */ + +/* This is like `ASM_OUTPUT_CONSTRUCTOR' but used for termination functions + rather than initialization functions. + + Defined in svr4.h. */ +/* #define ASM_OUTPUT_DESTRUCTOR(STREAM, NAME) */ + +/* If your system uses `collect2' as the means of processing constructors, then + that program normally uses `nm' to scan an object file for constructor + functions to be called. On certain kinds of systems, you can define these + macros to make `collect2' work faster (and, in some cases, make it work at + all): */ + +/* Define this macro if the system uses COFF (Common Object File Format) object + files, so that `collect2' can assume this format and scan object files + directly for dynamic constructor/destructor functions. */ +/* #define OBJECT_FORMAT_COFF */ + +/* Define this macro if the system uses ROSE format object files, so that + `collect2' can assume this format and scan object files directly for dynamic + constructor/destructor functions. + + These macros are effective only in a native compiler; `collect2' as + part of a cross compiler always uses `nm' for the target machine. */ +/* #define OBJECT_FORMAT_ROSE */ + +/* Define this macro if the system uses ELF format object files. + + Defined in svr4.h. */ +/* #define OBJECT_FORMAT_ELF */ + +/* Define this macro as a C string constant containing the file name to use to + execute `nm'. The default is to search the path normally for `nm'. + + If your system supports shared libraries and has a program to list the + dynamic dependencies of a given library or executable, you can define these + macros to enable support for running initialization and termination + functions in shared libraries: */ +/* #define REAL_NM_FILE_NAME */ + +/* Define this macro to a C string constant containing the name of the program + which lists dynamic dependencies, like `"ldd"' under SunOS 4. */ +/* #define LDD_SUFFIX */ + +/* Define this macro to be C code that extracts filenames from the output of + the program denoted by `LDD_SUFFIX'. PTR is a variable of type `char *' + that points to the beginning of a line of output from `LDD_SUFFIX'. If the + line lists a dynamic dependency, the code must advance PTR to the beginning + of the filename on that line. Otherwise, it must set PTR to `NULL'. */ +/* #define PARSE_LDD_OUTPUT (PTR) */ + + +/* Output of Assembler Instructions. */ + +/* A C initializer containing the assembler's names for the machine registers, + each one as a C string constant. This is what translates register numbers + in the compiler into assembler language. */ +#define REGISTER_NAMES \ +{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ + "r11", "r12", "r13", "psw", "sp", "carry", "fp", "ap" } + +/* If defined, a C initializer for an array of structures containing a name and + a register number. This macro defines additional names for hard registers, + thus allowing the `asm' option in declarations to refer to registers using + alternate names. */ +#define ADDITIONAL_REGISTER_NAMES \ + { { "r14", 14 }, \ + { "r15", 15 } } + +/* Define this macro if you are using an unusual assembler that requires + different names for the machine instructions. + + The definition is a C statement or statements which output an assembler + instruction opcode to the stdio stream STREAM. The macro-operand PTR is a + variable of type `char *' which points to the opcode name in its "internal" + form--the form that is written in the machine description. The definition + should output the opcode name to STREAM, performing any translation you + desire, and increment the variable PTR to point at the end of the opcode so + that it will not be output twice. + + In fact, your macro definition may process less than the entire opcode name, + or more than the opcode name; but if you want to process text that includes + `%'-sequences to substitute operands, you must take care of the substitution + yourself. Just be sure to increment PTR over whatever text should not be + output normally. + + If you need to look at the operand values, they can be found as the elements + of `recog_data.operand'. + + If the macro definition does nothing, the instruction is output in the usual + way. */ +/* #define ASM_OUTPUT_OPCODE(STREAM, PTR) */ + +/* If defined, a C statement to be executed just prior to the output of + assembler code for INSN, to modify the extracted operands so they will be + output differently. + + Here the argument OPVEC is the vector containing the operands extracted from + INSN, and NOPERANDS is the number of elements of the vector which contain + meaningful data for this insn. The contents of this vector are what will be + used to convert the insn template into assembler code, so you can change the + assembler output by changing the contents of the vector. + + This macro is useful when various assembler syntaxes share a single file of + instruction patterns; by defining this macro differently, you can cause a + large class of instructions to be output differently (such as with + rearranged operands). Naturally, variations in assembler syntax affecting + individual insn patterns ought to be handled by writing conditional output + routines in those patterns. + + If this macro is not defined, it is equivalent to a null statement. */ +/* #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) */ + +/* If defined, `FINAL_PRESCAN_INSN' will be called on each + `CODE_LABEL'. In that case, OPVEC will be a null pointer and + NOPERANDS will be zero. */ +/* #define FINAL_PRESCAN_LABEL */ + +/* A C compound statement to output to stdio stream STREAM the assembler syntax + for an instruction operand X. X is an RTL expression. + + CODE 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. CODE comes from the `%' specification that was + used to request printing of the operand. If the specification was just + `%DIGIT' then CODE is 0; if the specification was `%LTR DIGIT' then CODE is + the ASCII code for LTR. + + If X 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 X and + the punctuation character for CODE. */ +#define PRINT_OPERAND(STREAM, X, CODE) stormy16_print_operand (STREAM, X, CODE) + +/* A C expression which evaluates to true if CODE is a valid punctuation + character for use in the `PRINT_OPERAND' macro. If + `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no punctuation + characters (except for the standard one, `%') are used in this way. */ +/* #define PRINT_OPERAND_PUNCT_VALID_P(CODE) */ + +/* A C compound statement to output to stdio stream STREAM the assembler syntax + for an instruction operand that is a memory reference whose address is X. X + is an RTL expression. + + On some machines, the syntax for a symbolic address depends on the section + that the address refers to. On these machines, define the macro + `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and + then check for it here. + + This declaration must be present. */ +#define PRINT_OPERAND_ADDRESS(STREAM, X) stormy16_print_operand_address (STREAM, X) + +/* A C statement, to be executed after all slot-filler instructions have been + output. If necessary, call `dbr_sequence_length' to determine the number of + slots filled in a sequence (zero if not currently outputting a sequence), to + decide how many no-ops to output, or whatever. + + Don't define this macro if it has nothing to do, but it is helpful in + reading assembly output if the extent of the delay sequence is made explicit + (e.g. with white space). + + Note that output routines for instructions with delay slots must be prepared + to deal with not being output as part of a sequence (i.e. when the + scheduling pass is not run, or when no slot fillers could be found.) The + variable `final_sequence' is null when not processing a sequence, otherwise + it contains the `sequence' rtx being output. */ +/* #define DBR_OUTPUT_SEQEND(FILE) */ + +/* If defined, C string expressions to be used for the `%R', `%L', `%U', and + `%I' options of `asm_fprintf' (see `final.c'). These are useful when a + single `md' file must support multiple assembler formats. In that case, the + various `tm.h' files can define these macros differently. + + USER_LABEL_PREFIX is defined in svr4.h. */ +#define REGISTER_PREFIX "" +#define LOCAL_LABEL_PREFIX "." +#define USER_LABEL_PREFIX "" +#define IMMEDIATE_PREFIX "#" + +/* If your target supports multiple dialects of assembler language (such as + different opcodes), define this macro as a C expression that gives the + numeric index of the assembler language dialect to use, with zero as the + first variant. + + If this macro is defined, you may use `{option0|option1|option2...}' + constructs in the output templates of patterns or in the first argument of + `asm_fprintf'. This construct outputs `option0', `option1' or `option2', + etc., if the value of `ASSEMBLER_DIALECT' is zero, one or two, etc. Any + special characters within these strings retain their usual meaning. + + If you do not define this macro, the characters `{', `|' and `}' do not have + any special meaning when used in templates or operands to `asm_fprintf'. + + Define the macros `REGISTER_PREFIX', `LOCAL_LABEL_PREFIX', + `USER_LABEL_PREFIX' and `IMMEDIATE_PREFIX' if you can express the variations + in assemble language syntax with that mechanism. Define `ASSEMBLER_DIALECT' + and use the `{option0|option1}' syntax if the syntax variant are larger and + involve such things as different opcodes or operand order. */ +/* #define ASSEMBLER_DIALECT */ + +/* A C expression to output to STREAM some assembler code which will push hard + register number REGNO onto the stack. The code need not be optimal, since + this macro is used only when profiling. */ +#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \ + fprintf (STREAM, "\tpush %d\n", REGNO) + +/* A C expression to output to STREAM some assembler code which will pop hard + register number REGNO off of the stack. The code need not be optimal, since + this macro is used only when profiling. */ +#define ASM_OUTPUT_REG_POP(STREAM, REGNO) \ + fprintf (STREAM, "\tpop %d\n", REGNO) + + +/* Output of dispatch tables. */ + +/* This port does not use the ASM_OUTPUT_ADDR_VEC_ELT macro, because + this could cause label alignment to appear between the 'br' and the table, + which would be bad. Instead, it controls the output of the table + itself. */ +#define ASM_OUTPUT_ADDR_VEC(LABEL, BODY) \ + stormy16_output_addr_vec (file, LABEL, BODY) + +/* Alignment for ADDR_VECs is the same as for code. */ +#define ADDR_VEC_ALIGN(ADDR_VEC) 1 + + +/* Assembler Commands for Exception Regions. */ + +/* A C expression to output text to mark the start of an exception region. + + This macro need not be defined on most platforms. */ +/* #define ASM_OUTPUT_EH_REGION_BEG() */ + +/* A C expression to output text to mark the end of an exception region. + + This macro need not be defined on most platforms. */ +/* #define ASM_OUTPUT_EH_REGION_END() */ + +/* A C expression to switch to the section in which the main exception table is + to be placed. The default is a section named `.gcc_except_table' on machines + that support named sections via `ASM_OUTPUT_SECTION_NAME', otherwise if `-fpic' + or `-fPIC' is in effect, the `data_section', otherwise the + `readonly_data_section'. */ +/* #define EXCEPTION_SECTION() */ + +/* If defined, a C string constant for the assembler operation to switch to the + section for exception handling frame unwind information. If not defined, + GNU CC will provide a default definition if the target supports named + sections. `crtstuff.c' uses this macro to switch to the appropriate + section. + + You should define this symbol if your target supports DWARF 2 frame unwind + information and the default definition does not work. */ +/* #define EH_FRAME_SECTION_ASM_OP */ + +/* A C expression that is nonzero if the normal exception table output should + be omitted. + + This macro need not be defined on most platforms. */ +/* #define OMIT_EH_TABLE() */ + +/* Alternate runtime support for looking up an exception at runtime and finding + the associated handler, if the default method won't work. + + This macro need not be defined on most platforms. */ +/* #define EH_TABLE_LOOKUP() */ + +/* A C expression that decides whether or not the current function needs to + have a function unwinder generated for it. See the file `except.c' for + details on when to define this, and how. */ +/* #define DOESNT_NEED_UNWINDER */ + +/* An rtx used to mask the return address found via RETURN_ADDR_RTX, so that it + does not contain any extraneous set bits in it. */ +/* #define MASK_RETURN_ADDR */ + +/* Define this macro to 0 if your target supports DWARF 2 frame unwind + information, but it does not yet work with exception handling. Otherwise, + if your target supports this information (if it defines + `INCOMING_RETURN_ADDR_RTX' and either `UNALIGNED_INT_ASM_OP' or + `OBJECT_FORMAT_ELF'), GCC will provide a default definition of 1. + + If this macro is defined to 1, the DWARF 2 unwinder will be the default + exception handling mechanism; otherwise, setjmp/longjmp will be used by + default. + + If this macro is defined to anything, the DWARF 2 unwinder will be used + instead of inline unwinders and __unwind_function in the non-setjmp case. */ +/* #define DWARF2_UNWIND_INFO */ + + +/* Assembler Commands for Alignment. */ + +/* The alignment (log base 2) to put in front of LABEL, which follows + a BARRIER. + + This macro need not be defined if you don't want any special alignment to be + done at such a time. Most machine descriptions do not currently define the + macro. */ +/* #define LABEL_ALIGN_AFTER_BARRIER(LABEL) */ + +/* The desired alignment for the location counter at the beginning + of a loop. + + This macro need not be defined if you don't want any special alignment to be + done at such a time. Most machine descriptions do not currently define the + macro. */ +/* #define LOOP_ALIGN(LABEL) */ + +/* A C statement to output to the stdio stream STREAM an assembler instruction + to advance the location counter by NBYTES bytes. Those bytes should be zero + when loaded. NBYTES will be a C expression of type `int'. + + Defined in elfos.h. */ +/* #define ASM_OUTPUT_SKIP(STREAM, NBYTES) */ + +/* Define this macro if `ASM_OUTPUT_SKIP' should not be used in the text + section because it fails put zeros in the bytes that are skipped. This is + true on many Unix systems, where the pseudo-op to skip bytes produces no-op + instructions rather than zeros when used in the text section. */ +/* #define ASM_NO_SKIP_IN_TEXT */ + +/* A C statement to output to the stdio stream STREAM an assembler command to + advance the location counter to a multiple of 2 to the POWER bytes. POWER + will be a C expression of type `int'. */ +#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ + fprintf ((STREAM), "\t.p2align %d\n", (POWER)) + + +/* Macros Affecting all Debug Formats. */ + +/* A C expression that returns the DBX register number for the compiler + register number REGNO. In simple cases, the value of this expression may be + REGNO itself. But sometimes there are some registers that the compiler + knows about and DBX does not, or vice versa. In such cases, some register + may need to have one number in the compiler and another for DBX. + + If two registers have consecutive numbers inside GNU CC, and they can be + used as a pair to hold a multiword value, then they *must* have consecutive + numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers + will be unable to access such a pair, because they expect register pairs to + be consecutive in their own numbering scheme. + + If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not + preserve register pairs, then what you must do instead is redefine the + actual register numbering scheme. + + This declaration is required. */ +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* A C expression that returns the integer offset value for an automatic + variable having address X (an RTL expression). The default computation + assumes that X is based on the frame-pointer and gives the offset from the + frame-pointer. This is required for targets that produce debugging output + for DBX or COFF-style debugging output for SDB and allow the frame-pointer + to be eliminated when the `-g' options is used. */ +/* #define DEBUGGER_AUTO_OFFSET(X) */ + +/* A C expression that returns the integer offset value for an argument having + address X (an RTL expression). The nominal offset is OFFSET. */ +/* #define DEBUGGER_ARG_OFFSET(OFFSET, X) */ + +/* A C expression that returns the type of debugging output GNU CC produces + when the user specifies `-g' or `-ggdb'. Define this if you have arranged + for GNU CC to support more than one format of debugging output. Currently, + the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG', + `DWARF2_DEBUG', and `XCOFF_DEBUG'. + + The value of this macro only affects the default debugging output; the user + can always get a specific type of output by using `-gstabs', `-gcoff', + `-gdwarf-1', `-gdwarf-2', or `-gxcoff'. + + Defined in svr4.h. */ +#undef PREFERRED_DEBUGGING_TYPE +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + + +/* Specific Options for DBX Output. */ + +/* Define this macro if GNU CC should produce debugging output for DBX in + response to the `-g' option. + + Defined in svr4.h. */ +/* #define DBX_DEBUGGING_INFO */ + +/* Define this macro if GNU CC should produce XCOFF format debugging output in + response to the `-g' option. This is a variant of DBX format. */ +/* #define XCOFF_DEBUGGING_INFO */ + +/* Define this macro to control whether GNU CC should by default generate GDB's + extended version of DBX debugging information (assuming DBX-format debugging + information is enabled at all). If you don't define the macro, the default + is 1: always generate the extended information if there is any occasion to. */ +/* #define DEFAULT_GDB_EXTENSIONS */ + +/* Define this macro if all `.stabs' commands should be output while in the + text section. */ +/* #define DEBUG_SYMS_TEXT */ + +/* A C string constant naming the assembler pseudo op to use instead of + `.stabs' to define an ordinary debugging symbol. If you don't define this + macro, `.stabs' is used. This macro applies only to DBX debugging + information format. */ +/* #define ASM_STABS_OP */ + +/* A C string constant naming the assembler pseudo op to use instead of + `.stabd' to define a debugging symbol whose value is the current location. + If you don't define this macro, `.stabd' is used. This macro applies only + to DBX debugging information format. */ +/* #define ASM_STABD_OP */ + +/* A C string constant naming the assembler pseudo op to use instead of + `.stabn' to define a debugging symbol with no name. If you don't define + this macro, `.stabn' is used. This macro applies only to DBX debugging + information format. */ +/* #define ASM_STABN_OP */ + +/* Define this macro if DBX on your system does not support the construct + `xsTAGNAME'. On some systems, this construct is used to describe a forward + reference to a structure named TAGNAME. On other systems, this construct is + not supported at all. */ +/* #define DBX_NO_XREFS */ + +/* A symbol name in DBX-format debugging information is normally continued + (split into two separate `.stabs' directives) when it exceeds a certain + length (by default, 80 characters). On some operating systems, DBX requires + this splitting; on others, splitting must not be done. You can inhibit + splitting by defining this macro with the value zero. You can override the + default splitting-length by defining this macro as an expression for the + length you desire. */ +/* #define DBX_CONTIN_LENGTH */ + +/* Normally continuation is indicated by adding a `\' character to the end of a + `.stabs' string when a continuation follows. To use a different character + instead, define this macro as a character constant for the character you + want to use. Do not define this macro if backslash is correct for your + system. */ +/* #define DBX_CONTIN_CHAR */ + +/* Define this macro if it is necessary to go to the data section before + outputting the `.stabs' pseudo-op for a non-global static variable. */ +/* #define DBX_STATIC_STAB_DATA_SECTION */ + +/* The value to use in the "code" field of the `.stabs' directive for a + typedef. The default is `N_LSYM'. */ +/* #define DBX_TYPE_DECL_STABS_CODE */ + +/* The value to use in the "code" field of the `.stabs' directive for a static + variable located in the text section. DBX format does not provide any + "right" way to do this. The default is `N_FUN'. */ +/* #define DBX_STATIC_CONST_VAR_CODE */ + +/* The value to use in the "code" field of the `.stabs' directive for a + parameter passed in registers. DBX format does not provide any "right" way + to do this. The default is `N_RSYM'. */ +/* #define DBX_REGPARM_STABS_CODE */ + +/* The letter to use in DBX symbol data to identify a symbol as a parameter + passed in registers. DBX format does not customarily provide any way to do + this. The default is `'P''. */ +/* #define DBX_REGPARM_STABS_LETTER */ + +/* The letter to use in DBX symbol data to identify a symbol as a stack + parameter. The default is `'p''. */ +/* #define DBX_MEMPARM_STABS_LETTER */ + +/* Define this macro if the DBX information for a function and its arguments + should precede the assembler code for the function. Normally, in DBX + format, the debugging information entirely follows the assembler code. + + Defined in svr4.h. */ +/* #define DBX_FUNCTION_FIRST */ + +/* Define this macro if the `N_LBRAC' symbol for a block should precede the + debugging information for variables and functions defined in that block. + Normally, in DBX format, the `N_LBRAC' symbol comes first. */ +/* #define DBX_LBRAC_FIRST */ + +/* Define this macro if the value of a symbol describing the scope of a block + (`N_LBRAC' or `N_RBRAC') should be relative to the start of the enclosing + function. Normally, GNU C uses an absolute address. + + Defined in svr4.h. */ +/* #define DBX_BLOCKS_FUNCTION_RELATIVE */ + +/* Define this macro if GNU C should generate `N_BINCL' and `N_EINCL' + stabs for included header files, as on Sun systems. This macro + also directs GNU C to output a type number as a pair of a file + number and a type number within the file. Normally, GNU C does not + generate `N_BINCL' or `N_EINCL' stabs, and it outputs a single + number for a type number. */ +/* #define DBX_USE_BINCL */ + + +/* Open ended Hooks for DBX Output. */ + +/* Define this macro to say how to output to STREAM the debugging information + for the start of a scope level for variable names. The argument NAME is the + name of an assembler symbol (for use with `assemble_name') whose value is + the address where the scope begins. */ +/* #define DBX_OUTPUT_LBRAC(STREAM, NAME) */ + +/* Like `DBX_OUTPUT_LBRAC', but for the end of a scope level. */ +/* #define DBX_OUTPUT_RBRAC(STREAM, NAME) */ + +/* Define this macro if the target machine requires special handling to output + an enumeration type. The definition should be a C statement (sans + semicolon) to output the appropriate information to STREAM for the type + TYPE. */ +/* #define DBX_OUTPUT_ENUM(STREAM, TYPE) */ + +/* Define this macro if the target machine requires special output at the end + of the debugging information for a function. The definition should be a C + statement (sans semicolon) to output the appropriate information to STREAM. + FUNCTION is the `FUNCTION_DECL' node for the function. */ +/* #define DBX_OUTPUT_FUNCTION_END(STREAM, FUNCTION) */ + +/* Define this macro if you need to control the order of output of the standard + data types at the beginning of compilation. The argument SYMS is a `tree' + which is a chain of all the predefined global symbols, including names of + data types. + + Normally, DBX output starts with definitions of the types for integers and + characters, followed by all the other predefined types of the particular + language in no particular order. + + On some machines, it is necessary to output different particular types + first. To do this, define `DBX_OUTPUT_STANDARD_TYPES' to output those + symbols in the necessary order. Any predefined types that you don't + explicitly output will be output afterward in no particular order. + + Be careful not to define this macro so that it works only for C. There are + no global variables to access most of the built-in types, because another + language may have another set of types. The way to output a particular type + is to look through SYMS to see if you can find it. Here is an example: + + { + tree decl; + for (decl = syms; decl; decl = TREE_CHAIN (decl)) + if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), + "long int")) + dbxout_symbol (decl); + ... + } + + This does nothing if the expected type does not exist. + + See the function `init_decl_processing' in `c-decl.c' to find the names to + use for all the built-in C types. */ +/* #define DBX_OUTPUT_STANDARD_TYPES(SYMS) */ + +/* Some stabs encapsulation formats (in particular ECOFF), cannot + handle the `.stabs "",N_FUN,,0,0,Lscope-function-1' gdb dbx + extention construct. On those machines, define this macro to turn + this feature off without disturbing the rest of the gdb extensions. */ +/* #define NO_DBX_FUNCTION_END */ + + +/* File names in DBX format. */ + +/* Define this if DBX wants to have the current directory recorded in each + object file. + + Note that the working directory is always recorded if GDB extensions are + enabled. */ +/* #define DBX_WORKING_DIRECTORY */ + +/* A C statement to output DBX debugging information to the stdio stream STREAM + which indicates that file NAME is the main source file--the file specified + as the input file for compilation. This macro is called only once, at the + beginning of compilation. + + This macro need not be defined if the standard form of output for DBX + debugging information is appropriate. + + Defined in svr4.h. */ +/* #define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM, NAME) */ + +/* A C statement to output DBX debugging information to the stdio stream STREAM + which indicates that the current directory during compilation is named NAME. + + This macro need not be defined if the standard form of output for DBX + debugging information is appropriate. */ +/* #define DBX_OUTPUT_MAIN_SOURCE_DIRECTORY(STREAM, NAME) */ + +/* A C statement to output DBX debugging information at the end of compilation + of the main source file NAME. + + If you don't define this macro, nothing special is output at the end of + compilation, which is correct for most machines. */ +/* #define DBX_OUTPUT_MAIN_SOURCE_FILE_END(STREAM, NAME) */ + +/* A C statement to output DBX debugging information to the stdio stream STREAM + which indicates that file NAME is the current source file. This output is + generated each time input shifts to a different source file as a result of + `#include', the end of an included file, or a `#line' command. + + This macro need not be defined if the standard form of output for DBX + debugging information is appropriate. */ +/* #define DBX_OUTPUT_SOURCE_FILENAME(STREAM, NAME) */ + + +/* Macros for SDB and Dwarf Output. */ + +/* Define this macro if GNU CC should produce COFF-style debugging output for + SDB in response to the `-g' option. */ +/* #define SDB_DEBUGGING_INFO */ + +/* Define this macro if GNU CC should produce dwarf format debugging output in + response to the `-g' option. + + Defined in svr4.h. */ +/* #define DWARF_DEBUGGING_INFO */ + +/* Define this macro if GNU CC should produce dwarf version 2 format debugging + output in response to the `-g' option. + + To support optional call frame debugging information, you must also define + `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the + prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa' + and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you + don't. + + Defined in svr4.h. */ +/* #define DWARF2_DEBUGGING_INFO */ + +/* Define this macro if GNU CC should produce dwarf version 2-style + line numbers. This usually requires extending the assembler to + support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the + assembler configuration header files. */ +/* #define DWARF2_ASM_LINE_DEBUG_INFO 1 */ + +/* Define this macro if addresses in Dwarf 2 debugging info should not + be the same size as pointers on the target architecture. The + macro's value should be the size, in bytes, to use for addresses in + the debugging info. + + Some architectures use word addresses to refer to code locations, + but Dwarf 2 info always uses byte addresses. On such machines, + Dwarf 2 addresses need to be larger than the architecture's + pointers. */ +#define DWARF2_ADDR_SIZE 4 + +/* Define these macros to override the assembler syntax for the special SDB + assembler directives. See `sdbout.c' for a list of these macros and their + arguments. If the standard syntax is used, you need not define them + yourself. */ +/* #define PUT_SDB_... */ + +/* Some assemblers do not support a semicolon as a delimiter, even between SDB + assembler directives. In that case, define this macro to be the delimiter + to use (usually `\n'). It is not necessary to define a new set of + `PUT_SDB_OP' macros if this is the only change required. */ +/* #define SDB_DELIM */ + +/* Define this macro to override the usual method of constructing a dummy name + for anonymous structure and union types. See `sdbout.c' for more + information. */ +/* #define SDB_GENERATE_FAKE */ + +/* Define this macro to allow references to unknown structure, union, or + enumeration tags to be emitted. Standard COFF does not allow handling of + unknown references, MIPS ECOFF has support for it. */ +/* #define SDB_ALLOW_UNKNOWN_REFERENCES */ + +/* Define this macro to allow references to structure, union, or enumeration + tags that have not yet been seen to be handled. Some assemblers choke if + forward tags are used, while some require it. */ +/* #define SDB_ALLOW_FORWARD_REFERENCES */ + + +/* Miscellaneous Parameters. */ + +/* Define REAL_ARITHMETIC to use a software emulator for the target floating + point mode. Otherwise the host floating point mode is used. */ +#define REAL_ARITHMETIC + +/* Define this if you have defined special-purpose predicates in the file + `MACHINE.c'. This macro is called within an initializer of an array of + structures. The first field in the structure is the name of a predicate and + the second field is an array of rtl codes. For each predicate, list all rtl + codes that can be in expressions matched by the predicate. The list should + have a trailing comma. Here is an example of two entries in the list for a + typical RISC machine: + + #define PREDICATE_CODES \ + {"gen_reg_rtx_operand", {SUBREG, REG}}, \ + {"reg_or_short_cint_operand", {SUBREG, REG, CONST_INT}}, + + Defining this macro does not affect the generated code (however, incorrect + definitions that omit an rtl code that may be matched by the predicate can + cause the compiler to malfunction). Instead, it allows the table built by + `genrecog' to be more compact and efficient, thus speeding up the compiler. + The most important predicates to include in the list specified by this macro + are thoses used in the most insn patterns. */ +#define PREDICATE_CODES \ + {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT }}, \ + {"equality_operator", {EQ, NE }}, \ + {"inequality_operator", {GE, GT, LE, LT, GEU, GTU, LEU, LTU }}, \ + {"stormy16_ineqsi_operator", {LT, GE, LTU, GEU }}, + +/* An alias for a machine mode name. This is the machine mode that elements of + a jump-table should have. */ +#define CASE_VECTOR_MODE SImode + +/* Define as C expression which evaluates to nonzero if the tablejump + instruction expects the table to contain offsets from the address of the + table. + Do not define this if the table should contain absolute addresses. */ +/* #define CASE_VECTOR_PC_RELATIVE 1 */ + +/* Define this if control falls through a `case' insn when the index value is + out of range. This means the specified default-label is actually ignored by + the `case' insn proper. */ +/* #define CASE_DROPS_THROUGH */ + +/* Define this to be the smallest number of different values for which it is + best to use a jump-table instead of a tree of conditional branches. The + default is four for machines with a `casesi' instruction and five otherwise. + This is best for most machines. */ +/* #define CASE_VALUES_THRESHOLD */ + +/* Define this macro if operations between registers with integral mode smaller + than a word are always performed on the entire register. Most RISC machines + have this property and most CISC machines do not. */ +#define WORD_REGISTER_OPERATIONS + +/* Define this macro to be a C expression indicating when insns that read + memory in MODE, an integral mode narrower than a word, set the bits outside + of MODE to be either the sign-extension or the zero-extension of the data + read. Return `SIGN_EXTEND' for values of MODE for which the insn + sign-extends, `ZERO_EXTEND' for which it zero-extends, and `NIL' for other + modes. + + This macro is not called with MODE non-integral or with a width greater than + or equal to `BITS_PER_WORD', so you may return any value in this case. Do + not define this macro if it would always return `NIL'. On machines where + this macro is defined, you will normally define it as the constant + `SIGN_EXTEND' or `ZERO_EXTEND'. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* Define if loading short immediate values into registers sign extends. */ +/* #define SHORT_IMMEDIATES_SIGN_EXTEND */ + +/* An alias for a tree code that should be used by default for conversion of + floating point values to fixed point. Normally, `FIX_ROUND_EXPR' is used. */ +/* #define IMPLICIT_FIX_EXPR */ + +/* Define this macro if the same instructions that convert a floating point + number to a signed fixed point number also convert validly to an unsigned + one. */ +/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */ + +/* An alias for a tree code that is the easiest kind of division to compile + code for in the general case. It may be `TRUNC_DIV_EXPR', `FLOOR_DIV_EXPR', + `CEIL_DIV_EXPR' or `ROUND_DIV_EXPR'. These four division operators differ + in how they round the result to an integer. `EASY_DIV_EXPR' is used when it + is permissible to use any of those kinds of division and the choice should + be made on the basis of efficiency. */ +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* The maximum number of bytes that a single instruction can move quickly from + memory to memory. */ +#define MOVE_MAX 2 + +/* The maximum number of bytes that a single instruction can move quickly from + memory to memory. If this is undefined, the default is `MOVE_MAX'. + Otherwise, it is the constant value that is the largest value that + `MOVE_MAX' can have at run-time. */ +/* #define MAX_MOVE_MAX */ + +/* A C expression that is nonzero if on this machine the number of bits + actually used for the count of a shift operation is equal to the number of + bits needed to represent the size of the object being shifted. When this + macro is non-zero, the compiler will assume that it is safe to omit a + sign-extend, zero-extend, and certain bitwise `and' instructions that + truncates the count of a shift operation. On machines that have + instructions that act on bitfields at variable positions, which may include + `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables + deletion of truncations of the values that serve as arguments to bitfield + instructions. + + If both types of instructions truncate the count (for shifts) and position + (for bitfield operations), or if no variable-position bitfield instructions + exist, you should define this macro. + + However, on some machines, such as the 80386 and the 680x0, truncation only + applies to shift operations and not the (real or pretended) bitfield + operations. Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines. + Instead, add patterns to the `md' file that include the implied truncation + of the shift instructions. + + You need not define this macro if it would always have the value of zero. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* A C expression which is nonzero if on this machine it is safe to "convert" + an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller + than INPREC) by merely operating on it as if it had only OUTPREC bits. + + On many machines, this expression can be 1. + + When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for + which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the + case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve + things. */ +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* A C expression describing the value returned by a comparison operator with + an integral mode and stored by a store-flag instruction (`sCOND') when the + condition is true. This description must apply to *all* the `sCOND' + patterns and all the comparison operators whose results have a `MODE_INT' + mode. + + A value of 1 or -1 means that the instruction implementing the comparison + operator returns exactly 1 or -1 when the comparison is true and 0 when the + comparison is false. Otherwise, the value indicates which bits of the + result are guaranteed to be 1 when the comparison is true. This value is + interpreted in the mode of the comparison operation, which is given by the + mode of the first operand in the `sCOND' pattern. Either the low bit or the + sign bit of `STORE_FLAG_VALUE' be on. Presently, only those bits are used + by the compiler. + + If `STORE_FLAG_VALUE' is neither 1 or -1, the compiler will generate code + that depends only on the specified bits. It can also replace comparison + operators with equivalent operations if they cause the required bits to be + set, even if the remaining bits are undefined. For example, on a machine + whose comparison operators return an `SImode' value and where + `STORE_FLAG_VALUE' is defined as `0x80000000', saying that just the sign bit + is relevant, the expression + + (ne:SI (and:SI X (const_int POWER-OF-2)) (const_int 0)) + + can be converted to + + (ashift:SI X (const_int N)) + + where N is the appropriate shift count to move the bit being tested into the + sign bit. + + There is no way to describe a machine that always sets the low-order bit for + a true value, but does not guarantee the value of any other bits, but we do + not know of any machine that has such an instruction. If you are trying to + port GNU CC to such a machine, include an instruction to perform a + logical-and of the result with 1 in the pattern for the comparison operators + and let us know. + + Often, a machine will have multiple instructions that obtain a value from a + comparison (or the condition codes). Here are rules to guide the choice of + value for `STORE_FLAG_VALUE', and hence the instructions to be used: + + * Use the shortest sequence that yields a valid definition for + `STORE_FLAG_VALUE'. It is more efficient for the compiler to + "normalize" the value (convert it to, e.g., 1 or 0) than for + the comparison operators to do so because there may be + opportunities to combine the normalization with other + operations. + + * For equal-length sequences, use a value of 1 or -1, with -1 + being slightly preferred on machines with expensive jumps and + 1 preferred on other machines. + + * As a second choice, choose a value of `0x80000001' if + instructions exist that set both the sign and low-order bits + but do not define the others. + + * Otherwise, use a value of `0x80000000'. + + Many machines can produce both the value chosen for `STORE_FLAG_VALUE' and + its negation in the same number of instructions. On those machines, you + should also define a pattern for those cases, e.g., one matching + + (set A (neg:M (ne:M B C))) + + Some machines can also perform `and' or `plus' operations on condition code + values with less instructions than the corresponding `sCOND' insn followed + by `and' or `plus'. On those machines, define the appropriate patterns. + Use the names `incscc' and `decscc', respectively, for the the patterns + which perform `plus' or `minus' operations on condition code values. See + `rs6000.md' for some examples. The GNU Superoptizer can be used to find + such instruction sequences on other machines. + + You need not define `STORE_FLAG_VALUE' if the machine has no store-flag + instructions. */ +/* #define STORE_FLAG_VALUE */ + +/* A C expression that gives a non-zero floating point value that is returned + when comparison operators with floating-point results are true. Define this + macro on machine that have comparison operations that return floating-point + values. If there are no such operations, do not define this macro. */ +/* #define FLOAT_STORE_FLAG_VALUE */ + +/* An alias for the machine mode for pointers. On most machines, define this + to be the integer mode corresponding to the width of a hardware pointer; + `SImode' on 32-bit machine or `DImode' on 64-bit machines. On some machines + you must define this to be one of the partial integer modes, such as + `PSImode'. + + The width of `Pmode' must be at least as large as the value of + `POINTER_SIZE'. If it is not equal, you must define the macro + `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to `Pmode'. */ +#define Pmode HImode + +/* An alias for the machine mode used for memory references to functions being + called, in `call' RTL expressions. On most machines this should be + `QImode'. */ +#define FUNCTION_MODE HImode + +/* A C expression for the maximum number of instructions above which the + function DECL should not be inlined. DECL is a `FUNCTION_DECL' node. + + The default definition of this macro is 64 plus 8 times the number of + arguments that the function accepts. Some people think a larger threshold + should be used on RISC machines. */ +/* #define INTEGRATE_THRESHOLD(DECL) */ + +/* Define this if the preprocessor should ignore `#sccs' directives and print + no error message. + + Defined in svr4.h. */ +/* #define SCCS_DIRECTIVE */ + +/* Define this macro if the system header files support C++ as well as C. This + macro inhibits the usual method of using system header files in C++, which + is to pretend that the file's contents are enclosed in `extern "C" {...}'. */ +#define NO_IMPLICIT_EXTERN_C + +/* Define this macro if you want to implement any pragmas. If defined, it + should be a C expression to be executed when #pragma is seen. The + argument GETC is a function which will return the next character in the + input stream, or EOF if no characters are left. The argument UNGETC is + a function which will push a character back into the input stream. The + argument NAME is the word following #pragma in the input stream. The input + stream pointer will be pointing just beyond the end of this word. The + expression should return true if it handled the pragma, false otherwise. + The input stream should be left undistrubed if false is returned, otherwise + it should be pointing at the next character after the end of the pragma. + Any characters left between the end of the pragma and the end of the line will + be ignored. + + It is generally a bad idea to implement new uses of `#pragma'. The only + reason to define this macro is for compatibility with other compilers that + do support `#pragma' for the sake of any user programs which already use it. */ +/* #define HANDLE_PRAGMA(GETC, UNGETC, NAME) handle_pragma (GETC, UNGETC, NAME) */ + +/* Define this macro to handle System V style pragmas: #pragma pack and + #pragma weak. Note, #pragma weak will only be supported if SUPPORT_WEAK is + defined. + + Defined in svr4.h. */ +#define HANDLE_SYSV_PRAGMA + +/* Define this macro if you want to support the Win32 style pragmas + #pragma pack(push,<n>) and #pragma pack(pop). */ +/* HANDLE_PRAGMA_PACK_PUSH_POP 1 */ + +/* If defined, a C expression whose value is nonzero if IDENTIFIER with + arguments ARGS is a valid machine specific attribute for DECL. The + attributes in ATTRIBUTES have previously been assigned to DECL. */ +/* #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) */ + +/* If defined, a C expression whose value is nonzero if IDENTIFIER with + arguments ARGS is a valid machine specific attribute for TYPE. The + attributes in ATTRIBUTES have previously been assigned to TYPE. */ +/* #define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) */ + +/* If defined, a C expression whose value is zero if the attributes on TYPE1 + and TYPE2 are incompatible, one if they are compatible, and two if they are + nearly compatible (which causes a warning to be generated). */ +/* #define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) */ + +/* If defined, a C statement that assigns default attributes to newly defined + TYPE. */ +/* #define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) */ + +/* Define this macro to control use of the character `$' in identifier names. + The value should be 0, 1, or 2. 0 means `$' is not allowed by default; 1 + means it is allowed by default if `-traditional' is used; 2 means it is + allowed by default provided `-ansi' is not used. 1 is the default; there is + no need to define this macro in that case. */ +/* #define DOLLARS_IN_IDENTIFIERS */ + +/* Define this macro if the assembler does not accept the character `$' in + label names. By default constructors and destructors in G++ have `$' in the + identifiers. If this macro is defined, `.' is used instead. + + Defined in svr4.h. */ +/* #define NO_DOLLAR_IN_LABEL */ + +/* Define this macro if the assembler does not accept the character `.' in + label names. By default constructors and destructors in G++ have names that + use `.'. If this macro is defined, these names are rewritten to avoid `.'. */ +/* #define NO_DOT_IN_LABEL */ + +/* Define this macro if the target system expects every program's `main' + function to return a standard "success" value by default (if no other value + is explicitly returned). + + The definition should be a C statement (sans semicolon) to generate the + appropriate rtl instructions. It is used only when compiling the end of + `main'. */ +/* #define DEFAULT_MAIN_RETURN */ + +/* Define this if the target system supports the function `atexit' from the + ANSI C standard. If this is not defined, and `INIT_SECTION_ASM_OP' is not + defined, a default `exit' function will be provided to support C++. + + Defined by svr4.h */ +/* #define HAVE_ATEXIT */ + +/* Define this if your `exit' function needs to do something besides calling an + external function `_cleanup' before terminating with `_exit'. The + `EXIT_BODY' macro is only needed if netiher `HAVE_ATEXIT' nor + `INIT_SECTION_ASM_OP' are defined. */ +/* #define EXIT_BODY */ + +/* Define this macro as a C expression that is nonzero if it is safe for the + delay slot scheduler to place instructions in the delay slot of INSN, even + if they appear to use a resource set or clobbered in INSN. INSN is always a + `jump_insn' or an `insn'; GNU CC knows that every `call_insn' has this + behavior. On machines where some `insn' or `jump_insn' is really a function + call and hence has this behavior, you should define this macro. + + You need not define this macro if it would always return zero. */ +/* #define INSN_SETS_ARE_DELAYED(INSN) */ + +/* Define this macro as a C expression that is nonzero if it is safe for the + delay slot scheduler to place instructions in the delay slot of INSN, even + if they appear to set or clobber a resource referenced in INSN. INSN is + always a `jump_insn' or an `insn'. On machines where some `insn' or + `jump_insn' is really a function call and its operands are registers whose + use is actually in the subroutine it calls, you should define this macro. + Doing so allows the delay slot scheduler to move instructions which copy + arguments into the argument registers into the delay slot of INSN. + + You need not define this macro if it would always return zero. */ +/* #define INSN_REFERENCES_ARE_DELAYED(INSN) */ + +/* In rare cases, correct code generation requires extra machine dependent + processing between the second jump optimization pass and delayed branch + scheduling. On those machines, define this macro as a C statement to act on + the code starting at INSN. */ +/* #define MACHINE_DEPENDENT_REORG(INSN) */ + +/* Define this macro if in some cases global symbols from one translation unit + may not be bound to undefined symbols in another translation unit without + user intervention. For instance, under Microsoft Windows symbols must be + explicitly imported from shared libraries (DLLs). */ +/* #define MULTIPLE_SYMBOL_SPACES */ + +/* A C expression for the maximum number of instructions to execute via + conditional execution instructions instead of a branch. A value of + BRANCH_COST+1 is the default if the machine does not use + cc0, and 1 if it does use cc0. */ +/* #define MAX_CONDITIONAL_EXECUTE */ + +/* A C statement that adds to tree CLOBBERS a set of STRING_CST trees for any + hard regs the port wishes to automatically clobber for all asms. */ +/* #define MD_ASM_CLOBBERS(CLOBBERS) */ + +/* Indicate how many instructions can be issued at the same time. */ +/* #define ISSUE_RATE */ + +/* A C statement which is executed by the Haifa scheduler at the beginning of + each block of instructions that are to be scheduled. FILE is either a null + pointer, or a stdio stream to write any debug output to. VERBOSE is the + verbose level provided by -fsched-verbose-<n>. */ +/* #define MD_SCHED_INIT (FILE, VERBOSE) */ + +/* A C statement which is executed by the Haifa scheduler after it has scheduled + the ready list to allow the machine description to reorder it (for example to + combine two small instructions together on VLIW machines). FILE is either a + null pointer, or a stdio stream to write any debug output to. VERBOSE is the + verbose level provided by -fsched-verbose-=<n>. READY is a pointer to the + ready list of instructions that are ready to be scheduled. N_READY is the + number of elements in the ready list. The scheduler reads the ready list in + reverse order, starting with READY[N_READY-1] and going to READY[0]. CLOCK + is the timer tick of the scheduler. CAN_ISSUE_MORE is an output parameter that + is set to the number of insns that can issue this clock; normally this is just + 'issue_rate' */ +/* #define MD_SCHED_REORDER (FILE, VERBOSE, READY, N_READY, CLOCK, CAN_ISSUE_MORE) */ + +/* A C statement which is executed by the Haifa scheduler after it has scheduled + an insn from the ready list. FILE is either a null pointer, or a stdio stream + to write any debug output to. VERBOSE is the verbose level provided by + -fsched-verbose-<n>. INSN is the instruction that was scheduled. MORE is the + number of instructions that can be issued in the current cycle. This macro + is responsible for updating the value of MORE (typically by (MORE)--). */ +/* #define MD_SCHED_VARIABLE_ISSUE (FILE, VERBOSE, INSN, MORE) */ + +/* Define this to the largest integer machine mode which can be used for + operations other than load, store and copy operations. You need only define + this macro if the target holds values larger than word_mode in general purpose + registers. Most targets should not define this macro. */ +/* #define MAX_INTEGER_COMPUTATION_MODE */ + +/* Define this macro as a C string constant for the linker argument to link in the + system math library, or "" if the target does not have a separate math library. + You need only define this macro if the default of "-lm" is wrong. */ +/* #define MATH_LIBRARY */ + +/* Define the information needed to generate branch and scc insns. This is + stored from the compare operation. Note that we can't use "rtx" here + since it hasn't been defined! */ + +extern struct rtx_def *stormy16_compare_op0, *stormy16_compare_op1; + +/* End of generic.h */ diff --git a/gcc/config/stormy16/stormy16.md b/gcc/config/stormy16/stormy16.md new file mode 100644 index 0000000..83860b4 --- /dev/null +++ b/gcc/config/stormy16/stormy16.md @@ -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")]) diff --git a/gcc/config/stormy16/t-stormy16 b/gcc/config/stormy16/t-stormy16 new file mode 100644 index 0000000..241b89b --- /dev/null +++ b/gcc/config/stormy16/t-stormy16 @@ -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 |