cc65/src/cc65/codegen.h

520 lines
18 KiB
C

/*****************************************************************************/
/* */
/* codegen.h */
/* */
/* 6502 code generator */
/* */
/* */
/* */
/* (C) 1998-2013, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef CODEGEN_H
#define CODEGEN_H
/* common */
#include "coll.h"
#include "inttypes.h"
/* cc65 */
#include "segments.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Code generator flags.
** Note: The type flags are designed so that a smaller type may override a
** larger one by or'ing it into the existing one.
** Note^2: The actual type including the sign flag is in the lower bits, so
** we can mask the information and use them as a table index.
*/
#define CF_NONE 0x0000 /* No special flags */
/* Values for the actual type */
#define CF_CHAR 0x0007 /* Operation on characters */
#define CF_INT 0x0003 /* Operation on ints */
#define CF_SHORT CF_INT /* Alias */
#define CF_PTR CF_INT /* Alias for readability */
#define CF_LONG 0x0001 /* Operation on longs */
#define CF_FLOAT 0x0010 /* Operation on a float */
/* Signedness */
#define CF_UNSIGNED 0x0008 /* Value is unsigned */
/* Masks for retrieving type information */
#define CF_TYPEMASK 0x0017 /* Type information */
#define CF_STYPEMASK 0x001F /* Includes signedness */
#define CF_CONST 0x0040 /* Constant value available */
#define CF_TEST 0x0080 /* Test value */
#define CF_FIXARGC 0x0100 /* Function has fixed arg count */
#define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */
#define CF_NOKEEP 0x0400 /* Value may get destroyed when storing */
/* Type of address */
#define CF_ADDRMASK 0xF000 /* Bit mask of address type */
#define CF_IMM 0x0000 /* Value is pure rvalue and has no storage */
#define CF_ABSOLUTE 0x1000 /* Numeric absolute address */
#define CF_EXTERNAL 0x2000 /* External */
#define CF_REGVAR 0x4000 /* Register variable */
#define CF_LITERAL 0x7000 /* Literal */
#define CF_PRIMARY 0x8000 /* Value is in primary register */
#define CF_EXPR 0x9000 /* Value is addressed by primary register */
#define CF_STATIC 0xA000 /* Local static */
#define CF_CODE 0xB000 /* C code label location */
#define CF_STACK 0xC000 /* Function-local auto on stack */
/* Forward */
struct StrBuf;
/*****************************************************************************/
/* Files, pre- and postamble */
/*****************************************************************************/
void g_preamble (void);
/* Generate the assembler code preamble */
void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime);
/* If debug info is enabled, place a file info into the source */
/*****************************************************************************/
/* Segment support */
/*****************************************************************************/
void g_userodata (void);
/* Switch to the read only data segment */
void g_usedata (void);
/* Switch to the data segment */
void g_usebss (void);
/* Switch to the bss segment */
void g_segname (segment_t Seg);
/* Emit the name of a segment if necessary */
/*****************************************************************************/
/* Functions handling local labels */
/*****************************************************************************/
void g_defcodelabel (unsigned label);
/* Define a local code label */
void g_defdatalabel (unsigned label);
/* Define a local data label */
/*****************************************************************************/
/* Functions handling global labels */
/*****************************************************************************/
void g_defgloblabel (const char* Name);
/* Define a global label with the given name */
void g_defliterallabel (unsigned label);
/* Define a literal data label */
void g_aliasliterallabel (unsigned label, unsigned baselabel, long offs);
/* Define label as an alias for baselabel+offs */
void g_defexport (const char* Name, int ZP);
/* Export the given label */
void g_defimport (const char* Name, int ZP);
/* Import the given label */
void g_importstartup (void);
/* Forced import of the startup segment */
void g_importmainargs (void);
/* Forced import of a special symbol that handles arguments to main */
/*****************************************************************************/
/* stack */
/*****************************************************************************/
int pop (unsigned flags);
/* Pop an argument of the given size */
int push (unsigned flags);
/* Push an argument of the given size */
unsigned sizeofarg (unsigned flags);
/* Return the size of a function argument type that is encoded in flags */
/*****************************************************************************/
/* type conversion and similiar stuff */
/*****************************************************************************/
void g_toslong (unsigned flags);
/* Make sure, the value on TOS is a long. Convert if necessary */
void g_tosint (unsigned flags);
/* Make sure, the value on TOS is an int. Convert if necessary */
void g_regint (unsigned Flags);
/* Make sure, the value in the primary register an int. Convert if necessary */
void g_reglong (unsigned Flags);
/* Make sure, the value in the primary register a long. Convert if necessary */
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
/* Adjust the integer operands before doing a binary operation. lhs is a flags
** value, that corresponds to the value on TOS, rhs corresponds to the value
** in (e)ax. The return value is the flags value for the resulting type.
*/
unsigned g_typecast (unsigned lhs, unsigned rhs);
/* Cast the value in the primary register to the operand size that is flagged
** by the lhs value. Return the result value.
*/
void g_scale (unsigned flags, long val);
/* Scale the value in the primary register by the given value. If val is positive,
** scale up, is val is negative, scale down. This function is used to scale
** the operands or results of pointer arithmetic by the size of the type, the
** pointer points to.
*/
/*****************************************************************************/
/* Function entry and exit */
/*****************************************************************************/
void g_enter (unsigned flags, unsigned argsize);
/* Function prologue */
void g_leave (void);
/* Function epilogue */
/*****************************************************************************/
/* Register variables */
/*****************************************************************************/
void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes);
/* Swap a register variable with a location on the stack */
void g_save_regvars (int RegOffs, unsigned Bytes);
/* Save register variables */
void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes);
/* Restore register variables */
/*****************************************************************************/
/* Fetching memory cells */
/*****************************************************************************/
void g_getimmed (unsigned Flags, unsigned long Val, long Offs);
/* Load a constant into the primary register */
void g_getstatic (unsigned Flags, uintptr_t Label, long Offs);
/* Fetch an static memory cell into the primary register */
void g_getlocal (unsigned Flags, int Offs);
/* Fetch specified local object (local var). */
void g_getind (unsigned Flags, unsigned Offs);
/* Fetch the specified object type indirect through the primary register
** into the primary register
*/
void g_leasp (int Offs);
/* Fetch the address of the specified symbol into the primary register */
void g_leavariadic (int Offs);
/* Fetch the address of a parameter in a variadic function into the primary
** register
*/
/*****************************************************************************/
/* Store into memory */
/*****************************************************************************/
void g_putstatic (unsigned flags, uintptr_t label, long offs);
/* Store the primary register into the specified static memory cell */
void g_putlocal (unsigned Flags, int Offs, long Val);
/* Put data into local object. */
void g_putind (unsigned flags, unsigned offs);
/* Store the specified object type in the primary register at the address
** on the top of the stack
*/
/*****************************************************************************/
/* Adds and subs of variables fix a fixed address */
/*****************************************************************************/
void g_addlocal (unsigned flags, int offs);
/* Add a local variable to ax */
void g_addstatic (unsigned flags, uintptr_t label, long offs);
/* Add a static variable to ax */
/*****************************************************************************/
/* Special op= functions */
/*****************************************************************************/
void g_addeqstatic (unsigned flags, uintptr_t label, long offs,
unsigned long val);
/* Emit += for a static variable */
void g_addeqlocal (unsigned flags, int offs, unsigned long val);
/* Emit += for a local variable */
void g_addeqind (unsigned flags, unsigned offs, unsigned long val);
/* Emit += for the location with address in ax */
void g_subeqstatic (unsigned flags, uintptr_t label, long offs,
unsigned long val);
/* Emit -= for a static variable */
void g_subeqlocal (unsigned flags, int offs, unsigned long val);
/* Emit -= for a local variable */
void g_subeqind (unsigned flags, unsigned offs, unsigned long val);
/* Emit -= for the location with address in ax */
/*****************************************************************************/
/* Add a variable address to the value in ax */
/*****************************************************************************/
void g_addaddr_local (unsigned flags, int offs);
/* Add the address of a local variable to ax */
void g_addaddr_static (unsigned flags, uintptr_t label, long offs);
/* Add the address of a static variable to ax */
/*****************************************************************************/
/* */
/*****************************************************************************/
void g_save (unsigned flags);
/* Copy primary register to hold register. */
void g_restore (unsigned flags);
/* Copy hold register to primary. */
void g_cmp (unsigned flags, unsigned long val);
/* Immediate compare. The primary register will not be changed, Z flag
** will be set.
*/
void g_test (unsigned flags);
/* Test the value in the primary and set the condition codes */
void g_push (unsigned flags, unsigned long val);
/* Push the primary register or a constant value onto the stack */
void g_swap (unsigned flags);
/* Swap the primary register and the top of the stack. flags give the type
** of *both* values (must have same size).
*/
void g_call (unsigned Flags, const char* Label, unsigned ArgSize);
/* Call the specified subroutine name */
void g_callind (unsigned Flags, unsigned ArgSize, int Offs);
/* Call subroutine indirect */
void g_jump (unsigned Label);
/* Jump to specified internal label number */
void g_truejump (unsigned flags, unsigned label);
/* Jump to label if zero flag clear */
void g_falsejump (unsigned flags, unsigned label);
/* Jump to label if zero flag set */
void g_branch (unsigned Label);
/* Branch unconditionally to Label if the CPU has the BRA instruction.
** Otherwise, jump to Label.
** Use this function, instead of g_jump(), only where it is certain that
** the label cannot be farther away from the branch than -128/+127 bytes.
*/
void g_lateadjustSP (unsigned label);
/* Adjust stack based on non-immediate data */
void g_drop (unsigned Space);
/* Drop space allocated on the stack */
void g_space (int space);
/* Create or drop space on the stack */
void g_cstackcheck (void);
/* Check for a C stack overflow */
void g_stackcheck (void);
/* Check for a stack overflow */
void g_add (unsigned flags, unsigned long val);
void g_sub (unsigned flags, unsigned long val);
void g_rsub (unsigned flags, unsigned long val);
void g_mul (unsigned flags, unsigned long val);
void g_div (unsigned flags, unsigned long val);
void g_mod (unsigned flags, unsigned long val);
void g_or (unsigned flags, unsigned long val);
void g_xor (unsigned flags, unsigned long val);
void g_and (unsigned flags, unsigned long val);
void g_asr (unsigned flags, unsigned long val);
void g_asl (unsigned flags, unsigned long val);
void g_neg (unsigned flags);
void g_bneg (unsigned flags);
void g_com (unsigned flags);
void g_inc (unsigned flags, unsigned long n);
void g_dec (unsigned flags, unsigned long n);
void g_eq (unsigned flags, unsigned long val);
void g_ne (unsigned flags, unsigned long val);
void g_lt (unsigned flags, unsigned long val);
void g_le (unsigned flags, unsigned long val);
void g_gt (unsigned flags, unsigned long val);
void g_ge (unsigned flags, unsigned long val);
void g_res (unsigned n);
/* Reserve static storage, n bytes */
void g_defdata (unsigned flags, unsigned long val, long offs);
/* Define data with the size given in flags */
void g_defbytes (const void* bytes, unsigned count);
/* Output a row of bytes as a constant */
void g_zerobytes (unsigned Count);
/* Output Count bytes of data initialized with zero */
void g_initregister (unsigned Label, unsigned Reg, unsigned Size);
/* Initialize a register variable from static initialization data */
void g_initauto (unsigned Label, unsigned Size);
/* Initialize a local variable at stack offset zero from static data */
void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size);
/* Initialize a static local variable from static initialization data */
/*****************************************************************************/
/* Bit-fields */
/*****************************************************************************/
void g_testbitfield (unsigned Flags, unsigned BitOffs, unsigned BitWidth);
/* Test bit-field in ax. */
void g_extractbitfield (unsigned Flags, unsigned FullWidthFlags, int IsSigned,
unsigned BitOffs, unsigned BitWidth);
/* Extract bits from bit-field in ax. */
/*****************************************************************************/
/* Switch statement */
/*****************************************************************************/
void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth);
/* Generate code for a switch statement */
/*****************************************************************************/
/* User supplied assembler code */
/*****************************************************************************/
void g_asmcode (struct StrBuf* B);
/* Output one line of assembler code. */
/* End of codegen.h */
#endif