home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 219_01 / a48util.c < prev    next >
Text File  |  1989-01-13  |  14KB  |  529 lines

  1. /*
  2.     HEADER:        CUG219;
  3.     TITLE:        8048 Cross-Assembler (Portable);
  4.     FILENAME:    A48UTIL.C;
  5.     VERSION:    0.2;
  6.     DATE:        11/09/1988;
  7.  
  8.     DESCRIPTION:    "This program lets you use your computer to assemble
  9.             code for the Intel 8048 family of microprocessors.
  10.             The program is written in portable C rather than BDS
  11.             C.  All assembler features are supported except
  12.             relocation, linkage, and macros.";
  13.  
  14.     KEYWORDS:    Software Development, Assemblers, Cross-Assemblers,
  15.             Intel, 8048;
  16.  
  17.     SYSTEM:        CP/M-80, CP/M-86, HP-UX, MSDOS, PCDOS, QNIX;
  18.     COMPILERS:    Aztec C86, Aztec CII, CI-C86, Eco-C, Eco-C88, HP-UX,
  19.             Lattice C, Microsoft C,    QNIX C;
  20.  
  21.     WARNINGS:    "This program has compiled successfully on 2 UNIX
  22.             compilers, 5 MSDOS compilers, and 2 CP/M compilers.
  23.             A port to Toolworks C is untried."
  24.  
  25.     AUTHORS:    William C. Colley III;
  26. */
  27.  
  28. /*
  29.               8048 Cross-Assembler in Portable C
  30.  
  31.         Copyright (c) 1985,1987 William C. Colley, III
  32.  
  33. Revision History:
  34.  
  35. Ver    Date        Description
  36.  
  37. 0.0    APR 1987    Adapted from version 2.4 of my portable 1805A cross-
  38.             assembler.  WCC3.
  39.  
  40. 0.1    AUG 1988    Fixed a bug in the command line parser that puts it
  41.             into a VERY long loop if the user types a command line
  42.             like "A48 FILE.ASM -L".  WCC3 per Alex Cameron.
  43.  
  44. 0.2    NOV 1988    Fixed a name conflict between a variable and a goto
  45.             label that caused some compilers to choke.  WCC3.
  46.  
  47. This module contains the following utility packages:
  48.  
  49.     1)  symbol table building and searching
  50.  
  51.     2)  opcode and operator table searching
  52.  
  53.     3)  listing file output
  54.  
  55.     4)  hex file output
  56.  
  57.     5)  error flagging
  58. */
  59.  
  60. /*  Get global goodies:  */
  61.  
  62. #include "a48.h"
  63.  
  64. /*  Make sure that MSDOS compilers using the large memory model know    */
  65. /*  that calloc() returns pointer to char as an MSDOS far pointer is    */
  66. /*  NOT compatible with the int type as is usually the case.        */
  67.  
  68. char *calloc();
  69.  
  70. /*  Get access to global mailboxes defined in A18.C:            */
  71.  
  72. extern char errcode, line[], title[];
  73. extern int eject, listhex;
  74. extern unsigned address, bytes, errors, listleft, obj[], pagelen;
  75.  
  76. /*  The symbol table is a binary tree of variable-length blocks drawn    */
  77. /*  from the heap with the calloc() function.  The root pointer lives    */
  78. /*  here:                                */
  79.  
  80. static SYMBOL *sroot = NULL;
  81.  
  82. /*  Add new symbol to symbol table.  Returns pointer to symbol even if    */
  83. /*  the symbol already exists.  If there's not enough memory to store    */
  84. /*  the new symbol, a fatal error occurs.                */
  85.  
  86. SYMBOL *new_symbol(nam)
  87. char *nam;
  88. {
  89.     SCRATCH int i;
  90.     SCRATCH SYMBOL **p, *q;
  91.     void fatal_error();
  92.  
  93.     for (p = &sroot; (q = *p) && (i = strcmp(nam,q -> sname)); )
  94.     p = i < 0 ? &(q -> left) : &(q -> right);
  95.     if (!q) {
  96.     if (!(*p = q = (SYMBOL *)calloc(1,sizeof(SYMBOL) + strlen(nam))))
  97.         fatal_error(SYMBOLS);
  98.     strcpy(q -> sname,nam);
  99.     }
  100.     return q;
  101. }
  102.  
  103. /*  Look up symbol in symbol table.  Returns pointer to symbol or NULL    */
  104. /*  if symbol not found.                        */
  105.  
  106. SYMBOL *find_symbol(nam)
  107. char *nam;
  108. {
  109.     SCRATCH int i;
  110.     SCRATCH SYMBOL *p;
  111.  
  112.     for (p = sroot; p && (i = strcmp(nam,p -> sname));
  113.     p = i < 0 ? p -> left : p -> right);
  114.     return p;
  115. }
  116.  
  117. /*  Opcode table search routine.  This routine pats down the opcode    */
  118. /*  table for a given opcode and returns either a pointer to it or    */
  119. /*  NULL if the opcode doesn't exist.                    */
  120.  
  121. OPCODE *find_code(nam)
  122. char *nam;
  123. {
  124.     OPCODE *bsearch();
  125.  
  126.     static OPCODE opctbl[] = {
  127.     { ADD_OP + (R0 << 4) + 10,        0x60,    "ADD"    },
  128.     { ADD_OP + (R0 << 4) + 10,        0x70,    "ADDC"    },
  129.     { LOG_OP + (R0 << 4) + 10,        0x50,    "ANL"    },
  130.     { OUTPUT + (P4 << 4) + 4,        0x90,    "ANLD"    },
  131.     { LNG_JMP,                0x14,    "CALL"    },
  132.     { ONE_ARG + (F0 << 4) + 4,        0x27,    "CLR"    },
  133.     { ONE_ARG + (F0 << 4) + 4,        0x37,    "CPL"    },
  134.     { ONE_ARG + (A << 4) + 1,        0x57,    "DA"    },
  135.     { PSEUDO,                DB,    "DB"    },
  136.     { INC_DEC + (R0 << 4) + 8,        0xc0,    "DEC"    },
  137.     { ONE_ARG + (TCNTI << 4) + 2,        0x15,    "DIS"    },
  138.     { REG_CND + (R0 << 4) + 8,        0xe0,    "DJNZ"    },
  139.     { PSEUDO,                DS,    "DS"    },
  140.     { PSEUDO,                DW,    "DW"    },
  141.     { PSEUDO + ISIF,            ELSE,    "ELSE"    },
  142.     { ONE_ARG + (TCNTI << 4) + 2,        0x05,    "EN"    },
  143.     { PSEUDO,                END,    "END"    },
  144.     { PSEUDO + ISIF,            ENDIF,    "ENDIF"    },
  145.     { ONE_ARG + (CLK << 4) + 1,        0x75,    "ENT0"    },
  146.     { PSEUDO,                EQU,    "EQU"    },
  147.     { PSEUDO + ISIF,            IF,    "IF"    },
  148.     { A_REG_1 + (P1 << 4) + 2,        0x00,    "IN"    },
  149.     { INC_DEC + (R0 << 4) + 10,        0x10,    "INC"    },
  150.     { PSEUDO,                INCL,    "INCL"    },
  151.     { A_REG_1 + (BUS << 4) + 1,        0x00,    "INS"    },
  152.     { JMP_CND,                0x12,    "JB0"    },
  153.     { JMP_CND,                0x32,    "JB1"    },
  154.     { JMP_CND,                0x52,    "JB2"    },
  155.     { JMP_CND,                0x72,    "JB3"    },
  156.     { JMP_CND,                0x92,    "JB4"    },
  157.     { JMP_CND,                0xb2,    "JB5"    },
  158.     { JMP_CND,                0xd2,    "JB6"    },
  159.     { JMP_CND,                0xf2,    "JB7"    },
  160.     { JMP_CND,                0xf6,    "JC"    },
  161.     { JMP_CND,                0xb6,    "JF0"    },
  162.     { JMP_CND,                0x76,    "JF1"    },
  163.     { LNG_JMP,                0x04,    "JMP"    },
  164.     { ONE_ARG + (AT_A << 4) + 1,        0xb3,    "JMPP"    },
  165.     { JMP_CND,                0xe6,    "JNC"    },
  166.     { JMP_CND,                0x86,    "JNI"    },
  167.     { JMP_CND,                0x26,    "JNT0"    },
  168.     { JMP_CND,                0x46,    "JNT1"    },
  169.     { JMP_CND,                0x96,    "JNZ"    },
  170.     { JMP_CND,                0x36,    "JT0"    },
  171.     { JMP_CND,                0x56,    "JT1"    },
  172.     { JMP_CND,                0x16,    "JTF"    },
  173.     { JMP_CND,                0xc6,    "JZ"    },
  174.     { MOV + (R0 << 4) + 10,            0x00,    "MOV"    },
  175.     { A_REG_2 + (P4 << 4) + 4,        0x00,    "MOVD"    },
  176.     { A_AT_A + (AT_A << 4) + 1,        0xa3,    "MOVP"    },
  177.     { A_AT_A + (AT_A << 4) + 1,        0xe3,    "MOVP3"    },
  178.     { A_REG_2 + (AT_R0 << 4) + 2,        0x80,    "MOVX"    },
  179.     { NO_ARG,                0x00,    "NOP"    },
  180.     { PSEUDO,                ORG,    "ORG"    },
  181.     { LOG_OP + (R0 << 4) + 10,        0x40,    "ORL"    },
  182.     { OUTPUT + (P4 << 4) + 4,        0x80,    "ORLD"    },
  183.     { OUTPUT + (BUS << 4) + 3,        0x00,    "OUTL"    },
  184.     { PSEUDO,                PAGE,    "PAGE"    },
  185.     { PSEUDO,                REGI,    "REG"    },
  186.     { NO_ARG,                0x83,    "RET"    },
  187.     { NO_ARG,                0x93,    "RETR"    },
  188.     { ONE_ARG + (A << 4) + 1,        0xe7,    "RL"    },
  189.     { ONE_ARG + (A << 4) + 1,        0xf7,    "RLC"    },
  190.     { ONE_ARG + (A << 4) + 1,        0x77,    "RR"    },
  191.     { ONE_ARG + (A << 4) + 1,        0x67,    "RRC"    },
  192.     { ONE_ARG + (MB0 << 4) + 4,        0xc5,    "SEL"    },
  193.     { PSEUDO,                SET,    "SET"    },
  194.     { ONE_ARG + (TCNT << 4) + 1,        0x65,    "STOP"    },
  195.     { ONE_ARG + (CNT << 4) + 2,        0x45,    "STRT"    },
  196.     { ONE_ARG + (A << 4) + 1,        0x47,    "SWAP"    },
  197.     { PSEUDO,                TITL,    "TITL"    },
  198.     { A_REG_1 + (R0 << 4) + 10,        0x20,    "XCH"    },
  199.     { A_REG_1 + (AT_R0 << 4) + 2,        0x30,    "XCHD"    },
  200.     { ADD_OP + (R0 << 4) + 10,        0xd0,    "XRL"    }
  201.     };
  202.  
  203.     return bsearch(opctbl,opctbl + (sizeof(opctbl) / sizeof(OPCODE)),nam);
  204. }
  205.  
  206. /*  Operator table search routine.  This routine pats down the        */
  207. /*  operator table for a given operator and returns either a pointer    */
  208. /*  to it or NULL if the opcode doesn't exist.                */
  209.  
  210. OPCODE *find_operator(nam)
  211. char *nam;
  212. {
  213.     OPCODE *bsearch();
  214.  
  215.     static OPCODE oprtbl[] = {
  216.     { UNARY  + UOP1  + OPR,        '$',        "$"    },
  217.     { REG,                A,        "A"    },
  218.     { BINARY + LOG1  + OPR,        AND,        "AND"    },
  219.     { REG,                BUS,        "BUS"    },
  220.     { REG,                C,        "C"    },
  221.     { REG,                CLK,        "CLK"    },
  222.     { REG,                CNT,        "CNT"    },
  223.     { BINARY + RELAT + OPR,        '=',        "EQ"    },
  224.     { REG,                F0,        "F0"    },
  225.     { REG,                F1,        "F1"    },
  226.     { BINARY + RELAT + OPR,        GE,        "GE"    },
  227.     { BINARY + RELAT + OPR,        '>',        "GT"    },
  228.     { UNARY  + UOP3  + OPR,        HIGH,        "HIGH"    },
  229.     { REG,                I,        "I"    },
  230.     { BINARY + RELAT + OPR,        LE,        "LE"    },
  231.     { UNARY  + UOP3  + OPR,        LOW,        "LOW"    },
  232.     { BINARY + RELAT + OPR,        '<',        "LT"    },
  233.     { REG,                MB0,        "MB0"    },
  234.     { REG,                MB1,        "MB1"    },
  235.     { BINARY + MULT  + OPR,        MOD,        "MOD"    },
  236.     { BINARY + RELAT + OPR,        NE,        "NE"    },
  237.     { UNARY  + UOP2  + OPR,        NOT,        "NOT"    },
  238.     { BINARY + LOG2  + OPR,        OR,        "OR"    },
  239.     { REG,                P1,        "P1"    },
  240.     { REG,                P2,        "P2"    },
  241.     { REG,                P4,        "P4"    },
  242.     { REG,                P5,        "P5"    },
  243.     { REG,                P6,        "P6"    },
  244.     { REG,                P7,        "P7"    },
  245.     { REG,                PSW,        "PSW"    },
  246.     { REG,                R0,        "R0"    },
  247.     { REG,                R1,        "R1"    },
  248.     { REG,                R2,        "R2"    },
  249.     { REG,                R3,        "R3"    },
  250.     { REG,                R4,        "R4"    },
  251.     { REG,                R5,        "R5"    },
  252.     { REG,                R6,        "R6"    },
  253.     { REG,                R7,        "R7"    },
  254.     { REG,                RB0,        "RB0"    },
  255.     { REG,                RB1,        "RB1"    },
  256.     { BINARY + MULT  + OPR,        SHL,        "SHL"    },
  257.     { BINARY + MULT  + OPR,        SHR,        "SHR"    },
  258.     { REG,                T,        "T"    },
  259.     { REG,                TCNT,        "TCNT"    },
  260.     { REG,                TCNTI,        "TCNTI"    },
  261.     { BINARY + LOG2  + OPR,        XOR,        "XOR"    }
  262.     };
  263.  
  264.     return bsearch(oprtbl,oprtbl + (sizeof(oprtbl) / sizeof(OPCODE)),nam);
  265. }
  266.  
  267. s