/* Definitions of target machine for GNU compiler.  Amiga powerpc version.
   Copyright (C) 1996 Free Software Foundation, 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 "rs6000/sysv4.h"  This is for PowerUp */
#include "rs6000/rs6000.h" /* We want PowerOpen */
#include "stormsupport.h"


/* Handle some StormC-pragmas for compatibility with StormC */
extern int pragmapriority;
#define HANDLE_PRAGMA(GETC, UNGETC, NAME) 										\
	(((strcmp((NAME), "priority") == 0) 										\
		&&  (((yylex()  ==  CONSTANT)  &&  (TREE_CODE(yylval.ttype) == INTEGER_CST) \
		&&  (pragmapriority = TREE_INT_CST_LOW(yylval.ttype), 1)) 				\
		||  (error("invalid `#pragma priority'"), 0)))							\
	|| ((strcmp((NAME), "libbase") == 0)										\
		&&  ((({int v = yylex(); v == IDENTIFIER || v == TYPENAME;})  &&  (fprintf(asm_out_file, ".stabs \"%s\",33,0,0,0\n", IDENTIFIER_POINTER(yylval.ttype)), 1))	\
		||  (error("invalid `#pragma libbase'"), 0))))


/* Enable some special Amiga only features.  FIXME: This define should
   be eliminated in favor of more general ways to enable the features. */

#define TARGET_AMIGAOS
#define STORMCSPECIAL
#define STORMC_REMQUOTES(x) removeQuotationMarks((x))

#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-D__PPC__ -Damiga -Damigaos -DMCH_AMIGA -DAMIGA -Asystem(amigaos) --Acpu(powerpc) -Amachine(powerpc)"

#undef SET_ASM_OP
#define SET_ASM_OP  ".set"

#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)

#undef PROCESSOR_DEFAULT
#define PROCESSOR_DEFAULT PROCESSOR_POWERPC /* = 604 */

/* To maintain the binary compatibility with the m68k structures, we need
   to align 32-bit integers and pointers only to 16 bits in structures.  */
#undef ADJUST_FIELD_ALIGN
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) 				\
  (TYPE_MODE (TREE_CODE (TREE_TYPE (FIELD)) == ARRAY_TYPE 	\
	      ? get_inner_array_type (FIELD) 					\
	      : TREE_TYPE (FIELD)) == SImode 					\
   ? MIN ((COMPUTED), 16) : (COMPUTED))

/*
  (DECL_MODE (FIELD) != SImode ? (COMPUTED) : MIN ((COMPUTED), 16))*/

#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"

#undef VALID_MACHINE_TYPE_ATTRIBUTE
#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
  (storm_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))

#undef XCOFF_DEBUGGING_INFO
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
#define DBX_DEBUGGING_INFO
#define DWARF_DEBUGGING_INFO
extern char *xcoff_bss_section_name;
extern char *xcoff_private_data_section_name;
extern char *xcoff_read_only_section_name;
extern char *xcoff_private_toc_section_name;
extern int lctoc0_inuse;

#undef FASCIST_ASSEMBLER

#undef SAVE_FP_PREFIX
#define SAVE_FP_PREFIX "__savef"

#undef RESTORE_FP_PREFIX
#define RESTORE_FP_PREFIX "__restf"

#undef ASM_FILE_START
#define ASM_FILE_START(FILE)                    				\
{                               								\
	rs6000_gen_section_name (&xcoff_bss_section_name,     		\
	main_input_filename, "_bss_");   							\
	rs6000_gen_section_name (&xcoff_private_data_section_name,  \
	main_input_filename, "_rw_");    							\
	rs6000_gen_section_name (&xcoff_read_only_section_name,   	\
	main_input_filename, "_ro_");    							\
	rs6000_gen_section_name (&xcoff_private_toc_section_name,   \
	main_input_filename, "_toc_");    							\
																\
	output_file_directive (FILE, main_input_filename);        	\
	if (TARGET_64BIT)                     						\
		fputs ("\t.machine\t\"ppc64\"\n", FILE);            	\
	toc_section ();                       						\
	if (write_symbols != NO_DEBUG)                				\
		read_only_data_section ();                    			\
	text_section ();                      						\
	if (profile_flag)                     						\
		fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT);        \
	rs6000_file_start (FILE, TARGET_CPU_DEFAULT);         		\
}

