diff a09.c @ 33:7c5379eb406e

nitors9 version
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Jul 2018 15:22:54 +0900
parents 3c14d647bb51
children 2032755628dc
line wrap: on
line diff
--- a/a09.c	Sat Jul 14 15:16:39 2018 +0900
+++ b/a09.c	Sat Jul 14 15:22:54 2018 +0900
@@ -1,4 +1,4 @@
-/* A09, 6809 Assembler.
+/* A09, 6809 Assembler2
 
    created 1993,1994 by L.C. Benschop.
    copyleft (c) 1994-2014 by the sbc09 team, see AUTHORS for more details.
@@ -60,6 +60,36 @@
 #define LINELEN 128
 
 static int debug=0;
+static struct incl {
+    char *name;
+    struct incl *next;
+} *incls = 0;
+
+static struct longer {
+    int gline;
+    int change;
+     struct longer *next;
+} *lglist = 0;
+
+void makelonger(int gl) {
+    for(struct longer *p=lglist;p;p=p->next) {
+        if (p->gline==gl) { // already fixed
+            p->change = 1;
+            return;
+        }
+    }
+    struct longer *p = (struct longer *)calloc(sizeof(struct longer *),1);
+    p->gline=gl;
+    p->next = lglist;
+    lglist = p;
+}
+
+int longer() {
+    for(struct longer *p=lglist;p;p=p->next) {
+        if (p->change == 0) return 1;
+    }
+    return 0;
+}
 
 struct oprecord{char * name;
                 unsigned char cat;
@@ -121,8 +151,9 @@
   {"FCW",13,9},
   {"FDB",13,9},
   {"IF",13,10},
-  {"IFEQ",13,29},
-  {"IFGT",13,30},
+  {"IFEQ",13,30},
+  {"IFGT",13,29},
+  {"IFNDEF",13,33},
   {"IFNE",13,28},
   {"IFP1",13,21},
   {"INC",10,0x0c},{"INCA",0,0x4c},{"INCB",0,0x5c},
@@ -178,11 +209,13 @@
 struct symrecord{char name[MAXIDLEN+1];
                  char cat;
                  unsigned short value;
+                 struct symrecord *next;
                 };
 
 int symcounter=0;
 int os9 = 0;   // os9 flag
 int prevloc = 0;
+int prevrmb = 0;
 struct symrecord * prevlp = 0;
 
 /* expression categories...
@@ -262,7 +295,7 @@
 
 FILE *listfile,*objfile;
 char *listname,*objname,*srcname,*curname;
-int lineno;
+int lineno,glineno;
 
 void
 outsymtable()
@@ -319,8 +352,9 @@
 {
     generating = 1;
     if (prevloc) {
+       prevrmb = loccounter+1;  // we were in rmb mode
        oldlc = loccounter  = prevloc-1 ;
-       os9 = prevloc = 0;
+       prevloc = 0;
     }
 }
 
@@ -340,7 +374,7 @@
  while(1) {
    c=*srcptr++;
    if(c>='a'&&c<='z')c-=32;
-   if(c!='.'&&c!='$'&&(c<'0'||c>'9')&&(c<'A'||c>'Z'))break;
+   if(c!='_'&&c!='@'&&c!='.'&&c!='$'&&(c<'0'||c>'9')&&(c<'A'||c>'Z'))break;
    if(i<MAXIDLEN)namebuf[i++]=c;
  }
  namebuf[i]=0;
@@ -455,8 +489,8 @@
  if(isalpha(c))return scanlabel();
  else if(isdigit(c))return scandecimal();
  else switch(c) {
-  case '*' : if(prevloc) { srcptr++;exprcat|=2;return prevloc-1; }
-  case '.' : srcptr++;exprcat|=2;return loccounter;
+  case '*' : srcptr++;exprcat|=2; if(prevloc) return prevloc-1; else return loccounter;
+  case '.' : srcptr++;exprcat|=2; if(prevrmb) return prevrmb-1; else return loccounter;
   case '$' : return scanhex();
   case '%' : return scanbin();
   case '&' : /* compatibility */
