home *** CD-ROM | disk | FTP | other *** search
- /* z8 Cross Assembler for Commodore Amiga.
-
- Written by: Bob Bush (Compuserve-73105,1332) 14-Apr-1989
-
- Copyright (C) 1989 R.Bush. All rights reserved.
-
- This program is freely distributable as long as this copyright notice
- is retained. It intended for personal, non-commercial use.
-
-
- Brief Syntax notes:
- R0 thru R15 always refer to working register set.
- All other registers are addressed with the colon opertor eg.
- ld r:$ff,#1 ;load absolute register 255 with a '1'
- ld r:2,#0 ;load absolute register 2 with a '0'
-
- Additional: If this code seems somewhat sporadic it no doubt is..
- Could be due to the fact that the entire program was developed
- in a few days while sitting in front of a terminal (Amiga).
- This happens be my favorite method of program development <:
-
- */
-
- /* Amiga note: Compiled with Lattice 'C' 4.0 lc -L -v -cw z8ca */
-
- /* Modifications :
-
- 1) allow symbols to be case sensitive.
- 2) allow math operations on defs.
- 3) fixed bug in Intel Hex file output.
- 4) added sorted symbol table option.
- 5) enabled 'DS' pseudo op.
- 6) Bug fixed in 'DB' evaluation which prevented spaces after
- pseudo op.
- */
-
- #include <string.h>
- #include <stdio.h>
-
- /* #define DEBUG 1 */
-
- struct symbol { /* symbol table entry */
- struct symbol *next;
- char *label;
- int value;
- };
-
- #define HASHSIZE 101
-
- struct symbol *hashtab[HASHSIZE];
- struct symbol **spoint;
-
- struct def { /* entry for a define */
- struct def *next;
- char *label;
- char *substitute;
- };
-
- struct def *deftab[HASHSIZE];
-
-
- struct optable {
- int dest; /* valid operand for destination argument */
- int source; /* valid operand for source argument */
- int numbytes; /* number of bytes generated for this opcode */
- int opcode; /* the primary opcode byte */
- int opr1; /* formation rules for second byte */
- int opr2; /* formation rules for third byte */
- };
-
- /* argument sub classification (8bit reg specification as working reg) */
-
- #define WORKING 1
-
- /* opcode formation rules for second and/or third bytes (used in optable) */
-
- #define DESTSL4_OR_SOURCE 1
- #define OPCODE_OR_DESTSL4 2
- #define ZSOURCE 3
- #define ZDEST 4
- #define DATA8 5
- #define OPCODE_OR_SOURCESL4 6
- #define CC_OR_OP 7
- #define RELATIVE 8
- #define SOURCESL4_OR_DEST 9
-
- /* operand address mode descriptors used in (optable) */
-
- #define R4 1 /* working register 4 bit descriptor */
- #define R8 2 /* 8 bit register */
- #define IR4 3 /* indirect working register - 4 bits only */
- #define IR8 4 /* indirect register - 8 bits */
- #define IRR4 5 /* indirect working register pair */
- #define IRR8 6 /* indirect register pair */
- #define XX 7 /* indexed address */
- #define RR8 9 /* register pair */
- #define IM8 10 /* immediate 8-bit data */
- #define DA 11 /* direct 16-bit address */
- #define IMP 12 /* implied operand */
- #define RR4 13 /* working register pair */
- #define CC 14 /* condition code */
- #define RA 15 /* relative address */
-
-
- /* syntax descriptions for opcode (used in syntax structure) */
-
- #define DEST_SOURCE 1 /* standard (dest,source) format */
- #define DEST_ONLY 2 /* standard (dest) format */
- #define IMPLIED 3 /* implied operand (eg. NOP) */
- #define CREATE_JR 4 /* jump relative (eg JR NZ,DEST) */
- #define CREATE_DJ 5 /* djnz */
- #define CREATE_JP 6 /* cc jump */
-
- #include "optab.h"
-
- struct pseudo {
- char *mne; /* ascii mneumonic */
- };
-
- struct pseudo ps[] = {
- "Invalid",
- "ORG",
- "DB",
- "DW",
- "DS",
- "EQU",
- "DEF"
- };
-
- #define PSSIZE sizeof(ps) / sizeof(ps[0])
-
- struct cc_code {
- char *mne;
- int cc_value;
- };
-
- /* note: hi nibble is the condition code */
-
- struct cc_code cc[] = {
- "C",0x70,
- "NC",0xf0,
- "Z",0x60,
- "NZ",0xe0,
- "PL",0xd0,
- "MI",0x50,
- "OV",0x40,
- "NOV",0xc0,
- "EQ",0x60,
- "NE",0xe0,
- "GE",0x90,
- "LT",0x10,
- "GT",0xa0,
- "LE",0x20,
- "UGE",0xf0,
- "ULT",0x70,
- "UGT",0xb0,
- "ULE",0x30
- };
-
- #define CCSIZE sizeof (cc) / sizeof(cc[0])
-
- char *args[] = {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- };
-
- char cur_sym[40];
- char fbuff[101];
- char dbuff[101];
-
- int pc;
- unsigned char bincode[25];
- int bincode_index = 0;
-
- unsigned char bin_line[128];
- int bin_pc = 0;
- int bindex = 0;
- unsigned char checksum = 0;
-
- int syntax_index;
- int arg_val,arg_type,arg_subclass;
- int arg1_val,arg1_type,arg1_subclass;
- int arg2_val,arg2_type,arg2_subclass;
- int radix;
- int pcinc;
- char *curline;
- int pass;
- unsigned char code_line[8];
- int code_line_index;
- int line_no;
- int bytes_generated;
-
- struct symbol *lookup();
- struct def *lookup_def();
- struct def *lookup_def1();
- int special_def;
- int sym_cmp();
- int nsyms = 0;
- int sym_list = 0; /* default no symbol table listing */
-
- FILE *fpin = NULL;
- FILE *fpout = NULL;
- char out_fname[64];
- char in_fname[64];
-
- int listdb;
- int list_on;
- int fout_type;
-
- /* .hex file types */
-
- #define MOTOROLA 1
- #define INTEL 2
- #define Z8 3
-
- char *parse_line;
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int j;
-
- printf("\n\11z8 Cross Assembler Ver. 1.2\n");
-
- strcpy(in_fname,argv[1]);
- strcat(in_fname,".asm");
-
- if(!(fpin = fopen(in_fname,"r")))
- errexit2("Can't open input file");
-
- strcpy(out_fname,argv[1]);
- strcat(out_fname,".hex");
-
- fout_type = MOTOROLA;
- list_on = 0;
-
- if(argc > 2)
- for(j = 2; j < argc; j++)
- sel_opt(argv[j]);
-
- bytes_generated = 0;listdb = 1;
-
- pass = 1; line_no = 1; pc = 0;
- printf("Pass 1:\n");
- while(fgets(fbuff,100,fpin)) {
- strcpy(dbuff,fbuff);
- /* strupr_esc(fbuff); */
- curline = fbuff; /* establish current line pointer */
- code_line_index = 0; pcinc = 0;
- evaluate();
- line_no++;
- }
- fclose(fpin); /* end of pass #1 */
-
- pass = 2; line_no = 1; pc = 0;bytes_generated = 0;
-
- printf("Pass 2:\n");
-
- if(!(fpin = fopen(in_fname,"r")))
- errexit2("Can't re-open input file");
- if(!(fpout = fopen(out_fname,"w")))
- errexit2("Can't open output file");
-
- while(fgets(fbuff,100,fpin)) {
- strcpy(dbuff,fbuff); /* save un-altered copy of source code */
- /* strupr_esc(fbuff); convert to upper case */
- curline = fbuff; /* establish current line pointer */
- code_line_index = 0; pcinc = 0;
- evaluate(); /* grunt out some code */
- line_no++;
- }
- fclose(fpin);
-
- if(fout_type == Z8)
- fprintf(fpout,"+\n"); /* terminate for z8 Basic loader */
- else
- if(fout_type == MOTOROLA)
- end_m();
- else
- end_i(); /* INTEL */
-
- fclose(fpout);
- printf("\n\11Assembly Complete..\n");
- printf("\11%d Bytes Generated.\n",bytes_generated);
-
- list_symbols();
- }
-
- errexit2(s) /* fatal (any:>) error exit */
- char *s;
- {
- if(fpin)
- fclose(fpin);
- if(fpout)
- fclose(fpout);
- printf("\n ** Fatal Error ** at line # %d\n",line_no);
- printf("%s",dbuff);
- printf("%s\n",s);
- printf("Assembly Terminated\n");
- exit(0);
- }
-
- sel_opt(s)
- char *s;
- {
- if(*s++ == '-') {
- switch(*s) {
- case 'l': list_on = 1;
- break;
- case 'z': fout_type = Z8;
- break;
- case 'm': fout_type = MOTOROLA;
- break;
- case 'i': fout_type = INTEL;
- break;
- case 's': sym_list = 1;
- break;
- default: errexit2("Invalid assembler option");
- break;
- }
- }
- }
-
-
- syntax_error()
- {
- errexit2("Syntax Error .. Unable to evaluate..");
- }
-
- strupr_esc(buff)
- char *buff;
- {
- while(*buff) {
- if(*buff == '\'') {
- buff++;
- while(*buff){
- if(*buff == '\'')
- break;
- else
- buff++;
- }
- }
- if(*buff) {
- *buff = toupper(*buff); *buff++; }
- }
- }
-
-
- /* primary line evaluator */
-
- evaluate()
- {
- int status;
-
- if(!(status = get_token(args[0]))) { /* get a word */
- gen_line();
- return(0); } /* comment -or- blank line */
-
- if(checklabel(args[0],status)) { /* create a symbol if required */
- if(pass == 1) {
- create_symbol(args[0],pc);
- strcpy(cur_sym,args[0]);
- }
- if(!(status = get_token(args[0]))) { /* get a word */
- gen_line();
- return(0); } /* comment -or- blank line */
- }
-
- /* check_defs here would allow user to create own instruction mne's */
- /* check_defs(args[0]); */
-
- syntax_index = scankey(args[0]); /* lookup mneumonic keyword */
-
- if(syntax_index) {
- get_token(args[1]); get_token(args[2]);
- check_defs(args[1]); check_defs(args[2]); /* check for subs. */
- switch(z8[syntax_index].opr_type) {
- case DEST_SOURCE:
- if(create_ds())
- gen_line();
- else
- syntax_error();
- break;
- case DEST_ONLY:
- if(create_d())
- gen_line();
- else
- syntax_error();
- break;
- case IMPLIED:
- if(create_i())
- gen_line();
- else
- syntax_error();
- break;
- case CREATE_JR:
- if(create_jr())
- gen_line();
- else
- syntax_error();
- break;
- case CREATE_DJ:
- if(create_dj())
- gen_line();
- else
- syntax_error();
- break;
- case CREATE_JP:
- if(create_jp())
- gen_line();
- else
- syntax_error();
- break;
- }
- }
- else /* scan for pseudo op */
- if((syntax_index = scan_pse(args[0])))
- eval_pse(syntax_index);
- else {
- printf("Syntax error, %s is not a valid opcode or pseudo op\n",args[0]);
- errexit2("** syntax **");
- }
- }
-
- /* check for define substitutions, if found replace string */
-
- check_defs(s)
- char *s;
- {
- struct def *dp;
-
- if(*s) {
- if(!(dp = lookup_def(s)))
- return(0);
- else
- if(special_def) {
- strcpy(s,dp->substitute);
- strcat(s,args[5]);
- }
- else
- strcpy(s,dp->substitute);
- }
- }
-
-
-
- /* evaluate a pseudo op */
-
- eval_pse(ps_num)
- int ps_num;
- {
- int equ_val,do_gen;
- struct symbol *sp;
-
- pcinc = 0;do_gen = 1;
-
- switch(ps_num) {
- case 1: /* org */
- get_token(args[1]);
- pc = eval(args[1]);
- if(pass == 2) {
- switch(fout_type) {
- case Z8:
- fprintf(fpout,"%%%x\n",pc);
- break;
- case MOTOROLA:
- flush_m();
- bin_pc = pc;
- break;
- case INTEL:
- flush_i();
- bin_pc = pc;
- break;
- }
- }
- break;
- case 2: /* db */
- get_db();
- do_gen = 0;
- break;
- case 3: /* dw */
- get_dw();
- do_gen = 0;
- break;
- case 4: /* ds */
- get_token(args[1]);
- gen_line();
- do_gen = 0;
- pc+= eval(args[1]);
- break;
- case 5: /* equ */
- if(pass == 1) { /* only do this on pass #1... */
- get_token(args[1]);
- equ_val = eval(args[1]);
- if((sp = lookup(cur_sym)))
- sp->value = equ_val;
- else
- printf("can't find symbol for equate \n");
- }
- break;
- case 6: /* def */
- if(pass == 1) {
- get_token(args[1]); get_token(args[2]);
- create_def(args[1],args[2]);
- }
- break;
- }
- if(do_gen)
- gen_line();
- }
-
- /* generate listing on pass #2 */
-
- gen_line()
- {
- int j;
- if (pass == 2 && list_on) {
- printf("%04x ",pc);
- for(j=0;j<code_line_index;j++)
- printf("%02x ",code_line[j]);
- if(listdb)
- otext(dbuff,pcinc);
- else
- printf("\n");
- }
- pc+= pcinc;
- }
-
- otext(buff,num)
- char *buff;
- int num;
- {
- switch(num) {
- case 0: printf(" %s",buff);
- break;
- case 1: printf(" %s",buff);
- break;
- case 2: printf(" %s",buff);
- break;
- case 3: printf(" %s",buff);
- }
- }
-
- /* create a dest,source type code */
-
- create_ds()
- {
- int stat,j;
-
- if(is_in(args[1],'(') || is_in(args[2],'(')) {
- create_idx();
- return(1);
- }
-
- stat = get_any(args[1]);
- if(stat) {
- arg1_val = arg_val; arg1_type = arg_type;
- arg1_subclass = arg_subclass;
- }
- else {
- printf("Eval 1 failed\n");
- return(0);
- }
- stat = get_any(args[2]);
- if(stat) {
- arg2_val = arg_val; arg2_type = arg_type;
- arg2_subclass = arg_subclass;
- }
- else {
- printf("Eval 2 failed\n");
- return(0);
- }
- /* check for standard argument set */
-
- j = 0;
- while(z8[syntax_index].otab[j].dest) {
- if((arg1_type == z8[syntax_index].otab[j].dest) &&
- (arg2_type == z8[syntax_index].otab[j].source)) {
- build_code(z8[syntax_index].otab,j);
- return(1);
- }
- j++;
- }
-
- /* check extended argument set #2 */
- convert_arg2(); /* convert 4bit args to 8bit args */
- j = 0;
- while(z8[syntax_index].otab[j].dest) {
- if((arg1_type == z8[syntax_index].otab[j].dest) &&
- (arg2_type == z8[syntax_index].otab[j].source)) {
- build_code(z8[syntax_index].otab,j);
- return(1);
- }
- j++;
- }
-
- /* check extended argument set #1 */
- convert_arg1(); /* convert 4bit args to 8bit args */
- j = 0;
- while(z8[syntax_index].otab[j].dest) {
- if((arg1_type == z8[syntax_index].otab[j].dest) &&
- (arg2_type == z8[syntax_index].otab[j].source)) {
- build_code(z8[syntax_index].otab,j);
- return(1);
- }
- j++;
- }
-
- /* syntax format not available for this opcode */
-
- return(0);
- }
-
- /* convert 4bit arg to 8bit arg */
-
- convert_arg1()
- {
- switch(arg1_type) {
- case R4: arg1_type = R8;
- break;
- case IR4: arg1_type = IR8;
- break;
- case IRR4: arg1_type = IRR8;
- break;
- case RR4: arg1_type = RR8;
- break;
- }
- }
-
-
- /* convert 4bit arg to 8bit arg */
-
- convert_arg2()
- {
- switch(arg2_type) {
- case R4: arg2_type = R8;
- break;
- case IR4: arg2_type = IR8;
- break;
- case IRR4: arg2_type = IRR8;
- break;
- case RR4: arg2_type = RR8;
- break;
- }
- }
-
-
- /* create code for destination only type */
-
- create_d()
- {
- int stat,j;
- stat = get_any(args[1]);
- if(stat) {
- arg1_val = arg_val; arg1_type = arg_type;
- arg1_subclass = arg_subclass;
- }
- else {
- printf("Eval 1 failed\n");
- return(0);
- }
- j = 0;
- while(z8[syntax_index].otab[j].dest) {
- if((arg1_type == z8[syntax_index].otab[j].dest)) {
- build_code(z8[syntax_index].otab,j);
- return(1);
- }
- j++;
- }
-
- /* check extended argument set #1 */
-
- convert_arg1();
- j = 0;
- while(z8[syntax_index].otab[j].dest) {
- if((arg1_type == z8[syntax_index].otab[j].dest)) {
- build_code(z8[syntax_index].otab,j);
- return(1);
- }
- j++;
- }
- return(0);
- }
-
- /* create code for implied op */
- create_i()
- {
- build_code(z8[syntax_index].otab,0);
- return(1);
- }
-
-
- /* build actual code via table entry */
-
- build_code(optab,j)
- struct optable optab[];
- int j;
- {
- pcinc = optab[j].numbytes;
- switch(optab[j].numbytes) {
- case 1: switch(optab[j].opr1) {
- case OPCODE_OR_DESTSL4:
- generate((arg1_val<<4) | optab[j].opcode);
- break;
- default:
- generate(optab[j].opcode);
- break;
- }
- break;
- case 2: switch(optab[j].opr1) {
- case DESTSL4_OR_SOURCE:
- generate(optab[j].opcode);
- generate((arg1_val<<4) | arg2_val);
- break;
- case ZDEST:
- generate(optab[j].opcode);
- if(arg1_subclass == WORKING)
- generate(0xe0 | arg1_val);
- else
- generate(arg1_val);
- break;
- case OPCODE_OR_SOURCESL4:
- generate((arg2_val << 4) | optab[j].opcode);
- generate(arg1_val);
- break;
- case OPCODE_OR_DESTSL4:
- generate((arg1_val<<4) | optab[j].opcode);
- if(arg2_subclass == WORKING)
- generate(0xe0 | arg2_val);
- else
- generate(arg2_val);
- break;
- case SOURCESL4_OR_DEST:
- generate(optab[j].opcode);
- generate((arg2_val<<4) | arg1_val);
- break;
- }
- break;
- case 3: generate(optab[j].opcode);
- switch(optab[j].opr1) {
- case ZSOURCE:
- if(arg2_subclass == WORKING)
- generate(0xe0 | arg2_val);
- else
- generate(arg2_val);
- break;
- case ZDEST:
- if(arg1_subclass == WORKING)
- generate(0xe0 | arg1_val);
- else {
- if(optab[j].dest == DA) { /* 16 bit addr */
- generate(arg1_val >> 8); /* hi byte */
- generate(arg1_val & 0xff); /* lo byte */
- }
- else
- generate(arg1_val);
- }
- break;
- }
- if(optab[j].opr2) {
- switch(optab[j].opr2) {
- case ZSOURCE:
- if(arg2_subclass == WORKING)
- generate(0xe0 | arg2_val);
- else
- generate(arg2_val);
- break;
- case ZDEST:
- if(arg1_subclass == WORKING)
- generate(0xe0 | arg1_val);
- else
- generate(arg1_val);
- break;
- }
- }
- break;
-
- }
- }
-
- /* a hack for indexed mode addressing */
-
- create_idx()
- {
- int ix_op,src,rindex,dest;
- char *temp;
-
- if(pass == 1) {
- pcinc = 3; /* assume all ok for pass #1 */
- return(1);
- }
-
- pcinc = 3;
- if(is_in(args[1],'(')) {
- ix_op = 0xd7; /* dest is indexed */
- temp = args[1];
- while((*temp++ != '(')); /* get pointer to index register */
- get_any(args[1]); /* get base register, must be r8 */
- if(arg_type != R8)
- errexit2("dest INDEX Base not absolute");
- else
- dest = arg_val;
-
- get_any(temp); /* get index register */
- if(arg_type != R4)
- errexit2("dest INDEX must be working reg.");
- else
- rindex = arg_val;
-
- get_any(args[2]);
- if(arg_type != R4)
- errexit2("source must be working reg.");
- else
- src = arg_val;
-
- generate(ix_op);
- generate((src << 4) | rindex);
- generate(dest);
- return(1);
- }
- else {
- if(is_in(args[2],'('))
- ix_op = 0xc7; /* dest is r4 */
- else
- errexit2("Invalid index mode!");
- temp = args[2];
- while((*temp++ != '(')); /* get pointer to index register */
- get_any(args[1]); /* get dest register, must be r4 */
- if(arg_type != R4)
- errexit2("dest must be working reg.");
- else
- dest = arg_val;
- get_any(args[2]); /* get base register, must be r8 */
- if(arg_type != R8)
- errexit2("source INDEX Base not absolute");
- else
- src = arg_val;
- get_any(temp); /* get index register */
- if(arg_type != R4)
- errexit2("source INDEX must be working reg.");
- else
- rindex = arg_val;
- generate(ix_op);
- generate((dest << 4) | rindex);
- generate(src);
- return(1);
- }
- }
-
- is_in(s,c)
- char *s;
- char c;
- {
- while(*s) {
- if(*s == c)
- return(1);
- s++;
- }
- return(0);
- }
-
-
-
- create_jr()
- {
- int cc_code,cc_disp,cc_op;
- int cc_addr;
-
- if(pass == 1) { /* assume everything ok */
- pcinc = 2;
- return(1);
- }
-
- cc_op = 0x0b;
-
- if(isnull(args[2])) {
- cc_code = 0x80;
- cc_addr = eval(args[1]); /* will bomb if can't evaluate */
- }
- else {
- cc_addr = eval(args[2]);
- if(!(cc_code = find_cc_code(args[1])))
- errexit2("Condition code invalid!!");
- }
-
- cc_disp = compute_relative(cc_addr,pc);
- if((cc_disp > 127) | (cc_disp < -128))
- errexit2("Relative branch out of range!!");
-
- pcinc = 2;
- generate(cc_op | cc_code);
- generate(cc_disp & 0xff);
- return(1);
- }
-
- /* create jp cc,dest */
- create_jp()
- {
- int cc_code,cc_op;
- int cc_addr;
-
- if(pass == 1) { /* assume everything ok */
- get_any(args[1]);
- if(arg_type == IR4 || arg_type == IR8)
- pcinc = 2;
- else
- pcinc = 3;
- return(1);
- }
-
-
- if(isnull(args[2])) {
- get_any(args[1]);
- if(arg_type == IR4) {
- cc_op = 0x30;
- cc_addr = 0xe0 | arg_val;
- generate(cc_op);
- generate(cc_addr);
- pcinc = 2;
- return(1);
- }
- else
- if(arg_type == IR8) {
- cc_op = 0x30;
- generate(cc_op);
- generate(arg_val);
- pcinc = 2;
- return(1);
- }
- else
- cc_code = 0x80;
- cc_addr = eval(args[1]); /* will bomb if can't evaluate */
- }
- else {
- cc_addr = eval(args[2]);
- if(!(cc_code = find_cc_code(args[1])))
- errexit2("Condition code invalid!!");
- }
-
- pcinc = 3;
- cc_op = 0x0d;
- generate(cc_op | cc_code);
- generate(cc_addr >> 8);
- generate(cc_addr & 0xff);
- return(1);
- }
-
-
- /* create djnz code */
-
- create_dj()
- {
- int dj_disp,dj_op;
- int dj_addr;
-
- if(pass == 1) { /* assume everything ok */
- pcinc = 2;
- return(1);
- }
-
- dj_op = 0x0a;
-
- if(!(get_any(args[1])))
- errexit2("Syntax error");
-
- if(arg_type != R4)
- errexit2("Invalid reg. spec");
-
- dj_addr = eval(args[2]);
-
- dj_disp = compute_relative(dj_addr,pc);
- if((dj_disp > 127) | (dj_disp < -128))
- errexit2("Relative branch out of range!!");
-
- pcinc = 2;
- generate((arg_val << 4) | dj_op);
- generate(dj_disp & 0xff);
- return(1);
- }
-
- find_cc_code(code)
- char *code;
- {
- int j,cond;
-
- for(j = 0; j < CCSIZE;j++) {
- if((cond = stricmp(code,cc[j].mne)) == 0)
- return(cc[j].cc_value);
- }
- return(0);
- }
-
-
-
- compute_relative(dest,apc)
- int dest;
- int apc;
- {
- apc += 2;
- return(dest - apc);
- }
-
-
- isnull(s)
- char *s;
- {
- if(*s)
- return(0);
- else
- return(1);
- }
-
- generate(val)
- int val;
- {
- code_line[code_line_index] = val;
- code_line_index++;
- if(pass == 2) {
- switch(fout_type) {
- case Z8: fprintf(fpout,"%%%02x\n",val);
- break;
- case MOTOROLA: mout(val);
- break;
- case INTEL: iout(val);
- break;
- }
- }
- bytes_generated++;
- }
-
- iout(val)
- int val;
- {
- bin_line[bindex++] = val;
- if(bindex == 32)
- flush_i();
- }
-
- mout(val)
- int val;
- {
- bin_line[bindex++] = val;
- if(bindex == 32)
- flush_m();
- }
-
- flush_m()
- {
- int j;
-
- if(bindex) {
- fprintf(fpout,"S1");
- hexout(bindex+3);
- checksum += bindex+3;
- hexout(bin_pc >> 8);
- hexout(bin_pc & 0xff);
- checksum += (bin_pc>>8);
- checksum += (bin_pc & 0xff);
- bin_pc += bindex;
- for(j = 0; j < bindex; j++) {
- hexout(bin_line[j]);
- checksum += bin_line[j];
- }
- hexout(~checksum);
- fprintf(fpout,"\n");
- bindex = 0; checksum = 0;
- }
- }
-
- flush_i()
- {
- int j;
-
- if(bindex) {
- fprintf(fpout,":");
- hexout(bindex);
- checksum += bindex;
- hexout(bin_pc >> 8);
- hexout(bin_pc & 0xff);
- checksum += (bin_pc>>8);
- checksum += (bin_pc & 0xff);
- hexout(0);
- checksum += 0;
- bin_pc += bindex;
- for(j = 0; j < bindex; j++) {
- hexout(bin_line[j]);
- checksum += bin_line[j];
- }
- hexout(~checksum+1);
- fprintf(fpout,"\n");
- bindex = 0; checksum = 0;
- }
- }
-
- end_m()
- {
- flush_m();
- fprintf(fpout,"S9030000FC\n");
- }
-
- end_i()
- {
- flush_i();
- fprintf(fpout,":00000001FF\n");
- }
-
- char *hexstr = { "0123456789ABCDEF" } ;
-
- hexout(byte)
- int byte;
- {
-
- byte = byte & 0xff;
- fprintf(fpout,"%c%c",hexstr[byte>>4],hexstr[byte&017]);
- }
-
-
- get_any(st)
- char *st;
- {
- int tempn1;
-
- arg_subclass = 0;
-
- if(strnicmp(st,"@RR",3)== 0) { /* indirect register pair */
- if(st[3] == ':') {
- tempn1 = eval(&st[4]);
- if((tempn1 >= 0) && (tempn1 < 256)) {
- arg_val = tempn1; arg_type = IRR8;
- return(1);
- }
- }
- else {
- tempn1 = eval(&st[3]);
- if((tempn1 >= 0) && (tempn1 < 16)) {
- arg_val = tempn1; arg_type = IRR4;
- arg_subclass = WORKING;
- return(1);
- }
- else
- return(0);
- }
- }
-
- if(strnicmp(st,"RR",2)== 0) { /* register pair */
- if(st[2] == ':') {
- tempn1 = eval(&st[3]);
- if((tempn1 >= 0) && (tempn1 < 256)) {
- arg_val = tempn1; arg_type = RR8;
- return(1);
- }
- }
- else {
- tempn1 = eval(&st[2]);
- if((tempn1 >= 0) && (tempn1 < 16)) {
- arg_val = tempn1; arg_type = RR4;
- arg_subclass = WORKING;
- return(1);
- }
- else
- return(0);
- }
- }
-
-
- if(strnicmp(st,"@R",2)== 0) { /* indirect reg specifier */
- if(st[2] == ':') {
- tempn1 = eval(&st[3]);
- if((tempn1 >= 0) && (tempn1 < 256)) {
- arg_val = tempn1; arg_type = IR8;
- return(1);
- }
- }
- else {
- tempn1 = eval(&st[2]);
- if((tempn1 >= 0) && (tempn1 < 16)) {
- arg_val = tempn1; arg_type = IR4;
- arg_subclass = WORKING;
- return(1);
- }
- else
- return(0);
- }
- }
-
- if((st[0] == 'R') || st[0] == ('r')) {
- if(st[1] == ':') {
- tempn1 = eval(&st[2]);
- if((tempn1 >= 0) && (tempn1 < 256)) {
- arg_val = tempn1; arg_type = R8;
- return(1);
- }
- }
- else {
- tempn1 = eval(&st[1]);
- if((tempn1 >= 0) && (tempn1 < 16)) {
- arg_val = tempn1; arg_type = R4;
- arg_subclass = WORKING;
- return(1);
- }
- else
- return(0);
- }
- }
-
- if(st[0] == '#') {
- tempn1 = eval(&st[1]);
- if((tempn1 >= 0) && (tempn1 < 256)) {
- arg_val = tempn1; arg_type = IM8;
- return(1);
- }
- else
- return(0);
- }
- if(st[0]) {
- tempn1 = eval(&st[0]);
- if((tempn1 >= 0) && (tempn1 < 65536)) {
- arg_val = tempn1; arg_type = DA;
- return(1);
- }
- else
- return(0);
- }
-
-
- return(0);
- }
-
-
- /* scans a passed string for keyword and return index */
-
- scankey(word)
- char *word;
- {
- int j,cond;
-
- for(j = 1; j < Z8SIZE; j++) {
- if((cond = stricmp(word,z8[j].mne)) == 0) {
- return(j);
- }
- }
- return(0);
- }
-
-
- /* scans a passed string for pseudo-op keyword and return index */
-
- scan_pse(word)
- char *word;
- {
- int j,cond;
-
- for(j = 1; j < PSSIZE; j++) {
- if((cond = stricmp(word,ps[j].mne)) == 0) {
- return(j);
- }
- }
- return(0);
- }
-
- checklabel(s,c)
- char *s;
- int c;
- {
- if(s[c-1] == ':') {
- s[c-1] = '\0';
- return(1);
- }
- else
- return(0);
- }
- /* process define word */
-
- get_dw()
- {
- int result;
-
- while((get_token(args[1]))) {
- result = eval(args[1]);
- generate(result>>8);
- generate(result & 0xff);
- pcinc+=2;
- gen_line();
- pcinc = 0;code_line_index = 0;
- listdb = 0; /* turn off line listing */
- }
- listdb = 1; /* turn back on line listing */
- }
-
-
- /* process define byte */
-
- get_db()
- {
- char *c;
- int result;
-
- while((get_token1(args[1]))) {
- c = args[1];
- switch(*c) {
- case '\'': /* ascii text */
- c++;
- while((*c) && (*c != '\'')) {
- generate(*c);
- pcinc++;c++;
- if(pcinc == 3) {
- gen_line();
- pcinc = 0;code_line_index = 0;
- listdb = 0;
- }
- }
- break;
- default: /* the rest */
- result = eval(args[1]);
- generate(result);pcinc++;
- if(pcinc == 3) {
- gen_line();
- pcinc = 0;code_line_index = 0;
- listdb = 0;
- }
- break;
- }
- }
- if(pcinc) {
- gen_line();
- pcinc = 0;code_line_index = 0;
- }
- listdb = 1;
- }
-
-
- /* extract a token from current line and copy into 's'.
- s = null string if no token is available. returns status:
- status = 0 = no token extracted ,otherwise status =
- number of characters in the token. */
-
- get_token(s)
- char *s;
- {
- int st;
-
- st = 0;
- while(isany(*curline," ,\11\12\0")) /* skip any special chars */
- curline++;
-
- while(*curline) {
- if(isany(*curline," ,\11\12\0")) {
- *s = '\0';
- break;
- }
- else {
- if(*curline == ';') /* handle comment here */
- break;
- *s++ = *curline++; st++;
- }
- }
- *s = '\0';
- return(st);
- }
-
- get_token1(s)
- char *s;
- {
- int st;
-
- st = 0;
- while(isany(*curline," ,\11\12\0")) /* skip any special chars */
- curline++;
-
- if(*curline == '\'') { /* start of ascii text */
- *s++ = *curline++; st++; }
-
- while(*curline) {
- if(isany(*curline,",\11\12\0")) {
- *s = '\0';
- break;
- }
- else {
- if(*curline == ';') /* handle comment here */
- break;
- *s++ = *curline++; st++;
- }
- }
- *s = '\0';
- return(st);
- }
-
-
- isany(c,s)
- char c;
- char *s;
- {
- while(*s) {
- if(*s == c)
- return(1);
- s++;
- }
- return(0);
- }
-
- /* base routines for symbol table manipulation */
-
- unsigned int hash(s)
- char *s;
- {
- unsigned hashval;
-
- for(hashval = 0; *s != '\0'; *s++)
- hashval = *s + 31 * hashval;
- return(hashval % HASHSIZE);
- }
-
- /* lookup-- look for 's' in symbol table. returns pointer to symbol
- structure -or- NULL if no match found */
-
- struct symbol *lookup(s)
- char *s;
- {
- struct symbol *sp;
-
- for(sp = hashtab[hash(s)]; sp != NULL; sp = sp->next)
- if(strcmp(s,sp->label) == 0)
- return(sp);
- return(NULL);
- }
-
- struct symbol *special_lookup(s)
- char *s;
- {
- char *s1;
- struct symbol *sp;
-
- s1 = args[4]; /* safe temp storage area */
-
- while(*s && (!(isany(*s,"!+-*/|&"))))
- *s1++ = *s++; /* copy string */
- *s1 = '\0';
- sp = lookup(args[4]);
- return(sp);
- }
-
-
-
- struct def *lookup_def(s)
- char *s;
- {
- struct def *dp;
- char *s1;
-
- special_def = 0;
- s1=args[4];
- if(strpbrk(s,"!+-*/|&(")) {
- /* printf("Special lookup of '%s'\n",s); */
- while(*s && (!(isany(*s,"!+-*/|&("))))
- *s1++ = *s++; /* copy string */
- *s1 = '\0';
- strcpy(args[5],s); /* save remainder of arg */
- /* printf("Alternate lookup of '%s'\n",args[4]); */
- dp = lookup_def1(args[4]);
- if(dp)
- special_def = 1; /* flag caller */
- /* printf("Found '%s'\n",args[4]); */
- return(dp);
- }
- else {
- dp = lookup_def1(s);
- /* printf("s = %s\n",s); */
- return(dp);
- }
- }
-
- struct def *lookup_def1(s)
- char *s;
- {
- struct def *dp;
-
- for(dp = deftab[hash(s)]; dp != NULL; dp = dp->next)
- if(strcmp(s,dp->label) == 0)
- return(dp);
- return(NULL);
- }
-
- /* create symbol--- install a symbol into table */
-
- create_symbol(name,value)
- char *name;
- int value;
- {
- struct symbol *sp;
- unsigned int hashval;
-
- if((sp = lookup(name)) == NULL) { /* not found */
- sp = (struct symbol *) malloc(sizeof(*sp));
- if(sp == NULL || (sp->label = (char *)strdup(name)) == NULL)
- errexit2("Unable to allocte symbol table mem.");
- sp->value = value;
- hashval = hash(name);
- sp->next = hashtab[hashval];
- hashtab[hashval] = sp;
- nsyms++;
- }
- else {
- errexit2("Duplicate define");
- }
- return(1);
- }
-
- create_def(name,value)
- char *name;
- char *value;
- {
- struct def *dp;
- unsigned int hashval;
-
- if((dp = lookup_def(name)) == NULL) { /* not found */
- dp = (struct def *) malloc(sizeof(*dp));
- if(dp == NULL || (dp->label = (char *)strdup(name)) == NULL)
- errexit2("Unable to alloc symbol table mem.");
- if((dp->substitute = (char *)strdup(value)) == NULL)
- errexit2("Unable to alloc symbol table mem.");
- hashval = hash(name);
- dp->next = deftab[hashval];
- deftab[hashval] = dp;
- }
- else {
- errexit2("Duplicate def");
- }
- return(1);
- }
-
- list_symbols()
- {
- int j,n;
- struct symbol *sp;
-
- if(!nsyms || !sym_list)
- return(0);
- if(!(spoint = (struct symbol**) malloc(sizeof(*spoint) * nsyms))) {
- printf("Not enough memory for sorted symbol table\n");
- return(0);
- }
- /* make list of all pointers to symbol entrys */
-
- for(j=0,n=0; j < HASHSIZE;j++) {
- if(hashtab[j]) {
- for(sp = hashtab[j]; sp != NULL; sp = sp->next) {
- spoint[n++] = sp;
- }
- }
- }
- /* sort list */
-
- qsort(spoint,nsyms,sizeof(char *),sym_cmp);
- printf("\n\nSymbol Table:\n\n");
-
- /* print list */
-
- for(j=0; j < nsyms;j++) {
- sp = spoint[j];
- printf(" %04X -- %s\n",sp->value,sp->label);
- }
- }
-
- sym_cmp(a1,b1)
- struct symbol *a1[],*b1[];
-
- {
- struct symbol *a,*b;
- a = (struct symbol *) a1[0];
- b = (struct symbol *) b1[0];
- return(strnicmp(a->label,b->label,14));
- }
-
- /* Main expression evaluation.
- gets the next value from parse_line buffer.
- ends up pointing to next math operator or null
- */
-
- get_exp_val()
- {
- struct symbol *sp;
- int ret_val;
-
-
- /* while((isany(*parse_line," ")))
- parse_line++;
- */
- if((isalpha(*parse_line))) { /* better be a label!!! */
- sp = special_lookup(parse_line);
- if(!sp) {
- if(pass == 2)
- errexit2("Undefined Label");
- else {
- scan_to_next_math_op();
- return(0);
- }
- }
- else {
- scan_to_next_op();
- if(parse_line) {
- if (*parse_line == '!') { /* handle address operator */
- parse_line++;
- if(*parse_line == 'H' || *parse_line == 'h') {
- scan_to_next_op();
- return(sp->value >> 8); }
- else
- if(*parse_line == 'L'|| *parse_line == 'l') {
- scan_to_next_op();
- return(sp->value & 0xff); }
- else
- errexit2("Invalid address operator");
- } else return(sp->value);
- } else return(sp->value);
- }
- }
- /* if we made it here we better have a constant */
-
- if(!(isany(*parse_line,"%$'0123456789")))
- errexit2("Invalid constant");
- else {
- ret_val = getval(parse_line);
- scan_to_next_op();
- return(ret_val);
- }
- }
-
- scan_to_next_op()
- {
- while(!(isany(*parse_line,"+-*/!|&"))) {
- if(*parse_line && *parse_line != ';')
- parse_line++;
- else {
- parse_line = NULL;
- return(0);
- }
- }
- }
-
- scan_to_next_math_op()
- {
- while(!(isany(*parse_line,"+-*/|&"))) {
- if(*parse_line && *parse_line != ';')
- parse_line++;
- else {
- parse_line = NULL;
- return(0);
- }
- }
- }
-
-
- eval(curline) /* evaluate expression */
- char *curline;
- {
- int left,right,operator;
- left = 0;
-
- parse_line = curline;
-
- left = get_exp_val(); /* get leftmost operand */
-
- while(parse_line) { /* get operator and next expression */
- operator = *parse_line++;
- right = get_exp_val();
- switch (operator) {
- case '+': left = left + right;
- break;
- case '-': left = left - right;
- break;
- case '*': left = left * right;
- break;
- case '/': if(right > 0)
- left = left / right;
- break;
- case '|': left = left | right;
- break;
- case '&': left = left & right;
- break;
- }
- }
- return(left);
- }
-
- /* char digit connversion routines */
-
- cvdig(ch) /* return value of digit or -1 */
- char ch;
- {
- int z;
- if((z = ch) >= '0' && z <= '9') z -= '0';
- else
- if((z &= 0137) >= 'A' && z <= 'F') z -= 'A' - 10;
- else
- return (-1);
- if(z < radix)
- return(z);
-
- return (-1);
- }
-
- /* get numeric value from string, expects first char of string to
- be the radix specifier. % = binary, $ = hex, @ = octal '0..9' = decimal.
- returns converted value..
- */
-
- getval(curline)
- char *curline;
- {
- int j,n,k;
-
- switch(*curline)
- { case '$': radix = 16; curline++; break;
- case '%': radix = 2; curline++; break;
- case '\'': radix = 255; curline++; break;
- default: radix = 10;
- }
-
- j = 0;k = 0;
- if(radix < 255) {
- while(*curline) {
- if((n = cvdig(*curline++)) < 0){
- curline--;
- break;}
- j = j * radix + n;
- k++;
- }
- }
- else {
- j = *curline++;
- curline++;
- }
- return(j);
- }
-