/* ---------------------------------------------------------------------- * FILE: symbol.c * PACKAGE: as31 - 8031/8051 Assembler. * * DESCRIPTION: * This file contains the symbol table search/insertion routines * associated with user defined symbols. * * The reserved keyword (instructions/directives) look up routine * is defined here. * * The opcode table for all of the instructions is located in this * file. * * REVISION HISTORY: * Jan. 19, 1990 - Created. (Ken Stauffer) * * AUTHOR: * All code in this file written by Ken Stauffer (University of Calgary) * January, 1990. * */ #include "as31.h" #define NULL (0) #define B(a) (0xF0+(a)) #define ACC(a) (0xE0+(a)) #define PSW(a) (0xD0+(a)) #define T2CON(a) (0xC8+(a)) #define IP(a) (0xB8+(a)) #define P3(a) (0xB0+(a)) #define IE(a) (0xA8+(a)) #define P2(a) (0xA0+(a)) #define SCON(a) (0x98+(a)) #define P1(a) (0x90+(a)) #define TCON(a) (0x88+(a)) #define P0(a) (0x80+(a)) /* ---------------------------------------------------------------------- * sinit[] * These symbols are not reserved keywords. * This array contains the initial symbol table entries * for the user symbol table. The symbols are * basically convienient names that make writting * in 8031/8051 bearable. * * The function syminit() inserts these entries into the * symbol table. * */ static struct symbol sinit[] = { { "AC", LABEL, PSW(6), NULL }, { "ACC", LABEL, ACC(0), NULL }, { "B", LABEL, B(0), NULL }, { "CY", LABEL, PSW(7), NULL }, { "DPH", LABEL, 0x83, NULL }, { "DPL", LABEL, 0x82, NULL }, { "EA", LABEL, IE(7), NULL }, { "ES", LABEL, IE(4), NULL }, { "ET0", LABEL, IE(1), NULL }, { "ET1", LABEL, IE(3), NULL }, { "ET2", LABEL, IE(5), NULL }, { "EX0", LABEL, IE(0), NULL }, { "EX1", LABEL, IE(2), NULL }, { "EXEN2", LABEL, T2CON(3),NULL }, { "EXF2", LABEL, T2CON(6),NULL }, { "F0", LABEL, PSW(5), NULL }, { "IE", LABEL, IE(0), NULL }, { "IE0", LABEL, TCON(1),NULL }, { "IE1", LABEL, TCON(3),NULL }, { "IP", LABEL, IP(0), NULL }, { "IT0", LABEL, TCON(0),NULL }, { "IT1", LABEL, TCON(2),NULL }, { "OV", LABEL, PSW(2), NULL }, { "P", LABEL, PSW(0), NULL }, { "P0", LABEL, P0(0), NULL }, { "P1", LABEL, P1(0), NULL }, { "P2", LABEL, P2(0), NULL }, { "P3", LABEL, P3(0), NULL }, { "PCON", LABEL, 0x87, NULL }, { "PS", LABEL, IP(4), NULL }, { "PSW", LABEL, PSW(0), NULL }, { "PT0", LABEL, IP(1), NULL }, { "PT1", LABEL, IP(3), NULL }, { "PT2", LABEL, IP(5), NULL }, { "PX0", LABEL, IP(0), NULL }, { "PX1", LABEL, IP(2), NULL }, { "RB8", LABEL, SCON(2),NULL }, { "RCAP2H", LABEL, 0xCB, NULL }, { "RCAP2L", LABEL, 0xCA, NULL }, { "RCLK", LABEL, T2CON(5),NULL }, { "REN", LABEL, SCON(4),NULL }, { "RI", LABEL, SCON(0),NULL }, { "RL2", LABEL, T2CON(0),NULL }, { "RS0", LABEL, PSW(3), NULL }, { "RS1", LABEL, PSW(4), NULL }, { "SBUF", LABEL, 0x99, NULL }, { "SCON", LABEL, SCON(0),NULL }, { "SM0", LABEL, SCON(7),NULL }, { "SM1", LABEL, SCON(6),NULL }, { "SM2", LABEL, SCON(5),NULL }, { "SP", LABEL, 0x81, NULL }, { "T2CON", LABEL, T2CON(0),NULL }, { "TB8", LABEL, SCON(3),NULL }, { "TCLK", LABEL, T2CON(4),NULL }, { "TCON", LABEL, TCON(0),NULL }, { "TF0", LABEL, TCON(5),NULL }, { "TF1", LABEL, TCON(7),NULL }, { "TF2", LABEL, T2CON(7),NULL }, { "TH0", LABEL, 0x8C, NULL }, { "TH1", LABEL, 0x8D, NULL }, { "TH2", LABEL, 0xCD, NULL }, { "TI", LABEL, SCON(1),NULL }, { "TL0", LABEL, 0x8A, NULL }, { "TL1", LABEL, 0x8B, NULL }, { "TL2", LABEL, 0xCC, NULL }, { "TMOD", LABEL, 0x89, NULL }, { "TR0", LABEL, TCON(4),NULL }, { "TR1", LABEL, TCON(6),NULL }, { "TR2", LABEL, T2CON(2),NULL } }; #define SINITSIZE (sizeof(sinit)/sizeof(sinit[0])) /* ---------------------------------------------------------------------- * opcode vectors: * These arrays contain the various opcodes for the * various forms an instruction may take. * * The ordering of these opcodes is very critical to the * proper fuctioning of the assembler. * * When a given form of an instruction is parsed, the parser * indexes one of these arrays by the correct amount and thus * obtains the correct opcode for the particular form. * */ static unsigned char acall[]= { 0x11 }; static unsigned char add[]= { 0x28, 0x25, 0x26, 0x24 }; static unsigned char addc[]= { 0x38, 0x35, 0x36, 0x34 }; static unsigned char ajmp[]= { 0x01 }; static unsigned char anl[]= { 0x58, 0x55, 0x56, 0x54, 0x52, 0x53, 0x82, 0xb0 }; static unsigned char cjne[]= { 0xb5, 0xb4, 0xb8, 0xb6 }; static unsigned char clr[]= { 0xe4, 0xc3, 0xc2 }; static unsigned char cpl[]= { 0xf4, 0xb3, 0xb2 }; static unsigned char da[]= { 0xd4 }; static unsigned char dec[]= { 0x14, 0x18, 0x15, 0x16 }; static unsigned char div[]= { 0x84 }; static unsigned char djnz[]= { 0xd8, 0xd5 }; static unsigned char inc[]= { 0x04, 0x08, 0x05, 0x06, 0xa3 }; static unsigned char jb[]= { 0x20 }; static unsigned char jbc[]= { 0x10 }; static unsigned char jc[]= { 0x40 }; static unsigned char jmp[]= { 0x73 }; static unsigned char jnb[]= { 0x30 }; static unsigned char jnc[]= { 0x50 }; static unsigned char jnz[]= { 0x70 }; static unsigned char jz[]= { 0x60 }; static unsigned char lcall[]= { 0x12 }; static unsigned char ljmp[]= { 0x02 }; static unsigned char mov[]= { 0xe8, 0xe5, 0xe6, 0x74, 0xf5, 0x75, 0xf8, 0xa8, 0x78, 0x88, 0x85, 0x86, 0xf6, 0xa6, 0x76, 0x90, 0xa2, 0x92 }; static unsigned char movc[]= { 0x93, 0x83 }; static unsigned char movx[]= { 0xe2, 0xe3, 0xe0, 0xf2, 0xf3, 0xf0 }; static unsigned char mul[]= { 0xa4 }; static unsigned char nop[]= { 0x00 }; static unsigned char orl[]= { 0x48, 0x45, 0x46, 0x44, 0x42, 0x43, 0x72, 0xa0 }; static unsigned char pop[]= { 0xd0 }; static unsigned char push[]= { 0xc0 }; static unsigned char ret[]= { 0x22 }; static unsigned char reti[]= { 0x32 }; static unsigned char rl[]= { 0x23 }; static unsigned char rlc[]= { 0x33 }; static unsigned char rr[]= { 0x03 }; static unsigned char rrc[]= { 0x13 }; static unsigned char setb[]= { 0xd3, 0xd2 }; static unsigned char sjmp[]= { 0x80 }; static unsigned char subb[]= { 0x98, 0x95, 0x96, 0x94 }; static unsigned char swap[]= { 0xc4 }; static unsigned char xch[]= { 0xc8, 0xc5, 0xc6 }; static unsigned char xchd[]= { 0xd6 }; static unsigned char xrl[]= { 0x68, 0x65, 0x66, 0x64, 0x62, 0x63 }; /* ---------------------------------------------------------------------- * optable[] * This table contains opcodes, directives and a few reserved * symbols. * * The second field is the keywords token value. * * Unless the symbol is an opcode, the third field will * be NULL. * * The third field is a pointer to an array of opcode bytes. * */ static struct opcode optable[] = { {"a", A, NULL }, {"ab", AB, NULL }, {"acall", ACALL, acall }, {"add", ADD, add }, {"addc", ADDC, addc }, {"ajmp", AJMP, ajmp }, {"anl", ANL, anl }, {"byte", D_BYTE, NULL }, {"c", C, NULL }, {"cjne", CJNE, cjne }, {"clr", CLR, clr }, {"cpl", CPL, cpl }, {"da", DA, da }, {"dec", DEC, dec }, {"div", DIV, div }, {"djnz", DJNZ, djnz }, {"dptr", DPTR, NULL }, {"end", D_END, NULL }, {"equ", D_EQU, NULL }, {"flag", D_FLAG, NULL }, {"inc", INC, inc }, {"jb", JB, jb }, {"jbc", JBC, jbc }, {"jc", JC, jc }, {"jmp", JMP, jmp }, {"jnb", JNB, jnb }, {"jnc", JNC, jnc }, {"jnz", JNZ, jnz }, {"jz", JZ, jz }, {"lcall", LCALL, lcall }, {"ljmp", LJMP, ljmp }, {"mov", MOV, mov }, {"movc", MOVC, movc }, {"movx", MOVX, movx }, {"mul", MUL, mul }, {"nop", NOP, nop }, {"org", D_ORG, NULL }, {"orl", ORL, orl }, {"pc", PC, NULL }, {"pop", POP, pop }, {"push", PUSH, push }, {"r0", R0, NULL }, {"r1", R1, NULL }, {"r2", R2, NULL }, {"r3", R3, NULL }, {"r4", R4, NULL }, {"r5", R5, NULL }, {"r6", R6, NULL }, {"r7", R7, NULL }, {"ret", RET, ret }, {"reti", RETI, reti }, {"rl", RL, rl }, {"rlc", RLC, rlc }, {"rr", RR, rr }, {"rrc", RRC, rrc }, {"setb", SETB, setb }, {"sjmp", SJMP, sjmp }, {"skip", D_SKIP, NULL }, {"subb", SUBB, subb }, {"swap", SWAP, swap }, {"word", D_WORD, NULL }, {"xch", XCH, xch }, {"xchd", XCHD, xchd }, {"xrl", XRL, xrl } }; #define OPTABSIZE (sizeof(optable)/sizeof(struct opcode)) /* ---------------------------------------------------------------------- * strcase: * A case IN-sensitive string compare. * */ strcase(s,t) char *s,*t; { for( ; (*s|040) == (*t|040); s++, t++) if( *s == '\0') return(0); return( (*s|040) - (*t|040) ); } /* ---------------------------------------------------------------------- * lookop: * Do a binary search through optable[], for a matching * symbol. Return the symbol found or NULL. * */ struct opcode *lookop(s) char *s; { register int low,high,mid,cond; low = 0; high = OPTABSIZE-1; while( low<=high ) { mid = (low+high)/2; if( (cond = strcase(s,optable[mid].name)) < 0 ) high = mid-1; else if(cond > 0 ) low = mid+1; else return(&optable[mid]); } return(NULL); } /* ---------------------------------------------------------------------- * symtab, hash, looksym: * User symbol table routines. * symtab is the hash table for the user symbols. * (chaining is used for collision resolution). * */ static struct symbol *symtab[HASHTABSIZE]; static hash(s) char *s; { register char *p; register unsigned h=0,g; for(p=s; *p; p++) { h = (h<<4) + *p; if( g = h&0xf0000000 ) { h = h ^ (g >> 24); h = h ^ g; } } return( h % HASHTABSIZE ); } struct symbol *looksym(s) char *s; { register struct symbol *ptr,*prev; char *malloc(),*p; register int hv; hv = hash(s); prev = NULL; for(ptr=symtab[hv]; ptr; ptr = ptr->next) { if( !strcmp(ptr->name,s) ) { if( prev != NULL ) { prev->next = ptr->next; ptr->next = symtab[hv]; symtab[hv] = ptr; } return(ptr); } prev = ptr; } if( p = malloc(strlen(s)+1) ) strcpy(p,s); else error("Cannot allocate %d bytes",strlen(s)+1); ptr = (struct symbol *) malloc( sizeof(struct symbol) ); if( ptr == NULL ) error("Cannot allocate %d bytes",sizeof(struct symbol)); ptr->name = p; ptr->type = UNDEF; ptr->next = symtab[hv]; symtab[hv] = ptr; return(ptr); } /* ---------------------------------------------------------------------- * syminit: * Initializes the hash table, with the initial symbols from * sinit[] * */ syminit() { register int i,hv; for(i=0; i