#undef ASM_FILE_END
#define ASM_FILE_END(FILE)							\
{													\
	if(lctoc0_inuse  &&  toc_initialized < 2)		\
	{												\
		fputs (".section .tocd\n", FILE);   		\
		fputs ("LCTOC__0:\n", FILE);    			\
		fputs ("\t.long 0\n", FILE);				\
	}												\
}

#undef NO_DOLLAR_IN_LABEL

#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS             \
                            \
void                            \
read_only_data_section ()               \
{                           \
  if (in_section != read_only_data)         \
    {                           \
      fprintf (asm_out_file, ".section %s,\"drw4\"\n",     \
           xcoff_read_only_section_name);       \
      in_section = read_only_data;          \
    }                           \
}                           \
                            \
void                            \
private_data_section ()                 \
{                           \
  if (in_section != private_data)           \
    {                           \
      fprintf (asm_out_file, ".section %s,\"drw4\"\n",     \
           xcoff_private_data_section_name);    \
                            \
      in_section = private_data;            \
    }                           \
}                           \
                            \
void                            \
read_only_private_data_section ()           \
{                           \
  if (in_section != read_only_private_data)     \
    {                           \
      fprintf (asm_out_file, ".section %s,\"drw4\"\n",     \
           xcoff_private_data_section_name);    \
      in_section = read_only_private_data;      \
    }                           \
}                           \
                            \
void                            								\
toc_section ()                      							\
{                           									\
	if (TARGET_MINIMAL_TOC)               						\
	{                           								\
		/* toc_section is always called at least once from ASM_FILE_START, \
		so this is guaranteed to always be defined once and only once   \
		in each file.  */                       				\
		if (toc_initialized < 1)               					\
		{                       								\
			fputs (".section .tocd\n", asm_out_file);         	\
			toc_initialized = 1;								\
		}														\
		else if (toc_initialized < 2)							\
		{														\
			fputs (".section .tocd\n", asm_out_file);         	\
			fputs ("LCTOC__0:\n", asm_out_file);    			\
			fputs ("\t.long FILESCOPETOC__0\n", asm_out_file);	\
			toc_initialized = 2;              					\
		}                       								\
																\
		if (in_section != toc)                					\
		{														\
			fprintf (asm_out_file, ".section %s,\"drw4\"\n",    \
           		xcoff_private_toc_section_name);    			\
		}														\
	}                           								\
	else                          								\
	{                           								\
		if (in_section != toc)                					\
			fputs (".section .tocd\n", asm_out_file);         	\
	}                           								\
	in_section = toc;                 							\
}

#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL)   \
{                 									\
	RS6000_OUTPUT_BASENAME (FILE, NAME);            \
	fputs (":\n", FILE);                      		\
}

#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, WIN)  	\
{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X))									\
    {																		\
      storm_output_toc (FILE, X, LABELNO);									\
      goto WIN;																\
    }																		\
}

#undef RS6000_OUTPUT_BASENAME
#define RS6000_OUTPUT_BASENAME(FILE, NAME)  \
do { 										\
	char *_p = (NAME);                  \
                        				\
	int _len = strlen(_p);				\
	if (_p[_len - 1] != ']')			\
	{									\
		assemble_name ((FILE), _p);     \
	}									\
	else								\
	{									\
		_p = (char*)malloc(_len + 1);	\
		strcpy(_p, (NAME));				\
		_p[_len - 4] = '\0';			\
		assemble_name ((FILE), _p);     \
		free(_p);						\
	}									\
} while(0)

