home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / C64-128Toolkit / RA.ARC / RA2.C < prev    next >
Encoding:
C/C++ Source or Header  |  2019-04-13  |  8.7 KB  |  383 lines

  1. /* 
  2.  * ╥EVERSE ┴SSEMBLER
  3.  * ╘RANSLATION ╥OUTINES
  4.  * ╞ILENAME: RA2.C
  5.  * ═ODIFIED:
  6.  *   11/02/85 - ╥EMOVED DASHES BETWEEN EXTERNAL LABELS
  7.  *   04/14/86 - ┴DDED 'SYMBOL+OFFSET' SYNTAX OUTPUT.
  8.  */
  9. #INCLUDE "RA.H"
  10.  
  11. /* EXTERNAL DATA */
  12. EXTERN ╞╔╠┼ OBJ;
  13. EXTERN ╞╔╠┼ LST;
  14. EXTERN STRUCT LABEL *XDEFHD;
  15. EXTERN STRUCT LABEL *XREFHD;
  16. EXTERN CHAR *CODEBUF;
  17. EXTERN UNSIGNED CODESZ,BIAS,DATASZ,PROMPT;
  18. EXTERN UNSIGNED *RELBUF;
  19.  
  20. EXTERN CHAR *MTABLE[];  /* MNEMONIC STRINGS */
  21. EXTERN CHAR OPCODES[];  /* OPCODE TO MNEMONIC INDEX TRANSLATION */
  22. EXTERN CHAR AMODES[];   /* OPCODE TO ADDRESSING MODE TRANSLATION */
  23. EXTERN CHAR MODESZ[];   /* MODE TO ADDRESS FIELD SIZE */
  24. /* 
  25.  * ╨ACKAGE GLOBAL DATA
  26.  *
  27.  */
  28. CHAR *CODEPTR; /* CODE BUFFER POINTER */
  29. INT COUNT;     /* CODE COUNTER */
  30. CHAR EFUNC;    /* TRUE WHEN END OF FUNCTION DETECTED (C$106) */
  31. UNSIGNED LOC;  /* CURRENT LOCATION */
  32. INT *RELPTR;   /* RELOCATION INFO POINTER */
  33. STRUCT LABEL *CURSYM; /* CURRENT SYMBOL */
  34. STRUCT LABEL *XDEFPTR,*XREFPTR; /* POINTER TO NEXT XDEF, XREF */
  35.  
  36. /*
  37.  * ╨RINT ADDRESS VALUE AS EITHER A SYMBOLIC QUANTITY OR HEX VALUE
  38.  * ├ALLED WITH:
  39.  *   ┴DDRESS, ADDRESSING MODE, SIZE (0-2)
  40.  */
  41. PAV(A,M,S)
  42. UNSIGNED A,M,S;
  43.  IF (!CKREF()) █    /* XREF PENDING?  */
  44.    IF (M != ╔══) █  /* DON'T DO SYMBOL SEARCH FOR IMMEDIATE OPERANDS */
  45.      IF (CKSYM(A)) RETURN;
  46.    ▌
  47.    IF (S==2) FPRINTF(LST,"$%04X",A);
  48.    ELSE FPRINTF(LST,"$%02X",A);
  49.  ▌
  50.  
  51. /*
  52.  * ╨RINT ADDRESS FIELD BASED ON OPCODE
  53.  * ├ALLED WITH:
  54.  *   ADDRESS
  55.  *   ADDRESSING MODE
  56.  *   SIZE (1 OR 2)
  57.  */
  58. PAF(A,M,S)
  59. UNSIGNED A,M,S;
  60.   UNSIGNED ADDR; /* ADDRESS VALUE */
  61.  
  62.   SWITCH (M) /* PREFIX? */
  63.   █
  64.   CASE ┴├├: FPUTC('┴',LST);
  65.             BREAK;
  66.  
  67.   CASE ╔══: FPUTC('#',LST);
  68.             PAV(A,M,S);
  69.             BREAK;
  70.   CASE ┌┼╥:
  71.   CASE ┴┬╙:    
  72.             PAV(A,M,S);
  73.             BREAK;
  74.  
  75.   CASE ┌╨╪:
  76.   CASE ┴┬╪: PAV(A,M,S);
  77.             FPRINTF(LST,",╪");
  78.             BREAK;
  79.  
  80.   CASE ┌╨┘:
  81.   CASE ┴┬┘: PAV(A,M,S);
  82.             FPRINTF(LST,",┘");
  83.             BREAK;
  84.  
  85.   CASE ╔═╨: BREAK;
  86.  
  87.   CASE ╥┼╠: 
  88. #UNDEF ╧╠─╫┴┘
  89.  
  90.             IF (A>=128) █ /* SIGN EXTEND */
  91.               ADDR = (0XFF00 ▀ A);
  92.               FPRINTF(LST,"*%D",ADDR+2);
  93.             ▌
  94.             ELSE █
  95.               FPRINTF(LST,"*+%D",A+2);
  96.             ▌
  97. #IFDEF ╧╠─╫┴┘
  98.             ADDR=ADDR+LOC+2;
  99.             PAV(ADDR,M,S);
  100. #ENDIF           
  101.             BREAK;
  102.  
  103.   CASE ╔╬─╪: FPUTC('(',LST);
  104.              PAV(A,M,S);
  105.              FPRINTF(LST,",╪)");
  106.              BREAK;
  107.  
  108.   CASE ╔╬─┘: FPUTC('(',LST);
  109.              PAV(A,M,S);
  110.              FPRINTF(LST,"),┘");
  111.              BREAK;
  112.  
  113.   CASE ╔╬─: FPUTC('(',LST);
  114.             PAV(A,M,S);
  115.             FPUTC(')',LST);
  116.             BREAK;
  117.  
  118.   DEFAULT: FPRINTF(LST,"????");
  119.  
  120.   ▌
  121.  
  122. /* 
  123.  * ═AIN ROUTINE FOR THIS PACKAGE
  124.  *
  125.  */
  126. RVRS()
  127.   CHAR OP;
  128.   UNSIGNED A1,A2,DEFCNT;
  129.   UNSIGNED MODE,IMODE,SIZE,I;
  130.  
  131.   CODEPTR = CODEBUF;
  132.   RELPTR = RELBUF;
  133.   XDEFPTR = XDEFHD;
  134.   XREFPTR = XREFHD;
  135.   LOC = BIAS;
  136.   COUNT = CODESZ;
  137.   IMODE = 1; /* ALWAYS START IN INSTRUCTION MODE */
  138.   EFUNC = 0;
  139.   IF (!COUNT) CKDEF(); 
  140.   ELSE
  141.   WHILE (COUNT) █
  142.     IF (CKDEF() ▀▀ EFUNC) IMODE=CKMODE();
  143.     EFUNC = 0;
  144.     IF (!OPCODES[*CODEPTR]) █ /* INVALID OPCODE? */
  145.       FPRINTF(LST,";!!!╔NVALID OPCODE - SWITCHING TO BYTE MODE.\N");
  146.       IMODE=0;
  147.     ▌ 
  148.     IF (IMODE==0) █
  149.       DOBYTE();
  150.       IF (COUNT) IMODE = CKMODE();
  151.     ▌
  152.     ELSE █         /* INSTRUCTION MODE */
  153.       OP = *CODEPTR++;
  154.       COUNT--;
  155.       MODE = AMODES[OP];
  156.       SIZE = MODESZ[MODE];
  157.       A1=0;
  158.       A2=0;
  159.       IF (SIZE) █
  160.         A1 = *CODEPTR++;
  161.         COUNT--;
  162.         IF (SIZE==2) █
  163.           A2 = *CODEPTR++;
  164.           COUNT--;
  165.         ▌
  166.       ▌
  167.       IF (COUNT<0) █
  168.         FPRINTF(LST,"--- CODE UNDERFLOW ---\N");
  169.         ABORT();
  170.       ▌
  171. #IFDEF ─┼┬╒╟
  172.       FPRINTF(LST,"%02X %02X %02X / %04X  ",OP,A1,A2,LOC);
  173. #ENDIF
  174.       FPRINTF(LST," %S ",MTABLE[OPCODES[OP]]);
  175.       IF (SIZE==2)
  176.         A1 = A1 ▀ (A2 << 8);
  177.       PAF(A1,MODE,SIZE); /* PRINT ADDRESS FIELD */
  178.       FPUTC('\N',LST);
  179.       LOC=LOC+SIZE+1;
  180.     ▌                    /* INSTRUCTION MODE */
  181.   ▌ /* WHILE */
  182.   DODATA();              /* OUTPUT DATA BLOCKS */
  183.   FPUTC('\N',LST);
  184.  
  185. /* 
  186.  * ╞ORMAT DATA IN .BYTE MODE UNTIL A NEXT LABEL DEFINITION.
  187.  *
  188.  */
  189. DOBYTE()
  190.   UNSIGNED BYTECNT=8,FIRST=1;
  191.  
  192.   WHILE (COUNT) █
  193.     IF (CKDEF()) BREAK;  
  194.     IF (BYTECNT==8) █
  195.       IF (!FIRST) FPUTC('\N',LST);
  196.       FIRST=0;
  197.       BYTECNT=0;
  198. #IFDEF ─┼┬╒╟
  199.       FPRINTF(LST,"           %04X  ",LOC);
  200. #ENDIF
  201.       FPRINTF(LST," .BYTE ");
  202.     ▌
  203.     FPRINTF(LST,"%C $%02X ",(BYTECNT>0 ? ',' : ' '),*CODEPTR++);
  204.     BYTECNT++;
  205.     COUNT--;
  206.     LOC++;
  207.   ▌ /* WHILE */
  208.   FPUTC('\N',LST);
  209.   
  210. /*
  211.  * ╙EE IF CURRENT LOCATION HAS ONE OR MORE LABELS DEFINED.
  212.  * ╥ETURNS A COUNT OF LABELS DEFINED FOR THIS LOCATION.
  213.  */
  214. CKDEF()
  215.  UNSIGNED DC;
  216.  
  217.  DC = 0;
  218.  WHILE (XDEFPTR && (LOC >= XDEFPTR->OFFSET)) █
  219.    IF (XDEFPTR->GLOBAL) █
  220.      IF (!DC) █
  221.        FPUTC('\N',LST); /* SKIP LINE ON FIRST LABEL */
  222.      ▌
  223.      DC++;
  224.      IF ((XDEFPTR->FLAG==0) ▀▀ (XDEFPTR->OFFSET < LOC)) █ /* ABSOLUTE? */
  225.        FPRINTF(LST,"%-12S = $%04X\N",XDEFPTR->NAME,XDEFPTR->OFFSET);
  226.      ▌
  227.      ELSE
  228.        FPRINTF(LST,"%S\N",XDEFPTR->NAME);
  229.    ▌
  230.    CURSYM = XDEFPTR; /* SAVE CURRENT SYMBOL */
  231.    XDEFPTR = XDEFPTR->NEXT;
  232.  ▌
  233.  RETURN(DC);
  234.  
  235. /* 
  236.  * ╙EE IF CURRENT LOCATION HAS AN EXTERNAL REFERENCE.
  237.  *
  238.  */
  239. CKREF()
  240.  IF (XREFPTR && (LOC == XREFPTR->OFFSET)) █
  241. /*
  242.  * ╚ERE LIES A KLUDGE WHICH ASSISTS IN THE DETERMINATION OF THE FORMATTING
  243.  * MODE TO BE USED.  ╔F A REFERENCE TO RUNTIME ROUTINE ├$106 IS BEING MADE,
  244.  * WE ARE ABOUT TO EXIT A FUNCTION.  ╫HAT FOLLOWS COULD BE ANOTHER FUNCTION
  245.  * OR IT COULD BE THE BEGINNING OF UNLABELED PRESET STRING OR ARRAY DATA.  
  246.  * ╘HE MAIN LOOP TESTS THE FLAG 'EFUNC' WHICH IS SET HERE TO SEE IF A MODE
  247.  * CHECK IS NECESSARY.
  248.  */
  249.    EFUNC = !STRCMP(XREFPTR->NAME,"C$106");
  250.    IF (XREFPTR->FLAG == 1) FPUTC('>',LST); /* HIGH ORDER BYTE */
  251.    ELSE IF (XREFPTR->FLAG == 2) FPUTC('<',LST); /* LOW ORDER BYTE */
  252.    FPRINTF(LST,"%S",XREFPTR->NAME);
  253.    XREFPTR = XREFPTR->NEXT;
  254.    IF (EFUNC) FPUTC('\N',LST);
  255.    RETURN(1);
  256.  ▌
  257.  ELSE RETURN(0);
  258.  
  259. /*
  260.  * ╙EE IF ADDRESS VALUE MATCHES EXTERNAL SYMBOL DEFINITION OFFSET 
  261.  * ╥ETURNS SYMBOL OFFSET IF FOUND, ZERO OTHERWISE.  ╘HIS ASSUMES
  262.  * THAT ZERO IS AN INVALID OFFSET, WHICH IN FACT, IT IS, SINCE THE
  263.  * CODE AT ZERO IS ALWAYS A JMP C$START.
  264.  */
  265. CKSYM(A)
  266. UNSIGNED A;
  267. #DEFINE ═┴╪─╔╞╞ 127  /* MAX DISPLACEMENT FOR SYMBOL EXPRESSION */
  268.  
  269.   STRUCT LABEL *PTR,*CLOSEST;
  270.   REGISTER UNSIGNED DIFF,MIN;
  271.  
  272.   PTR = XDEFHD; /* GET XDEF LIST POINTER */
  273.   MIN = ═┴╪─╔╞╞ + 1;
  274.   WHILE (PTR) █  /* NOTHING FANCY - JUST A LINEAR SEARCH */
  275.     DIFF = A - PTR->OFFSET;
  276.     IF ((A >= PTR->OFFSET) && (DIFF <= ═┴╪─╔╞╞)) █
  277.       IF (DIFF == 0) █
  278.         MIN = 0;
  279.         CLOSEST = PTR;
  280.         BREAK;
  281.       ▌
  282.       ELSE IF (DIFF < MIN) █
  283.         MIN = DIFF;
  284.         CLOSEST = PTR;
  285.       ▌
  286.     ▌
  287.     PTR = PTR->NEXT;
  288.   ▌
  289.   IF (MIN <= ═┴╪─╔╞╞) █
  290.     FPRINTF(LST,"%S",CLOSEST->NAME);
  291.     IF (MIN) FPRINTF(LST,"+%D",MIN);
  292.     RETURN(CLOSEST->OFFSET);
  293.   ▌
  294.   RETURN 0;
  295.  
  296. /* 
  297.  * ├HECK FOR FORMATTING MODE CHANGE.
  298.  * ╥ETURNS 1 FOR INSTRUCTION MODE, 0 FOR .BYTE MODE
  299.  *
  300.  */
  301. CKMODE()
  302.   CHAR C1,C2; /* NEXT 2 BYTE VALUES */
  303.   CHAR S[20]; /* RESPONSE STRING */  
  304.   C1 = *CODEPTR;
  305.   C2 = *(CODEPTR+1);
  306.  
  307.   IF (PROMPT) █ /* USER WANTS AUTHORITY */
  308.     PRINTF("CURRENT SYMBOL: %S\NFIRST 2 BYTES: %02X %02X\N",CURSYM->NAME,C1,C2);
  309.     FOR (;;) █
  310.       PRINTF("╔NSTRUCTION OR ┬YTE MODE? ");
  311.       GETS(S);
  312.       SWITCH(*S) █
  313.       CASE '╔':
  314.       CASE 'I': RETURN(1);
  315.       CASE '┬':
  316.       CASE 'B': RETURN(0);
  317.       DEFAULT: PRINTF("┼NTER AN ╔ OR A ┬, PLEASE\N");
  318.       ▌
  319.     ▌
  320.   ▌
  321.   ELSE █
  322.  
  323.     /*********************************************************************
  324.      * ╚ERE COMES THE BIG KLUDGE, FOLKS!  ╔N ORDER TO DECIDE WHETHER THE *
  325.      * CODE THAT FOLLOWS IS INSTRUCTION OR DATA, WE TEST FOR THE PATTERN *
  326.      * 'STA $FB' WHICH SEEMS TO OCCUR AT THE ENTRY TO EVERY PROCEDURE.   *
  327.      * ┴NOTHER POSSIBILITY IS THE JMP C$START AT THE BEGINNING OF EACH   *
  328.      * CODE SEGMENT.                                                     *
  329.      * ╔F THESE PATTERNS ARE NOT DETECTED, THEN SWITCH TO DATA MODE AND  *
  330.      * OUTPUT .BYTE DIRECTIVES.                                          *
  331.      *********************************************************************/
  332.  
  333.     IF ((C1==0X85) && (C2==0XFB))
  334.       RETURN(1);       /* SET INSTRUCTION MODE */
  335.     ELSE IF (XREFPTR && (LOC == XREFPTR->OFFSET))
  336.       RETURN 1;
  337.     ELSE
  338.       RETURN(0);
  339.   ▌
  340.  
  341. /*
  342.  * ╧UTPUT ─ATA ┬LOCKS
  343.  *
  344.  */
  345.  
  346. DODATA()
  347.   UNSIGNED CNT,SIZE;
  348.   CHAR ID[═┴╪╔─];
  349.  
  350.   CNT = GETW(OBJ); /* GET NUMBER OF ENTRIES */
  351.   IF (CNT) █
  352.     FPRINTF(LST,"\N;═ODULE DATA BLOCKS.\N");
  353.  
  354. #IFDEF ─┼┬╒╟
  355.     FPRINTF(LST,"%D DATA BLOCKS.\N",CNT);
  356. #ENDIF
  357.  
  358.     WHILE (CNT--) █
  359.       GETID(ID,OBJ); /* GET IDENTIFIER */
  360.       SIZE = GETW(OBJ);
  361.       FPRINTF(LST,"%-10S .DSEG %D\N",ID,SIZE);
  362.     ▌
  363.   ▌
  364.  
  365.