home *** CD-ROM | disk | FTP | other *** search
- /* $VER: pasm tables.c 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 (01.01.98) phx
- * search_instr() is global.
- * v0.5 (08.10.97) phx
- * .globl directive declares unknown symbols in pass 1 as
- * externally defined. If the symbol is defined later in the
- * source, it will be made global by add_symbol().
- * v0.3 (05.04.97) phx
- * Minor changes.
- * 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).
- * Externally defined symbols will automatically get global binding.
- * v0.1 (11.03.97) phx
- * First test version with all PowerPC instructions and most
- * important directives. Only raw, absolute output.
- * v0.0 (22.02.97) phx
- * File created.
- */
-
-
- #define TABLES_C
- #include "ppcasm.h"
-
-
- void init_hashtables(struct GlobalVars *);
- void add_macro(struct GlobalVars *,struct Macro *);
- struct Symbol *add_symbol(struct GlobalVars *,char *,uint8,uint32);
- unsigned long elf_hash(unsigned char *);
- struct Symbol *search_symbol(struct GlobalVars *,char *);
- struct CPUInstr *search_instr(struct GlobalVars *,char *);
- struct Section *search_section(struct GlobalVars *,char *);
- void search_opcode(struct GlobalVars *,struct ParsedLine *,char *,char *);
-
- static void *alloc_hashtable(size_t);
- static void add_instruction(struct GlobalVars *,struct CPUInstr *);
- static void add_directive(struct GlobalVars *,struct Directive *);
- static struct Directive *search_directive(struct GlobalVars *,char *);
- static struct Macro *search_macro(struct GlobalVars *,char *);
- static void execute_macro(struct GlobalVars *,struct ParsedLine *);
- static void execute_directive(struct GlobalVars *,struct ParsedLine *);
-
-
-
- void init_hashtables(struct GlobalVars *gv)
- {
- struct CPUInstr *ins = instructions;
- struct Directive *dir = directives;
-
- gv->symbols = alloc_hashtable(SYMHTABSIZE);
- gv->instr = alloc_hashtable(INSTRHTABSIZE);
- gv->directives = alloc_hashtable(DIRHTABSIZE);
- gv->macros = alloc_hashtable(MACROHTABSIZE);
- while (ins->name)
- add_instruction(gv,ins++);
- while (dir->name)
- add_directive(gv,dir++);
- }
-
-
- static void *alloc_hashtable(size_t entries)
- {
- return (alloczero(entries * sizeof(void *)));
- }
-
-
- static void add_instruction(struct GlobalVars *gv,struct CPUInstr *ins)
- /* make new entry into instruction hash table */
- {
- struct CPUInstr *chain;
- unsigned long offs = elf_hash(ins->name)%INSTRHTABSIZE;
-
- if (!(ins->flags & F_EXTENDED) || !gv->noextmnemo) {
- if (chain = gv->instr[offs])
- ins->hash_chain = chain;
- else
- ins->hash_chain = NULL;
- gv->instr[offs] = ins;
- }
- }
-
-
- static void add_directive(struct GlobalVars *gv,struct Directive *dir)
- /* make new entry into directive hash table */
- {
- struct Directive *chain;
- unsigned long offs = elf_hash(dir->name)%DIRHTABSIZE;
-
- if (chain = gv->directives[offs])
- dir->hash_chain = chain;
- else
- dir->hash_chain = NULL;
- gv->directives[offs] = dir;
- }
-
-
- void add_macro(struct GlobalVars *gv,struct Macro *mac)
- /* make new entry into macro hash table */
- {
- struct Macro *chain,*m;
- unsigned long offs = elf_hash(mac->name)%MACROHTABSIZE;
-
- if (chain = m = gv->macros[offs]) { /* hash code already used? */
- do {
- if (!strcmp(m->name,mac->name)) {
- error(8,mac->name); /* macro defined twice! */
- break;
- }
- }
- while (m = m->hash_chain);
- }
- gv->macros[offs] = mac;
- mac->hash_chain = chain;
- }
-
-
- struct Symbol *add_symbol(struct GlobalVars *gv,char *name,uint8 type,
- uint32 value)
- /* define new symbol - absolute, relocatable or external */
- {
- struct Symbol *sym,*chain;
- unsigned long offs = elf_hash(name)%SYMHTABSIZE;
-
- if (chain = sym = gv->symbols[offs]) { /* hash code already used? */
- do {
- if (!strcmp(name,sym->name)) {
- if (sym->type == SYM_EXTERN) { /* declared ext. visible by .globl? */
- if ((sym->type = type) == SYM_RELOC) {
- sym->relsect = gv->csect;
- sym->alignpoint = gv->csect->current_align;
- }
- sym->value = value;
- }
- else
- error(7,name); /* symbol defined twice! */
- return (sym);
- }
- }
- while (sym = sym->hash_chain);
- }
- gv->symbols[offs] = sym = alloczero(sizeof(struct Symbol));
- sym->hash_chain = chain;
- sym->name = allocstring(name);
- sym->value = value;
- if ((sym->type = type) == SYM_RELOC) {
- sym->relsect = gv->csect;
- sym->alignpoint = gv->csect->current_align;
- }
- else if (type == SYM_EXTERN)
- sym->bind = SYMB_GLOBAL;
- return (sym);
- }
-
-
- unsigned long elf_hash(unsigned char *name)
- /* calculate a hash code as used in ELF objects */
- {
- unsigned long h=0,g;
-
- while (*name) {
- h = (h << 4) + *name++;
- if (g = h & 0xf0000000)
- h ^= g >> 24;
- h &= ~g;
- }
- return (h);
- }
-
-
- struct Symbol *search_symbol(struct GlobalVars *gv,char *name)
- /* find a symbol in the symbol hash table */
- {
- struct Symbol *chain;
- unsigned long offs = elf_hash(name)%SYMHTABSIZE;
-
- chain = gv->symbols[offs];
- while (chain) {
- if (!strcmp(chain->name,name))
- return (chain);
- chain = chain->hash_chain;
- }
- return (NULL);
- }
-
-
- struct CPUInstr *search_instr(struct GlobalVars *gv,char *name)
- /* find an instruction in the instruction hash table */
- {
- struct CPUInstr *chain;
- unsigned long offs = elf_hash(name)%INSTRHTABSIZE;
-
- chain = gv->instr[offs];
- while (chain) {
- if (!strcmp(chain->name,name))
- return (chain);
- chain = chain->hash_chain;
- }
- return (NULL);
- }
-
-
- static struct Directive *search_directive(struct GlobalVars *gv,char *name)
- /* find a directive in the directive hash table */
- {
- struct Directive *chain;
- unsigned long offs = elf_hash(name)%DIRHTABSIZE;
-
- chain = gv->directives[offs];
- while (chain) {
- if (!strcmp(chain->name,name))
- return (chain);
- chain = chain->hash_chain;
- }
- return (NULL);
- }
-
-
- static struct Macro *search_macro(struct GlobalVars *gv,char *name)
- /* find a macro in the macro hash table */
- {
- struct Macro *chain;
- unsigned long offs = elf_hash(name)%MACROHTABSIZE;
-
- chain = gv->macros[offs];
- while (chain) {
- if (!strcmp(chain->name,name))
- return (chain);
- chain = chain->hash_chain;
- }
- return (NULL);
- }
-
-
- struct Section *search_section(struct GlobalVars *gv,char *name)
- {
- struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
-
- while (nextsec = (struct Section *)sec->n.next) {
- if (!strcmp(name,sec->name))
- return (sec);
- sec = nextsec;
- }
- return (NULL);
- }
-
-
- void search_opcode(struct GlobalVars *gv,struct ParsedLine *pl,
- char *opname,char *operand)
- {
- if (gv->alignflag)
- pl->flags |= PLF_ALIGN;
- gv->alignflag = FALSE;
- if (pl->opcode = (void *)search_macro(gv,opname)) {
- pl->type = OT_MACRO;
- pl->operand = operand;
- execute_macro(gv,pl);
- }
- else if (pl->opcode = (void *)search_instr(gv,opname)) {
- pl->type = OT_INSTRUCTION;
- pl->operand = allocstring(operand);
- gv->csect->pc += 4; /* every PPC instruction has a size of 4 bytes */
- }
- else if (pl->opcode = (void *)search_directive(gv,opname)) {
- pl->type = OT_DIRECTIVE;
- pl->operand = allocstring(operand);
- execute_directive(gv,pl);
- }
- else if (pl->opcode = (void *)search_section(gv,opname)) {
- pl->type = OT_SECTION;
- activate_section(gv,(struct Section *)pl->opcode);
- }
- else
- error(10,opname); /* Unknown opcode */
- }
-
-
- static void execute_macro(struct GlobalVars *gv,struct ParsedLine *pl)
- /* creates a SourceText structure for every macro invocation, parses */
- /* macro parameters and recursively calls pass1() to execute the macro */
- {
- struct Macro *m = (struct Macro *)pl->opcode;
- struct MacroParams *mp = alloczero(sizeof(struct MacroParams));
- struct SourceText *stxt = alloc(sizeof(struct SourceText));
- char *mac_params = alloc(strlen(pl->operand)+1);
- uint32 oldnarg = gv->nargsym->value;
-
- /* create SourceText node for macro-call */
- stxt->name = m->name;
- stxt->text = m->text;
- stxt->nlines = m->nlines;
- stxt->plin = alloczero(m->nlines * sizeof(struct ParsedLine));
- addtail(&gv->sourcelist,&stxt->n);
-
- /* initialize MacroParams structure */
- mp->call_id = gv->macrocnt++;
- strcpy(mac_params,pl->operand);
- read_macro_params(gv,pl,mp,mac_params);
- pl->narg = (uint8)mp->narg;
- gv->nargsym->value = mp->narg;
-
- /* recursively call pass 1 and create new SourceThread */
- pass1(gv,stxt,mp,gv->cthread);
- gv->nargsym->value = oldnarg;
-
- /* cleanup */
- free(mp);
- pl->opcode = stxt;
- }
-
-
- static void execute_directive(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- struct Directive *d = (struct Directive *)pl->opcode;
-
- (d->dfunct)(gv,pl);
- }
-