home *** CD-ROM | disk | FTP | other *** search
- /* $VER: pasm directives.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.6 (30.10.97) phx
- * The names of macros will be converted to lower case (otherwise,
- * they would remain inaccessible ;)
- * v0.5 (12.10.97) phx
- * .set directive is allowed multiple times on the same symbol.
- * If a .set-assignment can't be resolved in pass 1, the symbol
- * is no longer undefined, but defined with an absolute default
- * value of '1'. So .ifdef will work correctly.
- * .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()/tables.c.
- * v0.4 (29.04.97) phx
- * .new_section sets type of section-symbol to SYMI_SECTION.
- * New directives: .baserel
- * v0.3 (10.04.97) phx
- * Some vbcc-specific 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).
- * Floating pointer support. New directives: .fail, .ident, .file,
- * .float, .ufloat, .double, .udouble, .local.
- * v0.1 (11.03.97) phx
- * First test version with all PowerPC instructions and most
- * important directives. Only raw, absolute output.
- * .ident and .file directives are supported, but have no effect.
- * Especially floating point directives are missing.
- * v0.0 (21.02.97) phx
- * File created.
- */
-
-
- #define DIRECTIVES_C
- #include "ppcasm.h"
-
-
- void activate_section(struct GlobalVars *,struct Section *);
- void alignment(struct GlobalVars *,unsigned long);
- char escchar(char);
-
- static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
- static char *section_attributes(struct GlobalVars *,char *,uint8 *,
- uint8 *,uint8 *,uint8 *);
- static void _uahalf(struct GlobalVars *,struct ParsedLine *);
- static void _uaword(struct GlobalVars *,struct ParsedLine *);
- static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
- static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
- static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
-
-
-
- static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- start_section(gv,pl,1);
- }
-
-
- static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- start_section(gv,pl,0);
- }
-
-
- static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
- bool force_new)
- /* define a new section with new attributes or reactivate a */
- /* previously defined one */
- {
- struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
- struct Symbol *sym;
- struct AlignPoint *ap;
- char *s,*name;
- uint8 type,flags,protection,alignment;
-
- s = getarg(gv,pl->operand); /* section's name */
- name = remquotes(gv->strbuf);
-
- while (nexts = (struct Section *)sec->n.next) {
- if (!strcmp(name,sec->name)) {
-
- if (force_new) { /* overwrite an old section with the same name? */
- sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
- name = sec->name;
- sec->name = allocstring(gv->strbuf);
- break;
- }
-
- else { /* reactivate old section with the same name */
- s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
- if (type != ST_UNDEFINED) /* attributes specified? */
- if (sec->type!=type || sec->flags!=flags ||
- sec->protection!=protection || sec->alignment!=alignment)
- error(16); /* section attributes don't match */
- pl->type = OT_SECTION;
- pl->opcode = (void *)sec;
- activate_section(gv,sec);
- checkEOL(s);
- return;
- }
-
- }
- sec = nexts;
- }
-
- /* create a new section */
- sec = alloczero(sizeof(struct Section));
- sec->name = allocstring(name);
- s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
- &sec->alignment);
- if (sec->type == ST_UNDEFINED) { /* set default attributes */
- sec->type = ST_DATA;
- sec->protection = SP_READ|SP_WRITE;
- sec->alignment = 2;
- }
- initlist(&sec->reloclist);
- initlist(&sec->xreflist);
- ap = alloc(sizeof(struct AlignPoint));
- ap->next = NULL;
- ap->offset = ap->gap = 0;
- ap->val = 1 << sec->alignment;
- sec->first_align = sec->current_align = ap;
- addtail(&gv->sectionlist,&sec->n);
- pl->type = OT_SECTION;
- pl->opcode = (void *)sec;
- activate_section(gv,sec);
- sym = add_symbol(gv,sec->name,SYM_RELOC,0);
- sym->info = SYMI_SECTION;
- checkEOL(s);
- }
-
-
- void activate_section(struct GlobalVars *gv,struct Section *sec)
- {
- gv->csect = sec; /* set active section */
- gv->lcsym->relsect = sec;
- gv->lcsym->value = sec->pc;
- }
-
-
- static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
- uint8 *f,uint8 *p,uint8 *a)
- /* fill in section attributes, if specified */
- {
- char c,*attr;
-
- *t = ST_UNDEFINED;
- *f = *p = *a = 0;
- s = skipspaces(s);
- if (*s) {
- if (*s == ',') {
- s = skipspaces(++s);
- s = getarg(gv,s);
- c = *gv->strbuf;
- if (c=='\"' || c=='\'') {
- attr = remquotes(gv->strbuf);
- while (c = *attr++) {
- switch (c) {
- /* contents type */
- case 'c':
- *t = ST_CODE;
- break;
- case 'd':
- *t = ST_DATA;
- break;
- case 'u':
- *t = ST_UDATA;
- *f |= SF_UNINITIALIZED;
- break;
- case 'i':
- *t = ST_STRUCT;
- *f |= SF_DISCARD|SF_UNINITIALIZED;
- break;
- /* protection */
- case 'r':
- *p |= SP_READ;
- break;
- case 'w':
- *p |= SP_WRITE;
- break;
- case 'x':
- *p |= SP_EXEC;
- break;
- case 's':
- *p |= SP_SHARE;
- break;
- case 'n': /* remove and discard currently not supported */
- case 'R':
- break;
- default:
- if (c>='0' && c <='6')
- *a = (uint8)(c-'0'); /* alignment */
- else
- error(15,c); /* illegal section attribute */
- break;
- }
- }
- }
- else
- error(14); /* string constant expected */
- }
- else if (*s != '#')
- error(12); /* colon expected */
- }
- return (s);
- }
-
-
- static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = getsymbol(gv,pl->operand);
- struct Expression exp;
- struct Section *cs;
- char setname[STRBUFSIZE];
- struct Symbol *sym;
-
- if (*gv->strbuf) {
- strcpy(setname,gv->strbuf);
- if (s = check_comma(s)) {
- s = eval_expression(gv,&exp,s);
- if (exp.type != SYM_UNDEF) {
- if (exp.type != SYM_EXTERN) {
- if (exp.type == SYM_RELOC) {
- if (exp.reloctype == R_PPC_ADDR32) {
- if (sym = search_symbol(gv,setname)) {
- sym->value = exp.value;
- sym->type = SYM_RELOC;
- sym->relsect = exp.symbol->relsect;
- }
- else {
- cs = gv->csect;
- gv->csect = exp.symbol->relsect;
- add_symbol(gv,setname,SYM_RELOC,exp.value);
- gv->csect = cs;
- }
- }
- else
- error(29); /* can't assign relocatable half word */
- }
- else {
- if (sym = search_symbol(gv,setname)) {
- sym->value = exp.value;
- sym->type = SYM_ABS;
- }
- else
- add_symbol(gv,setname,SYM_ABS,exp.value);
- }
- }
- else
- error(28); /* can't assign external symbol */
- }
- else {
- if (gv->pass) /* expression still undefined in pass 2 ? */
- error(19); /* undefined symbol */
- else if (!search_symbol(gv,setname))
- /* set value to 1 if unknown in first pass */
- add_symbol(gv,setname,SYM_ABS,1);
- }
- checkEOL(s);
- return;
- }
- }
- else
- error(17); /* missing argument */
- }
-
-
- static void _macro(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- struct Macro *mac = alloczero(sizeof(struct Macro));
- char *s = getsymbol(gv,pl->operand);
-
- mac->name = allocstring(gv->strbuf);
- lower_case(mac->name); /* convert macro name to lower case */
- mac->text = gv->cthread->srcptr;
- mac->nlines = gv->absline + 1;
- gv->cthread->macskip = mac;
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- checkEOL(s);
- }
-
-
- static void _include(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
-
- if (!gv->pass) { /* pass 1 */
- s = getarg(gv,pl->operand); /* include file's name */
-
- /* recursively call pass 1 and create new SourceThread */
- pass1(gv,include_source(gv,remquotes(gv->strbuf)),NULL,gv->cthread);
- checkEOL(s);
- }
-
- else /* recursively call pass 2 */
- pass2(gv,get_source(gv),NULL,gv->cthread);
- }
-
-
- void alignment(struct GlobalVars *gv,unsigned long a)
- {
- unsigned long x = (1<<a) - 1;
- unsigned long pc, oldpc = gv->csect->pc;
- struct AlignPoint *ap = gv->csect->current_align;
-
- pc = (oldpc + x) & ~x;
- if (!gv->pass) {
- if (ap->next)
- ierror("Current alignment point is not the last one!");
- ap->next = alloc(sizeof(struct AlignPoint));
- ap = ap->next;
- ap->next = NULL;
- ap->offset = oldpc;
- ap->val = 1 << a;
- ap->gap = pc - oldpc;
- gv->csect->current_align = ap;
- gv->csect->pc = pc;
- }
- else {
- if (!(gv->csect->current_align = ap->next)) /* next alignment section */
- ierror("No more alignments in list!");
- store_space(gv,pc-oldpc);
- }
- }
-
-
- static void _align(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- uint32 a=2;
- static uint8 na=0;
-
- if (pl->flags & PLF_ALIGN) {
- if (++na > 2)
- gv->vc = TRUE;
- }
- else
- na = 0;
- s = getintexp(gv,pl->operand,&a);
- alignment(gv,a);
- gv->alignflag = TRUE;
- if (!gv->pass)
- checkEOL(s);
- }
-
-
- static void _space(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- uint32 n=0;
-
- s = getintexp(gv,pl->operand,&n);
- if (!gv->pass) {
- pcadd(gv,n);
- checkEOL(s);
- }
- else
- store_space(gv,n);
- }
-
-
- char escchar(char c)
- /* convert escape code */
- {
- switch (c) {
- case 'b':
- c = 8;
- break;
- case 'f':
- c = 12;
- break;
- case 'n':
- c = 10;
- break;
- case 'r':
- c = 13;
- break;
- case 't':
- c = 8;
- break;
- }
- return (c);
- }
-
-
- static void _byte(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = pl->operand;
- char *sb,c;
- uint8 pass = gv->pass;
- uint32 i;
-
- for (;;) {
- if ((c = *s) == '\"') { /* read string */
- s = getarg(gv,s);
- sb = remquotes(gv->strbuf);
- if (!pass)
- while (c = *sb++) {
- if (c=='\\' || c=='\"')
- if (*sb++ == 0)
- break;
- pcadd(gv,1);
- }
- else
- while (c = *sb++) {
- if (c == '\\') {
- if (!(c = escchar(*sb++)))
- break;
- }
- else if (c == '\"') {
- if (!(c = *sb++))
- break;
- }
- store_byte(gv,(uint8)c);
- }
- }
-
- else { /* get integer expression */
- if (c==0 || c=='#') {
- error(17); /* missing argument */
- break;
- }
- if (!pass) {
- s = skipexpression(gv,s);
- pcadd(gv,1);
- }
- else {
- s = getintexp(gv,s,&i);
- store_byte(gv,(uint8)i);
- s = skipspaces(s);
- }
- }
-
- c = *s++;
- if (c==0 || c=='#') /* no more arguments? */
- break;
- if (c != ',') {
- error(12); /* colon expected */
- break;
- }
- s = skipspaces(s);
- }
- }
-
-
- static void _string(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = pl->operand;
- char *sb,c;
- uint8 pass = gv->pass;
-
- for (;;) {
- if ((c = *s) == '\"') { /* read string */
- s = getarg(gv,s);
- sb = remquotes(gv->strbuf);
- if (!pass) {
- while (c = *sb++) {
- if (c=='\\' || c=='\"')
- if (*sb++ == 0)
- break;
- pcadd(gv,1);
- }
- pcadd(gv,1);
- }
- else {
- while (c = *sb++) {
- if (c == '\\') {
- if (!(c = escchar(*sb++)))
- break;
- }
- else if (c == '\"') {
- if (!(c = *sb++))
- break;
- }
- store_byte(gv,(uint8)c);
- }
- store_byte(gv,0);
- }
- }
- else {
- error(14); /* string constant expected */
- break;
- }
-
- c = *s++;
- if (c==0 || c=='#') /* no more arguments? */
- break;
- if (c != ',') {
- error(12); /* colon expected */
- break;
- }
- s = skipspaces(s);
- }
- }
-
-
- static void _half(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- alignment(gv,1);
- _uahalf(gv,pl);
- }
-
-
- static void _uahalf(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = pl->operand;
- char *sb,c;
- uint8 pass = gv->pass;
- uint32 i;
-
- for (;;) {
- c = *s;
- if (c==0 || c=='#') {
- error(17); /* missing argument */
- break;
- }
- if (!pass) {
- s = skipexpression(gv,s);
- pcadd(gv,2);
- }
- else {
- s = getexp(gv,s,&i,2);
- store_half(gv,(uint16)i);
- s = skipspaces(s);
- }
-
- c = *s++;
- if (c==0 || c=='#') /* no more arguments? */
- break;
- if (c != ',') {
- error(12); /* colon expected */
- break;
- }
- s = skipspaces(s);
- }
- }
-
-
- static void _word(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- alignment(gv,2);
- _uaword(gv,pl);
- }
-
-
- static void _uaword(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = pl->operand;
- char *sb,c;
- uint8 pass = gv->pass;
- uint32 i;
-
- for (;;) {
- c = *s;
- if (c==0 || c=='#') {
- error(17); /* missing argument */
- break;
- }
- if (!pass) {
- s = skipexpression(gv,s);
- pcadd(gv,4);
- }
- else {
- s = getexp(gv,s,&i,4);
- store_word(gv,i);
- s = skipspaces(s);
- }
-
- c = *s++;
- if (c==0 || c=='#') /* no more arguments? */
- break;
- if (c != ',') {
- error(12); /* colon expected */
- break;
- }
- s = skipspaces(s);
- }
- }
-
-
- static void _float(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- alignment(gv,2);
- uafloat(gv,pl,FALSE);
- }
-
-
- static void _uafloat(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- uafloat(gv,pl,FALSE);
- }
-
-
- static void _double(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- alignment(gv,3);
- uafloat(gv,pl,TRUE);
- }
-
-
- static void _uadouble(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- uafloat(gv,pl,TRUE);
- }
-
-
- static void uafloat(struct GlobalVars *gv,struct ParsedLine *pl,bool dbl)
- {
- char *s = pl->operand;
- char *sb,c;
- uint8 pass = gv->pass;
- double f;
-
- for (;;) {
- c = *s;
- if (c==0 || c=='#') {
- error(17); /* missing argument */
- break;
- }
- if (!pass) {
- s = skipexpression(gv,s);
- pcadd(gv,dbl?8:4);
- }
- else {
- sscanf(s,"%lf",&f);
- if (dbl)
- store_double(gv,f);
- else
- store_float(gv,f);
- s = skipexpression(gv,s);
- }
-
- c = *s++;
- if (c==0 || c=='#') /* no more arguments? */
- break;
- if (c != ',') {
- error(12); /* colon expected */
- break;
- }
- s = skipspaces(s);
- }
- }
-
-
- static void _globl(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- struct Symbol *sym;
-
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (!(sym = search_symbol(gv,gv->strbuf))) {
- /* unknown in pass 1, then declare as externally defined first */
- sym = add_symbol(gv,gv->strbuf,SYM_EXTERN,0);
- }
- sym->bind = SYMB_GLOBAL;
- checkEOL(s);
- }
- else
- error(17); /* missing argument */
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _local(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- struct Symbol *sym;
-
- if (gv->pass) {
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (!(sym = search_symbol(gv,gv->strbuf)))
- error(19); /* undefined symbol */
- else
- sym->bind = SYMB_LOCAL;
- checkEOL(s);
- }
- else
- error(17); /* missing argument */
- }
- }
-
-
- static void _bss(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- static char *bssname=".bss";
- char *s;
- struct Section *bss,*old=gv->csect;
- uint32 size,align;
- char symbname[STRBUFSIZE];
- struct Symbol *sym;
-
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (!gv->pass)
- strcpy(symbname,gv->strbuf);
- if (!(s = check_comma(s)))
- return;
- s = getintexp(gv,s,&size); /* size of bss symbol */
- align = (size>=8)? 3 : 2;
- s = skipspaces(s);
- if (*s == ',') {
- s = getintexp(gv,++s,&align); /* optional aligment */
- if (align < 2)
- align = 2;
- }
- if (bss = search_section(gv,bssname)) {
- activate_section(gv,bss);
- alignment(gv,align);
- if (!gv->pass) {
- sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
- sym->info = SYMI_OBJECT;
- sym->size = size;
- sym->bind = SYMB_LOCAL;
- pcadd(gv,size);
- checkEOL(s);
- }
- else
- store_space(gv,size);
- activate_section(gv,old);
- }
- else
- error(47,bssname); /* section .bss was never defined */
- }
- else
- error(17); /* missing argument */
- }
-
-
- static void _comm(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- static char *bssname=".bss";
- char *s;
- struct Section *bss,*old=gv->csect;
- uint32 size;
- char symbname[STRBUFSIZE];
- struct Symbol *sym;
-
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (!gv->pass)
- strcpy(symbname,gv->strbuf);
- if (!(s = check_comma(s)))
- return;
- s = getintexp(gv,s,&size); /* size of bss symbol */
- if (bss = search_section(gv,bssname)) {
- activate_section(gv,bss);
- alignment(gv,(size>=8)? 3:2);
- if (!gv->pass) {
- sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
- sym->info = SYMI_OBJECT;
- sym->size = size;
- sym->bind = SYMB_GLOBAL; /* or SYMB_WEAK ?? */
- pcadd(gv,size);
- checkEOL(s);
- }
- else
- store_space(gv,size);
- activate_section(gv,old);
- }
- else
- error(47,bssname); /* section .bss was never defined */
- }
- else
- error(17); /* missing argument */
- }
-
-
- static void _type(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- struct Symbol *sym;
- uint32 type;
-
- if (gv->pass) {
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (sym = search_symbol(gv,gv->strbuf)) {
- if (s = check_comma(s)) {
- s = getintexp(gv,s,&type);
- sym->info = (uint8)type;
- checkEOL(s);
- }
- }
- else
- error(19); /* undefined symbol */
- }
- else
- error(17); /* missing argument */
- }
- }
-
-
- static void _size(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- struct Symbol *sym;
- uint32 size;
-
- if (gv->pass) {
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (sym = search_symbol(gv,gv->strbuf)) {
- if (s = check_comma(s)) {
- s = getintexp(gv,s,&size);
- sym->size = size;
- checkEOL(s);
- }
- }
- else
- error(19); /* undefined symbol */
- }
- else
- error(17); /* missing argument */
- }
- }
-
-
- static void _ifeq(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifeqs(gv,pl,0);
- }
-
-
- static void _ifne(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifeqs(gv,pl,1);
- }
-
-
- static void _ifgt(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifeqs(gv,pl,2);
- }
-
-
- static void _ifge(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifeqs(gv,pl,3);
- }
-
-
- static void _iflt(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifeqs(gv,pl,4);
- }
-
-
- static void _ifle(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifeqs(gv,pl,5);
- }
-
-
- static void ifeqs(struct GlobalVars *gv,struct ParsedLine *pl,int cond)
- {
- char *s;
- int32 val;
- bool *condptr;
-
- if (gv->iflevel < (MAX_IFLEVELS-1)) {
- condptr = &gv->ifcond[++gv->iflevel];
- *condptr = FALSE;
- s = getintexp(gv,pl->operand,&val);
- switch (cond) {
- case 0: /* eq */
- if (val==0)
- *condptr = TRUE;
- break;
- case 1: /* ne */
- if (val!=0)
- *condptr = TRUE;
- break;
- case 2: /* gt */
- if (val>0)
- *condptr = TRUE;
- break;
- case 3: /* ge */
- if (val>=0)
- *condptr = TRUE;
- break;
- case 4: /* lt */
- if (val<0)
- *condptr = TRUE;
- break;
- case 5: /* le */
- if (val<=0)
- *condptr = TRUE;
- break;
- }
- checkEOL(s);
- }
- else
- error(43); /* maximum nesting depth for conditional assembly exceeded */
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _ifdef(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifdef(gv,pl,TRUE);
- }
-
-
- static void _ifndef(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- ifdef(gv,pl,FALSE);
- }
-
-
- static void ifdef(struct GlobalVars *gv,struct ParsedLine *pl,bool c)
- {
- char *s;
- bool *condptr;
-
- if (gv->iflevel < (MAX_IFLEVELS-1)) {
- condptr = &gv->ifcond[++gv->iflevel];
- *condptr = c ? FALSE:TRUE;
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf)
- if (search_symbol(gv,gv->strbuf))
- *condptr = c;
- checkEOL(s);
- }
- else
- error(43); /* maximum nesting depth for conditional assembly exceeded */
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _else(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- if (gv->iflevel > 0) {
- gv->ifcond[gv->iflevel] = FALSE;
- checkEOL(pl->operand);
- }
- else
- error(44,".else"); /* .else without matching .if */
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _endif(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- if (gv->iflevel > 0) {
- gv->iflevel--;
- checkEOL(pl->operand);
- }
- else
- error(44,".endif"); /* .endif without matching .if */
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _fail(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- error(45); /* fail directive encountered */
- }
-
-
- static void _noop(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- }
-
-
- static void _ident(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = getarg(gv,pl->operand); /* identification / comment */
-
- gv->ident = allocstring(remquotes(gv->strbuf));
- checkEOL(s);
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _file(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s = getarg(gv,pl->operand); /* source file name */
-
- gv->file = allocstring(remquotes(gv->strbuf));
- checkEOL(s);
- pl->type = OT_IGNORE; /* ignore in pass 2 */
- }
-
-
- static void _baserel(struct GlobalVars *gv,struct ParsedLine *pl)
- {
- char *s;
- struct Symbol *sym;
- uint32 tocreg;
-
- if (gv->pass) {
- s = getsymbol(gv,pl->operand);
- if (*gv->strbuf) {
- if (sym = search_symbol(gv,gv->strbuf)) {
- if (s = check_comma(s)) {
- s = getintexp(gv,s,&tocreg);
- if (sym->info == SYMI_SECTION) {
- /* activate new base relative addressing mode */
- gv->tocsect = sym->relsect;
- gv->rtoc = (int)tocreg;
- }
- else
- error(50,sym->name); /* symbol is not a section base address */
- checkEOL(s);
- }
- }
- else
- error(19); /* undefined symbol */
- }
- else
- error(17); /* missing argument */
- }
- }
-
-
-
- struct Directive directives[] = {
- 0,".new_section",_new_section,
- 0,".section",_section,
- 0,".set",_set,
- 0,".macro",_macro,
- 0,".include",_include,
- 0,".align",_align,
- 0,".space",_space,
- 0,".byte",_byte,
- 0,".ascii",_byte,
- 0,".string",_string,
- 0,".asciiz",_string,
- 0,".half",_half,
- 0,".short",_half,
- 0,".word",_word,
- 0,".long",_word,
- 0,".float",_float,
- 0,".double",_double,
- 0,".uahalf",_uahalf,
- 0,".uashort",_uahalf,
- 0,".uaword",_uaword,
- 0,".ualong",_uaword,
- 0,".uafloat",_uafloat,
- 0,".uadouble",_uadouble,
- 0,".globl",_globl,
- 0,".global",_globl,
- 0,".extern",_globl,
- 0,".local",_local,
- 0,".bss",_bss,
- 0,".lcomm",_bss,
- 0,".comm",_comm,
- 0,".type",_type,
- 0,".size",_size,
- 0,".if",_ifne,
- 0,".ifeq",_ifeq,
- 0,".ifne",_ifne,
- 0,".ifgt",_ifgt,
- 0,".ifge",_ifge,
- 0,".iflt",_iflt,
- 0,".ifle",_ifle,
- 0,".ifdef",_ifdef,
- 0,".ifndef",_ifndef,
- 0,".else",_else,
- 0,".endif",_endif,
- 0,".fail",_fail,
- 0,".ident",_ident,
- 0,".file",_file,
- 0,".baserel",_baserel,
- 0,0 /* end mark */
- };
-