#undef ASM_OUTPUT_EXTERNAL
#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)   \
{ rtx _symref = XEXP (DECL_RTL (DECL), 0);  \
  if ((TREE_CODE (DECL) == VAR_DECL     \
       || TREE_CODE (DECL) == FUNCTION_DECL)    \
      && (NAME)[strlen (NAME) - 1] != ']')  \
    {                       \
      char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
      strcpy (_name, XSTR (_symref, 0));    \
      XSTR (_symref, 0) = _name;        \
    }                       \
  fputs ("\t.extern ", FILE);           \
  assemble_name (FILE, XSTR (_symref, 0));  \
  putc ('\n', FILE);                \
}

#undef ASM_OUTPUT_EXTERNAL_LIBCALL
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN)  \
{ 										\
	fputs ("\t.extern ", FILE);        \
	assemble_name (FILE, XSTR (FUN, 0));\
	putc ('\n', FILE);                	\
}

#undef TEXT_SECTION_ASM_OP
#define TEXT_SECTION_ASM_OP ".section .text"

#undef DATA_SECTION_ASM_OP
#define DATA_SECTION_ASM_OP ".section .data"


extern char storm_reg_names[][8];
#undef REGISTER_NAMES
#define REGISTER_NAMES								\
{													\
  &storm_reg_names[ 0][0],	/* r0   */				\
  &storm_reg_names[ 1][0],	/* r1	*/				\
  &storm_reg_names[ 2][0],	/* r2	*/				\
  &storm_reg_names[ 3][0],	/* r3	*/				\
  &storm_reg_names[ 4][0],	/* r4	*/				\
  &storm_reg_names[ 5][0],	/* r5	*/				\
  &storm_reg_names[ 6][0],	/* r6	*/				\
  &storm_reg_names[ 7][0],	/* r7	*/				\
  &storm_reg_names[ 8][0],	/* r8	*/				\
  &storm_reg_names[ 9][0],	/* r9	*/				\
  &storm_reg_names[10][0],	/* r10  */				\
  &storm_reg_names[11][0],	/* r11  */				\
  &storm_reg_names[12][0],	/* r12  */				\
  &storm_reg_names[13][0],	/* r13  */				\
  &storm_reg_names[14][0],	/* r14  */				\
  &storm_reg_names[15][0],	/* r15  */				\
  &storm_reg_names[16][0],	/* r16  */				\
  &storm_reg_names[17][0],	/* r17  */				\
  &storm_reg_names[18][0],	/* r18  */				\
  &storm_reg_names[19][0],	/* r19  */				\
  &storm_reg_names[20][0],	/* r20  */				\
  &storm_reg_names[21][0],	/* r21  */				\
  &storm_reg_names[22][0],	/* r22  */				\
  &storm_reg_names[23][0],	/* r23  */				\
  &storm_reg_names[24][0],	/* r24  */				\
  &storm_reg_names[25][0],	/* r25  */				\
  &storm_reg_names[26][0],	/* r26  */				\
  &storm_reg_names[27][0],	/* r27  */				\
  &storm_reg_names[28][0],	/* r28  */				\
  &storm_reg_names[29][0],	/* r29  */				\
  &storm_reg_names[30][0],	/* r30  */				\
  &storm_reg_names[31][0],	/* r31  */				\
													\
  &storm_reg_names[32][0],	/* fr0  */				\
  &storm_reg_names[33][0],	/* fr1  */				\
  &storm_reg_names[34][0],	/* fr2  */				\
  &storm_reg_names[35][0],	/* fr3  */				\
  &storm_reg_names[36][0],	/* fr4  */				\
  &storm_reg_names[37][0],	/* fr5  */				\
  &storm_reg_names[38][0],	/* fr6  */				\
  &storm_reg_names[39][0],	/* fr7  */				\
  &storm_reg_names[40][0],	/* fr8  */				\
  &storm_reg_names[41][0],	/* fr9  */				\
  &storm_reg_names[42][0],	/* fr10 */				\
  &storm_reg_names[43][0],	/* fr11 */				\
  &storm_reg_names[44][0],	/* fr12 */				\
  &storm_reg_names[45][0],	/* fr13 */				\
  &storm_reg_names[46][0],	/* fr14 */				\
  &storm_reg_names[47][0],	/* fr15 */				\
  &storm_reg_names[48][0],	/* fr16 */				\
  &storm_reg_names[49][0],	/* fr17 */				\
  &storm_reg_names[50][0],	/* fr18 */				\
  &storm_reg_names[51][0],	/* fr19 */				\
  &storm_reg_names[52][0],	/* fr20 */				\
  &storm_reg_names[53][0],	/* fr21 */				\
  &storm_reg_names[54][0],	/* fr22 */				\
  &storm_reg_names[55][0],	/* fr23 */				\
  &storm_reg_names[56][0],	/* fr24 */				\
  &storm_reg_names[57][0],	/* fr25 */				\
  &storm_reg_names[58][0],	/* fr26 */				\
  &storm_reg_names[59][0],	/* fr27 */				\
  &storm_reg_names[60][0],	/* fr28 */				\
  &storm_reg_names[61][0],	/* fr29 */				\
  &storm_reg_names[62][0],	/* fr30 */				\
  &storm_reg_names[63][0],	/* fr31 */				\
													\
  &storm_reg_names[64][0],  /* mq   */				\
  &storm_reg_names[65][0],	/* lr   */				\
  &storm_reg_names[66][0],	/* ctr  */				\
  &storm_reg_names[67][0],	/* ap   */				\
													\
  &storm_reg_names[68][0],	/* cr0  */				\
  &storm_reg_names[69][0],	/* cr1  */				\
  &storm_reg_names[70][0],	/* cr2  */				\
  &storm_reg_names[71][0],	/* cr3  */				\
  &storm_reg_names[72][0],	/* cr4  */				\
  &storm_reg_names[73][0],	/* cr5  */				\
  &storm_reg_names[74][0],	/* cr6  */				\
  &storm_reg_names[75][0],	/* cr7  */				\
													\
  &storm_reg_names[76][0],	/* fpmem */				\
}