@@ -897,15 +931,15 @@
 void
 setlabel(struct symrecord * lp)
 {
- if (prevlp) {
+ while (prevlp) {
      struct symrecord *l = prevlp;
-     prevlp = 0;
+     prevlp = prevlp->next;
      setlabel(l);
  }
  if(lp) {
   if(lp->cat!=13&&lp->cat!=6) {
    if(lp->cat!=2||lp->value!=loccounter)
-    error|=8;
+    ; // error|=8;
   } else {
    lp->cat=2;
    lp->value=loccounter;
@@ -942,8 +976,9 @@
     break;
  case 4: case 6: offs=(unsigned short)operand-loccounter-codeptr-2;
                 if(offs<-128||offs>=128||opsize==3||unknown||!certain) {
-                  if((!unknown)&&opsize==2&&(offs<-128||offs>=128) )
-                     error|=16;
+                  if((!unknown)&&opsize==2&&(offs<-128||offs>=128) ) {
+                     error|=16; makelonger(glineno);
+                  }
                   offs--;
                   opsize=3;
                   postbyte++;
@@ -999,7 +1034,20 @@
  scanoperands();
  if(mode!=1&&mode!=2)error|=2;
  offs=(unsigned short)operand-loccounter-2;
- if(!unknown&&(offs<-128||offs>=128))error|=16;
+ if(!unknown&&(offs<-128||offs>=128)) {
+     error|=16;makelonger(glineno);
+     if (co==0x20) {
+         if(mode!=1&&mode!=2)error|=2;
+         putbyte(0x16);
+         putword(operand-loccounter-3);
+     } else {
+         if(mode!=1&&mode!=2)error|=2;
+         putbyte(0x10);
+         putbyte(co);
+         putword(operand-loccounter-4);
+     }
+     return;
+ }
  if(pass==2&&unknown)error|=4;
  putbyte(co);
  putbyte(offs);
@@ -1170,6 +1218,10 @@
  case 0:/* RMB */
         //   in OS9 mode, this generates no data
         //   loccounter will be reset after any code to the current code generation
+        if (prevrmb) {
+            oldlc = loccounter  = prevrmb-1 ;
+            prevrmb = 0;
+        }
         setlabel(lp);
         operand=scanexpr(0);
         if(unknown)error|=4;
@@ -1191,7 +1243,7 @@
           if(exprcat==2)lp->cat=2;
           else lp->cat=0;
           lp->value=operand;
-         } else error|=8;
+         } // else error|=8;
         }
         break;
  case 7:/* FCB */
@@ -1253,24 +1305,24 @@
         break;                
  case 29: /* IFGT */
         operand=scanexpr(0);
-        if(unknown)error|=4;
-        if(operand>0)suppress=2;
+        if(operand<=0)suppress=2;
         break;                
  case 31: /* IFLT */
         operand=scanexpr(0);
-        if(unknown)error|=4;
-        if(operand<0)suppress=2;
+        if(operand>=0)suppress=2;
         break;                
  case 30: /* IFEQ */
         operand=scanexpr(0);
-        if(unknown)error|=4;
-        if(operand==0)suppress=2;
+        if(operand!=0)suppress=2;
         break;                
  case 28: /* IFNE */
  case 10: /* IF */
         operand=scanexpr(0);
-        if(unknown)error|=4;
-        if(!operand)suppress=2;
+        if(operand==0)suppress=2;
+        break;                
+ case 33: /* IFNDEF */
+        operand=scanexpr(0);
+        if(!unknown)suppress=2;
         break;                
  case 12: /* ORG */
          operand=scanexpr(0);
@@ -1297,7 +1349,7 @@
           if(exprcat==2)lp->cat=3;
           else lp->cat=1;
           lp->value=operand;
-         } else error|=8;
+         } // else error|=8;
         }
         break;
    case 2: /* END */
@@ -1400,7 +1452,10 @@
   }
   else error|=0x8000;
  } else {
-     prevlp = lp;    // os9 mode label can be data or code 
+     if (lp) {
+         lp->next = prevlp;
+         prevlp = lp;    // os9 mode label can be data or code 
+     }
  }
  if(pass==2) {
   outbuffer();
@@ -1428,7 +1483,7 @@
  skipspace();
  scanname();op=findop(namebuf);
  if(op && op->cat==13) {
-  if(op->code==10||op->code==13||op->code==29||op->code==28||op->code==21||op->code==30) ifcount++;
+  if(op->code==10||op->code==13||op->code==29||op->code==28||op->code==21||op->code==30||op->code==31||op->code==33) ifcount++;
   else if(op->code==3) {
    if(ifcount>0)ifcount--;else if(suppress==1|suppress==2)suppress=0;
   } else if(op->code==1) {
@@ -1477,6 +1532,17 @@
      } else if(strcmp(v[i],"-l")==0) {
        listname=v[i+1];
        i+=2;
+     } else if(strcmp(v[i],"-I")==0) {
+       struct incl *j = (struct incl *)malloc(sizeof(struct incl));
+       j->name = v[i+1];
+       j->next  = 0;
+       if (!incls) incls = j;
+       else { 
+           struct incl *k=incls ;
+           for(; k->next ; k = k->next ) ;
+           k->next = j;
+       }
+       i+=2;
      } else if(*v[i]=='-') {
          usage(v[0]);
      } else {
@@ -1528,19 +1594,27 @@
    }
    if (i>0) {
        char *next = strconcat(oldname,i+1,name);
-       if((srcfile=fopen(next,"r"))==0) {
-          fprintf(stderr,"Cannot open source file %s\n",next);
-          exit(4);
+       if((srcfile=fopen(next,"r"))!=0) {
+          curname = next;
        }
-       curname = next;
-   } else {
+   } 
+   if (!srcfile) {
+     for( struct incl *d = incls; d ; d = d->next) {
+          char *next = strconcat(d->name,0,name);
+          if((srcfile=fopen(next,"r"))!=0) {
+             curname = next;
+             break;
+          }
+     }
+   }
+ }
+ if (!srcfile) {
      fprintf(stderr,"Cannot open source file %s\n",name);
      exit(4);
-   }
  }
  while(!terminate&&fgets(inpline,128,srcfile)) {
    expandline();
-   lineno++;
+   lineno++; glineno++;
    srcptr=srcline;
    if(suppress)suppressline(); else processline();
  }
@@ -1570,12 +1644,14 @@
   c=getchar();
   if(c=='n'||c=='N') exit(3);
  }
+ do {
  pass=2;
  prevloc = 0;
  loccounter=0;
  errors=0;
  generating=0;
  terminate=0;
+ glineno=0;
  if(listing&&((listfile=fopen(listname,"w"))==0)) {
   fprintf(stderr,"Cannot open list file");
   exit(4);
@@ -1585,6 +1661,7 @@
   exit(4);
  }
  processfile(srcname);
+ } while (longer());
  fprintf(stderr,"%d Pass 2 errors.\n",errors);
  if(listing) {
   fprintf(listfile,"%d Pass 2 errors.\n",errors);