home *** CD-ROM | disk | FTP | other *** search
- /* $VER: pasm ppcasm.h V0.8 (14.02.98)
- *
- * This file is part of pasm, a portable PowerPC assembler.
- * Copyright (c) 1997-98 Frank Wille
- *
- * pasm is freeware and part of the portable and retargetable ANSI C
- * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
- * pasm may be freely redistributed as long as no modifications are
- * made and nothing is charged for it. Non-commercial usage is allowed
- * without any restrictions.
- * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
- * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
- *
- *
- * v0.8 (14.02.98) phx
- * Alignment list for each section. This fixes the problems
- * with optimizations.
- * v0.7 (02.01.98) phx
- * Define "NetBSDAmiga68k" changed to "NetBSD68k".
- * Changed ParsedLine (next) and GlobalVars (anotherpass) to
- * allow more than two assembler passes - as required for
- * optimizations.
- * search_instr() is global.
- * Output format 3 is ADOS (like EHF, but doesn't use HUNK_PPC_CODE).
- * v0.6 (30.10.97) phx
- * More options. GlobalVars: optinstrmode and supermode.
- * v0.5 (12.10.97) phx
- * Add userdeflist and usrdefs to GlobalVars for symbol definitions
- * via the command line.
- * .set allows symbols to be reused.
- * Last line of a source text was ignored, if newline is missing.
- * v0.4 (05.07.97) phx
- * Program returns EXIT_FAILURE if an error occurs.
- * Base address for absolute code may be set with -B option.
- * EHF support.
- * Added R_PPC_TOC16 relocation type.
- * Option -x automatically declares unknown symbols as
- * externally defined. New GlobalVars entry: autoextern.
- * Runs on Linux/DEC-Alpha with 64-bit integers.
- * Changed program name from "PPCasm" to "pasm". Reason: There
- * is already a PPCasm for Apple Macintosh.
- * v0.3 (20.04.97) phx
- * Using correct names for PowerPC relocations.
- * Added little-endian conversion macros.
- * v0.2 (25.03.97) phx
- * Writes ELF object for 32-bit PowerPC big-endian. Either absolute
- * or ELF output format may be selected. ELF is default for all
- * currently supported platforms. PPCasm supports nine different
- * relocation types (there are much more...).
- * Compiles and works also under NetBSD/amiga (68k).
- * Changed function declaration to 'new style' in all sources
- * (to avoid problems with '...' for example).
- * Included NetBSD/amiga as supported architecture.
- * v0.1 (11.03.97) phx
- * First test version with all PowerPC instructions and most
- * important directives. Only raw, absolute output.
- * v0.0 (14.02.97) phx
- * File created. Project started.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <ctype.h>
-
- /* program's name */
- #define PNAME "pasm"
-
- /* version/revision */
- #define VERSION 0
- #define REVISION 80
-
- /* architecture specific defines */
- #if defined (AmigaOS68k)
- #define MACHINE "Amiga OS/M68k"
- #define BIGENDIAN
- #define STDTYPES
- #elif defined (AmigaOSPPC)
- #define MACHINE "Amiga OS/PowerPC"
- #define BIGENDIAN
- #define STDTYPES
- #elif defined (NetBSD68k)
- #define MACHINE "NetBSD/M68k"
- #define BIGENDIAN
- #define STDTYPES
- #elif defined (SolarisSparc)
- #define MACHINE "Solaris/Sparc"
- #define BIGENDIAN
- #define STDTYPES
- #elif defined (SunOSSparc)
- #define MACHINE "SunOS/Sparc"
- #define BIGENDIAN
- #define STDTYPES
- #elif defined (SCOi386)
- #define MACHINE "SCO/i386"
- #define LITTLEENDIAN
- #define STDTYPES
- #elif defined (Linuxi386)
- #define MACHINE "Linux/i386"
- #define LITTLEENDIAN
- #define STDTYPES
- #elif defined (LinuxAlpha)
- #define MACHINE "Linux/Alpha"
- #define LITTLEENDIAN
- #define TYPES64BIT
- #else
- #error Unsupported architecture! Please adapt the source text.
- #endif
-
- #ifdef STDTYPES
- typedef signed char int8;
- typedef unsigned char uint8;
- typedef signed short int int16;
- typedef unsigned short int uint16;
- typedef signed long int int32;
- typedef unsigned long int uint32;
- typedef signed char bool;
- #elif defined (TYPES64BIT)
- typedef signed char int8;
- typedef unsigned char uint8;
- typedef signed short int16;
- typedef unsigned short uint16;
- typedef signed int int32;
- typedef unsigned int uint32;
- typedef int bool;
- #else
- #error Unsupported architecture! Please adapt the source text.
- #endif
-
- /* endian conversion */
- #if defined (BIGENDIAN)
- #define ECH(x) x
- #define ECW(x) x
- #define ECVH(x) x
- #define ECVW(x) x
- #elif defined (LITTLEENDIAN)
- #define ECH(x) (((x)&0xff)<<8|((x)&0xff00)>>8)
- #define ECW(x) (((x)&0xff)<<24|((x)&0xff00)<<8|((x)&0xff0000)>>8|((x)&0xff000000)>>24)
- #define ECVH(x) l2bh(x)
- #define ECVW(x) l2bw(x)
- #else
- #error You have to define either BIGENDIAN or LITTLEENDIAN.
- #endif
-
-
- /* program constants */
-
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
- #ifndef NULL
- #define NULL 0
- #endif
-
- #define FNAMEBUFSIZE 1024 /* buffer size for file names */
- #define EXPSTACKSIZE 32 /* maximum arguments in an expression */
-
-
- /* structures */
-
- struct node {
- struct node *next;
- struct node *pred;
- };
-
- struct list {
- struct node *first;
- struct node *dummy;
- struct node *last;
- };
-
- struct CPUInstr {
- struct CPUInstr *hash_chain; /* next instruction in hash chain */
- char *name; /* instruction's name */
- uint16 flags; /* format flags */
- uint8 type; /* instruction format, see defines */
- uint8 opcd; /* opcode (bit 0-5) */
- uint8 fieldD; /* preset D field (bit 6-10) */
- uint8 fieldA; /* preset D field (bit 11-15) */
- uint16 xo; /* extended opcode (bit 21-31) */
- };
- /* CPU instruction formats */
- #define T_I 0 /* Bx */
- #define T_B 1 /* BCx */
- #define T_DD 2 /* LWZ */
- #define T_DI 3 /* ADDI */
- #define T_DS 4 /* LD */
- #define T_X 5 /* AND */
- #define T_IMM 6 /* MTFSFI */
- #define T_XLB 7 /* BCLRx */
- #define T_XSPR 8 /* MFSPR */
- #define T_XCRM 9 /* MTCRF */
- #define T_XFL 10 /* MTFSF */
- #define T_XS 11 /* SRADIx */
- #define T_A 12 /* FMADDx */
- #define T_M 13 /* RLWIMIx */
- #define T_MD 14 /* RLDICx */
- #define T_CMP 15 /* CMP */
- /* CPU instruction flags */
- #define F_SUPP_D 0x01 /* D = 0 */
- #define F_SUPP_A 0x02 /* A = 0 */
- #define F_SUPP_B 0x04 /* B = 0 */
- #define F_SUPP_C 0x08 /* C = 0 */
- #define F_CRF_D 0x10 /* D = CR field */
- #define F_CRF_S 0x20 /* S = CR field */
- #define F_SWAP 0x40 /* S instr.: D = S, A and S are swapped */
- #define F_SIGNED 0x80 /* 16 bit signed immediate */
- #define F_64BIT 0x100 /* 64 bit instruction */
- #define F_SUPER 0x200 /* supervisor-only instruction */
- #define F_OPTIONAL 0x400 /* optional instruction */
- #define F_EXTENDED 0x8000 /* extended mnemonic */
-
- struct Directive {
- struct Directive *hash_chain; /* next directive in hash chain */
- char *name; /* directive's name */
- void (*dfunct)();
- };
-
- struct Macro {
- struct Macro *hash_chain; /* next macro in hash chain */
- char *name; /* macro's name */
- char *text; /* ptr to first macro line */
- unsigned long nlines; /* number of lines in this macro */
- };
-
- struct AlignPoint { /* defines an alignment point (.align) */
- struct AlignPoint *next;
- unsigned long offset; /* section offset for alignent */
- long val; /* alignment value */
- long gap; /* current alignment gap */
- };
-
- struct Section {
- struct node n;
- char *name; /* section's name */
- uint8 type; /* type: code, data, bss, offsets, ... */
- uint8 flags;
- uint8 protection; /* readable, writable, executable, ... */
- uint8 alignment; /* number of bits, which have to be zero */
- unsigned long pc; /* current program counter (sect. offset) */
- unsigned long size; /* size of section in bytes */
- void *contents; /* contents, allocated in pass 2 */
- void *data;
- struct AlignPoint *first_align; /* pointer to first alignment point */
- struct AlignPoint *current_align; /* current alignment point */
- struct list reloclist; /* section offsets to relocate */
- struct list xreflist; /* external references in this section */
- uint32 index; /* e.g. section header index for ELF */
- };
- /* section types */
- #define ST_UNDEFINED 0
- #define ST_CODE 1 /* section contains code */
- #define ST_DATA 2 /* section contains initialized data */
- #define ST_UDATA 3 /* section contains uninitialized data */
- #define ST_STRUCT 4 /* offset section (will be discarded) */
- /* section flags */
- #define SF_DISCARD 1 /* can be discarded (e.g. ST_STRUCT) */
- #define SF_UNINITIALIZED 2 /* section has uninitialized contents */
- /* protection */
- #define SP_READ 1
- #define SP_WRITE 2
- #define SP_EXEC 4
- #define SP_SHARE 8
-
- struct Symbol {
- struct Symbol *hash_chain; /* next symbol in hash chain */
- char *name; /* symbol's name */
- uint32 value; /* absolute value or relocation offset */
- struct Section *relsect; /* symbol def. relative to this section */
- struct AlignPoint *alignpoint;/* sym. was defined after this aligment */
- uint8 type; /* absolute, relocatable or extern */
- uint8 flags;
- uint8 info; /* section, function or object */
- uint8 bind; /* local or global */
- uint32 size; /* object's size in bytes */
- };
- /* symbol type */
- #define SYM_UNDEF 0
- #define SYM_ABS 1
- #define SYM_RELOC 2
- #define SYM_EXTERN 3
- /* object type */
- #define SYMI_NOTYPE 0
- #define SYMI_OBJECT 1
- #define SYMI_FUNC 2
- #define SYMI_SECTION 3
- #define SYMI_FILE 4
- /* symbol bind */
- #define SYMB_NONE 0
- #define SYMB_LOCAL 1
- #define SYMB_GLOBAL 2
- #define SYMB_WEAK 3
-
- struct Reloc {
- struct node n;
- unsigned long offset; /* section-offset of relocation */
- uint32 addend; /* add this to relocation value */
- struct Section *relocsect; /* base addr of this sect. has to be added */
- uint8 type;
- };
- /* reloc types (identical with the reloc types used for ELF) */
- #define R_NONE 0
- #define R_PPC_ADDR32 1 /* 32-bit relocation */
- #define R_PPC_ADDR24 2 /* 26-bit relocation for B-instruction */
- #define R_PPC_ADDR16 3 /* 16-bit relocation */
- #define R_PPC_ADDR16_LO 4 /* relocation of the lower half-word */
- #define R_PPC_ADDR16_HI 5 /* relocation of the higher half-word */
- #define R_PPC_ADDR16_HA 6 /* higher half-word reloc. for ADDI */
- #define R_PPC_ADDR14 7 /* BC-instruction, 16-bit absolute */
- #define R_PPC_ADDR14_BRTAKEN 8
- #define R_PPC_ADDR14_BRNTAKEN 9
- #define R_PPC_REL24 10 /* relative 26-bit (PowerPC B-instruction) */
- #define R_PPC_REL14 11 /* BC-instruction, 16-bit relative */
- #define R_PPC_REL14_BRTAKEN 12
- #define R_PPC_REL14_BRNTAKEN 13
- #define R_PPC_GOT16 14
- #define R_PPC_GOT16_LO 15
- #define R_PPC_GOT16_HI 16
- #define R_PPC_GOT16_HA 17
- #define R_PPC_PLTREL24 18
- #define R_PPC_COPY 19
- #define R_PPC_GLOB_DAT 20
- #define R_PPC_JMP_SLOT 21
- #define R_PPC_RELATIVE 22
- #define R_PPC_LOCAL24PC 23
- #define R_PPC_UADDR32 24
- #define R_PPC_UADDR16 25
- #define R_PPC_REL32 26 /* section base offset */
- #define R_PPC_PLT32 27
- #define R_PPC_PLTREL32 28
- #define R_PPC_PLT16_LO 29
- #define R_PPC_PLT16_HI 30
- #define R_PPC_PLT16_HA 31
- #define R_PPC_SDAREL16 32
- #define R_PPC_SECTOFF 33
- #define R_PPC_SECTOFF_LO 34
- #define R_PPC_SECTOFF_HI 35
- #define R_PPC_SECTOFF_HA 36
- #define R_PPC_TOC16 255
-
- struct XReference {
- struct node n;
- struct Symbol *xsymbol; /* external symbol, which is referenced */
- unsigned long offset;
- uint32 addend;
- uint8 type; /* relocation type, see struct Reloc */
- uint8 size; /* size of reference in bytes (3 = 26bit) */
- };
-
- struct ParsedLine {
- uint8 type; /* opcode type */
- uint8 flags;
- int8 branch_hint; /* 0=no hint, 1=b. taken(+), -1=not taken(-)*/
- uint8 narg; /* value for $NARG, when calling macro */
- char *lineptr; /* ptr to source text line */
- void *opcode; /* ptr to CPUInstr, Directive or SourceText */
- char *operand; /* ptr to operand-string */
- struct ParsedLine *next; /* pasm added another opcode here, if != 0 */
- };
- /* opcode types */
- #define OT_IGNORE 0 /* line is empty or commented out */
- #define OT_INSTRUCTION 1
- #define OT_DIRECTIVE 2
- #define OT_MACRO 3
- #define OT_SECTION 4
- /* flags */
- #define PLF_NONEWLINE 1 /* new statement is still part of same line */
- #define PLF_ALIGN 2
-
- struct SourceText { /* start address and size of all text files */
- struct node n;
- char *name; /* name of source, include file or macro */
- char *text; /* source text pointer */
- unsigned long nlines; /* number of lines in source text */
- struct ParsedLine *plin; /* ParsedLine structures for nlines */
- };
-
- #define MAX_MACPARAMS 10 /* macro parameters \0-\9 */
- struct MacroParams {
- char *param[MAX_MACPARAMS]; /* parameter strings, which replace \x */
- uint32 call_id; /* macro call id */
- uint32 narg; /* number of arguments */
- char param0[2]; /* parameter 0 contains the branch hint */
- };
-
- struct SourceThread { /* main source, includes and macros */
- struct SourceThread *prev; /* previous source thread */
- struct MacroParams *macro; /* only assigned in macro mode */
- struct SourceText *csource; /* ptr to current source text node */
- char *lineptr; /* source text pointer to current line */
- char *srcptr; /* current source text pointer */
- unsigned long line; /* current line inside this thread */
- struct Macro *macskip; /* indicates macro skip mode */
- };
-
- struct Expression {
- uint32 value;
- uint8 type; /* same type definitions as used for Symbol */
- uint8 reloctype; /* see struct Reloc */
- struct Symbol *symbol; /* reloc or extern symbol, used in exp. */
- };
-
- struct UserDefine {
- struct node n;
- char *line; /* .set <symbol>,<assignment> */
- };
-
-
- #define DEF_MAXERRORS 5
- #define MAX_INCPATHS 8
- #define MAX_IFLEVELS 16
- #define LINEBUFSIZE 1024
- #define STRBUFSIZE 256
- /* number of entries in hash tables */
- #define SYMHTABSIZE 0x4000 /* symbol hash table */
- #define INSTRHTABSIZE 0x1000 /* instruction hash table */
- #define DIRHTABSIZE 0x800 /* directive hash table */
- #define MACROHTABSIZE 0x800 /* macro hash table */
- /* supported output formats */
- #define OFMT_ABSOLUTE 0
- #define OFMT_ELF 1
- #define OFMT_EHF 2
- #define OFMT_ADOS 3
- #define OFMT_LAST 3
- /* optimization flags */
- #define OPT_FAR_BRANCH 0x00010000
- /* "Bcc label" with destination out of range will be converted into a */
- /* "B!cc *+8/B label" combination. */
-
- struct GlobalVars {
- char *source_name; /* source text file name */
- char *dest_name; /* output file name */
-
- /* options */
- bool dontwarn; /* suppress warnings */
- bool noregsymbols; /* don't predefine register symbols etc. */
- bool noextmnemo; /* no extended mnemonics */
- bool sixtyfourmode; /* 64-bit mode activated */
- bool optinstrmode; /* optional instructions */
- bool supermode; /* supervisor mode instructions */
- bool autoextern; /* autom. declare undef. sym. as extern */
- uint8 output; /* output format */
- uint32 opt; /* optimization flags */
- struct list userdeflist; /* user defines */
- bool usrdefs;
-
- int maxerrors; /* # of errors to display, before aborting */
- int errcnt; /* number of errors displayed */
- int returncode; /* return code for exit() */
- char *incpaths[MAX_INCPATHS]; /* paths where to search for files */
- char *ident; /* unit identification or comment */
- char *file; /* source file name for debugging */
- unsigned long absbase; /* base address for absolute code */
- struct list sourcelist; /* source text list */
- struct list sectionlist; /* defined sections */
-
- struct SourceThread *cthread; /* current source thread */
- struct Section *csect; /* current section */
- struct Symbol *lcsym; /* location counter symbol '$' */
- struct Symbol *nargsym; /* symbol for number of arguments '$NARG' */
- struct SourceText *srctxtp; /* source text pointer for get_source() */
- uint32 macrocnt; /* incremented on every macro invocation */
- unsigned long absline; /* absolute line number */
- uint8 pass; /* 0 or 1 */
- uint8 iflevel; /* current level for conditional assembly */
- uint8 ifignore; /* number of else/endifs to ignore */
- bool ifcond[MAX_IFLEVELS]; /* ifcond[0] is always TRUE */
- bool signedexp; /* current expression to eval is signed */
- bool alignflag,vc;
- bool anotherpass; /* true, if another pass is required */
-
- /* TOC */
- int rtoc; /* register number for toc-mode */
- struct Section *tocsect; /* ptr to TOC section, or NULL */
-
- /* hash tables */
- struct Symbol **symbols; /* symbol hash table */
- struct CPUInstr **instr; /* instruction hash table */
- struct Directive **directives; /* directive hash table */
- struct Macro **macros; /* macro hash table */
-
- /* buffers */
- char linebuf[LINEBUFSIZE]; /* buffer for a whole source text line */
- char strbuf[STRBUFSIZE]; /* string buffer for labels, opcodes, etc. */
- uint8 alignment_bytes[4]; /* four zero bytes */
- };
-
-
- /* global functions */
-
- /* main.c */
- #ifndef MAIN_C
- extern struct GlobalVars gvars;
- extern void cleanup(struct GlobalVars *);
- #endif
-
- /* version.c */
- #ifndef VERSION_C
- extern void show_version(void);
- extern void show_usage(void);
- #endif
-
- /* pass.c */
- #ifndef PASS_C
- extern void exec_pass1(struct GlobalVars *);
- extern void pass1(struct GlobalVars *,struct SourceText *,
- struct MacroParams *,struct SourceThread *);
- extern struct SourceText *include_source(struct GlobalVars *,char *);
- extern void exec_pass2(struct GlobalVars *);
- extern void pass2(struct GlobalVars *,struct SourceText *,
- struct MacroParams *,struct SourceThread *);
- extern struct SourceText *get_source(struct GlobalVars *);
- #endif
-
- /* support.c */
- #ifndef SUPPORT_C
- extern void *alloc(size_t);
- extern void *alloczero(size_t);
- extern char *allocstring(char *);
- extern void initlist(struct list *);
- extern void addtail(struct list *,struct node *);
- extern struct node *remhead(struct list *);
- extern struct node *remnode(struct node *);
- extern char *mapfile(struct GlobalVars *,char *);
- extern void checkrange(uint32,int,bool);
- extern void lower_case(char *);
- #ifdef LITTLEENDIAN
- extern uint16 l2bh(uint16);
- extern uint32 l2bw(uint32);
- #endif
- #endif
-
- /* eval.c */
- #ifndef EVAL_C
- extern char *getsymbol(struct GlobalVars *,char *);
- extern char *getarg(struct GlobalVars *,char *);
- extern char *skipspaces(char *);
- extern char *remquotes(char *);
- extern void checkEOL(char *);
- extern char *skipexpression(struct GlobalVars *,char *);
- extern void read_macro_params(struct GlobalVars *,struct ParsedLine *,
- struct MacroParams *,char *);
- extern char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
- extern uint32 makereloc(struct GlobalVars *,struct Expression *);
- extern uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
- extern char *getintexp(struct GlobalVars *,char *,uint32 *);
- extern char *eval_expression(struct GlobalVars *,struct Expression *,char *);
- #endif
-
- /* tables.c */
- #ifndef TABLES_C
- extern void init_hashtables(struct GlobalVars *);
- extern void add_macro(struct GlobalVars *,struct Macro *);
- extern struct Symbol *add_symbol(struct GlobalVars *,char *,uint8,uint32);
- extern struct CPUInstr *search_instr(struct GlobalVars *,char *);
- extern unsigned long elf_hash(unsigned char *);
- extern struct Symbol *search_symbol(struct GlobalVars *,char *);
- extern struct Section *search_section(struct GlobalVars *,char *);
- extern void search_opcode(struct GlobalVars *,struct ParsedLine *,
- char *,char *);
- #endif
-
- /* errors.c */
- #ifndef ERRORS_C
- extern void error(int,...);
- extern void ierror(char *,...);
- #endif
-
- /* predefs.c */
- extern char stdsects[];
- extern char stdsets[];
- extern char *xmnemos[];
-
- /* elfrelocnames.c */
- extern char *elfrel_name[];
- #define ELFRELNAMMSK 0x3f /* number of names in elfrel_name[] minus 1 */
-
- /* instructions.c */
- #ifndef INSTRUCTIONS_C
- extern struct CPUInstr instructions[];
- extern void instr(struct GlobalVars *,struct ParsedLine *);
- extern char *check_comma(char *);
- extern void pcadd(struct GlobalVars *,unsigned long);
- extern void store_byte(struct GlobalVars *,uint8);
- extern void store_half(struct GlobalVars *,uint16);
- extern void store_word(struct GlobalVars *,uint32);
- extern void store_float(struct GlobalVars *,double);
- extern void store_double(struct GlobalVars *,double);
- extern void store_space(struct GlobalVars *,unsigned long);
- #endif
-
- /* directives.c */
- #ifndef DIRECTIVES_C
- extern struct Directive directives[];
- extern void activate_section(struct GlobalVars *,struct Section *);
- extern void alignment(struct GlobalVars *,unsigned long);
- extern char escchar(char);
- #endif
-
- /* output_abs.c */
- #ifndef OUTPUT_ABS_C
- extern void output_absolute(struct GlobalVars *);
- #endif
-
- /* output_elf.c */
- #ifndef OUTPUT_ELF_C
- extern void output_elf32msb(struct GlobalVars *);
- #endif
-
- /* output_ehf.c */
- #ifndef OUTPUT_EHF_C
- extern void output_ehf(struct GlobalVars *);
- #endif
-