#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE,NAME)	\
	asm_fprintf (FILE, "%0U%s", NAME)

#undef ASM_OUTPUT_INTERNAL_LABEL
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM)  \
  fprintf (FILE, "%s__%d:\n", PREFIX, NUM)

#undef ASM_OUTPUT_INTERNAL_LABEL_PREFIX
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX)   \
  fprintf (FILE, "%s__", PREFIX)

#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)   \
  sprintf (LABEL, "*%s__%d", PREFIX, NUM)

#undef ASM_OUTPUT_DOUBLE(FILE, VALUE)
#define ASM_OUTPUT_DOUBLE(FILE, VALUE)                  \
  {                                 					\
    long t[2];                          				\
    REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);           \
    fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n",    \
        t[0] & 0xffffffff, t[1] & 0xffffffff);          \
  }

#undef ASM_OUTPUT_FLOAT
#define ASM_OUTPUT_FLOAT(FILE, VALUE)                   \
  {                                 					\
    long t;                             				\
    REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);           \
    fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff);  \
  }

#undef ASM_OUTPUT_ALIGNED_COMMON
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT)  \
  do {	fputs (".comm ", (FILE));            					\
		RS6000_OUTPUT_BASENAME ((FILE), (NAME));     			\
		fprintf( (FILE), ",%d\n", (SIZE));     					\
  } while (0)


#undef ASM_OUTPUT_LOCAL
#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE,ROUNDED)  \
  do { fputs (".lcomm ", (FILE));           		\
       RS6000_OUTPUT_BASENAME ((FILE), (NAME));     \
       fprintf ((FILE), ",%d\n", (SIZE)); 			\
     } while (0)

#undef ASM_FORMAT_PRIVATE_NAME
#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO)  \
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),    \
  sprintf ((OUTPUT), "%s_%d", (NAME), (LABELNO)))

#undef ASM_OUTPUT_MAIN_SOURCE_FILENAME
#define ASM_OUTPUT_MAIN_SOURCE_FILENAME

/* We don't have to inform GDB about compiler or language. */
#define ASM_IDENTIFY_GCC(x)
#define ASM_IDENTIFY_LANGUAGE(x)

