⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 picasm.c

📁 MicroChip的12BIt和14Bit的PIC系列单片机的汇编器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * picasm.c * * Freely distributable for non-commercial use (basically, * don't sell this program without my permission. You can * use it for developing commercial PIC applications, but * of course I am not responsible for any damages caused by * this assembler generating bad code or anything like that) * * Copyright 1995-1998 by Timo Rossi * See the file picasm.doc for more information *  *   email: trossi@iki.fi *   www: http://www.iki.fi/trossi/pic/ * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <ctype.h>#include <time.h>#include "picasm.h"int warnlevel;static int total_line_count;static int errors, warnings; /* error & warning counts */unsigned short list_flags;/* imported from devices.c */extern struct pic_type pic_types[];static FILE *list_fp;static int listing_on;static int list_loc;static pic_instr_t *list_ptr;static long list_val, list_len;int cond_nest_count;int unique_id_count;/* the current source file/macro */struct inc_file *current_file;/* Line buffer & pointer to it */char *line_buf_ptr;char line_buffer[256];static struct patch *global_patch_list;struct patch **local_patch_list_ptr;struct pic_type *pic_type;int prog_mem_size;static int reg_file_limit;short code_generated;static pic_instr_t prog_mem[PROGMEM_MAX];static pic_instr_t data_eeprom[EEPROM_MAX];static pic_instr_t pic_id[4];pic_instr_t config_fuses;org_mode_t O_Mode;int prog_location;         /* current address for program code */int reg_location;   /* current address for register file */int edata_location; /* current address for data EEPROM */int org_val;int local_level;/* Error handling *//* * Show line number/line with error message */static voiderr_line_ref(void){  struct inc_file *inc;  if(current_file != NULL) {    inc = current_file;    if(inc->type != INC_FILE) {      fprintf(stderr, "(Macro %s line %d) ",	      inc->v.m.sym->name, inc->linenum);      while(inc != NULL && inc->type != INC_FILE)	inc = inc->next;    }    fprintf(stderr, "File '%s' at line %d:\n",	    inc->v.f.fname, inc->linenum);    fputs(line_buffer, stderr);    if(line_buffer[0] != '\0' && line_buffer[strlen(line_buffer)-1] != '\n')      fputc('\n', stderr);  }}/* * Warning message */voidwarning(char *fmt, ...){  va_list args;  err_line_ref();  fputs("Warning: ", stderr);  va_start(args, fmt);  vfprintf(stderr, fmt, args);  if(list_fp != NULL) {    fputs("Warning: ", list_fp);    vfprintf(list_fp, fmt, args);    fputc('\n', list_fp);  }  fputc('\n', stderr);  va_end(args);  warnings++;}/* * skip the end of line, in case of an error */static voiderror_lineskip(void){  write_listing_line(0);  skip_eol();  get_token();}/* * Error message * call error_lineskip() if lskip is non-zero * */voiderror(int lskip, char *fmt, ...){  va_list args;  err_line_ref();  fputs("Error: ", stderr);  va_start(args, fmt);  vfprintf(stderr, fmt, args);  if(list_fp != NULL) {    fputs("Error: ", list_fp);    vfprintf(list_fp, fmt, args);    fputc('\n', list_fp);  }  fputc('\n', stderr);  va_end(args);  if(++errors >= MAX_ERRORS)    fatal_error("too many errors, aborting");	  if(lskip)    error_lineskip();}/* * Fatal error message */voidfatal_error(char *fmt, ...){  va_list args;  err_line_ref();  fputs("Fatal error: ", stderr);  va_start(args, fmt);  vfprintf(stderr, fmt, args);  fputc('\n', stderr);  va_end(args);  exit(EXIT_FAILURE);}/* memory allocation */void *mem_alloc(int size){  void *p;  if((p = malloc(size)) == NULL)    fatal_error("Out of memory");  return p;}/* * initialize the assembler */static voidinit_assembler(void){  pic_instr_t *cp;  int n;  init_symtab(); /* initialize symbol table */  /* initialize program memory to invalid values */  for(n = PROGMEM_MAX, cp = prog_mem; n-- > 0; *cp++ = INVALID_INSTR);  /* initialize data memory to invalid values */  for(n = EEPROM_MAX, cp = data_eeprom; n-- > 0; *cp++ = INVALID_DATA);  /* initialize jump  patch list */  global_patch_list = NULL;  prog_location = -1;  reg_location = -1;  edata_location = -1;  org_val = -1;  current_file = NULL;  config_fuses = INVALID_CONFIG;  pic_id[0] = INVALID_ID;  errors = warnings = 0;  list_flags = 0;  list_len = 0;  listing_on = 1;  cond_nest_count = 0;  unique_id_count = 1;  total_line_count = 0;  code_generated = 0;  local_level = 0;  ifskip_mode = 0;}/* * generate program code */void gen_code(int val){  if(pic_type == NULL)    fatal_error("PIC device type not set");  if(O_Mode == O_NONE) {    O_Mode = O_PROGRAM;    if(org_val < 0) {      error(0, "ORG value not set");      prog_location = 0;      return;    }    prog_location = org_val;  } else if(O_Mode != O_PROGRAM) {    error(0, "ORG mode conflict");    O_Mode = O_PROGRAM;    return;  }  if(prog_location >= prog_mem_size)    fatal_error("Code address out of range");  if(prog_mem[prog_location] != INVALID_INSTR)    warning("Overlapping code at 0x%x\n", prog_location);  if((list_flags & LIST_PROG) == 0) {    list_loc = prog_location;    list_flags = LIST_LOC | LIST_PROG;  }  list_len++;  prog_mem[prog_location++] = val;  code_generated = 1;}/* * Generate data for data EEPROM */voidgen_edata(int val){  if(O_Mode == O_NONE) {    O_Mode = O_EDATA;    if(org_val < 0) {      error(0, "ORG value not set");      edata_location = 0;      return;    }    edata_location = org_val;  } else if(O_Mode != O_EDATA) {    error(0, "ORG mode conflict");    O_Mode = O_EDATA;    return;  }  if(edata_location >= pic_type->eeprom_size)    fatal_error("Data EEPROM address out of range");  if(data_eeprom[edata_location] < 0x100)    warning("Overlapping EEPROM data at 0x%x\n", edata_location);  if((list_flags & LIST_LOC) == 0) {    list_loc = edata_location;    list_flags = LIST_LOC | LIST_EDATA;  }  list_len++;  data_eeprom[edata_location++] = val;  code_generated = 1;}/* * Write one line of Intel-hex file */static voidwrite_hex_record(FILE *fp,			   int reclen, /* length (in words) */			   int loc, /* address */			   pic_instr_t *data, /* pointer to word data */			   int format) /* IHX8M or IHX16 */{  int check = 0;  switch(format) {    case IHX8M:      fprintf(fp, ":%02X%04X00", 2*reclen, 2*loc);      check += ((2*loc) & 0xff) + (((2*loc) >> 8) & 0xff) + 2*reclen;      break;    case IHX16:      fprintf(fp, ":%02X%04X00", reclen, loc);      check += (loc & 0xff) + ((loc >> 8) & 0xff) + reclen;      break;  }  while(reclen--) {    switch(format) {      case IHX8M:        fprintf(fp, "%02X%02X",		(int)(*data & 0xff), (int)((*data >> 8) & 0xff));	break;      case IHX16:	fprintf(fp, "%02X%02X",		(int)((*data >> 8) & 0xff), (int)(*data & 0xff));	break;    }    check += (*data & 0xff) + ((*data >> 8) & 0xff);    data++;  }  /* write checksum, assumes 2-complement */  fprintf(fp, "%02X" HEX_EOL, (-check) & 0xff);}/* * Write output file in ihx8m or ihx16-format * */static voidwrite_output(char *fname, int format){  int loc, reclen;  FILE *fp;  if((fp = fopen(fname, "w")) == NULL)    fatal_error("Can't create file '%s'", fname);  /* program */  for(loc = 0;;) {    while(loc < prog_mem_size && prog_mem[loc] == INVALID_INSTR)      loc++;    if(loc >= prog_mem_size)      break;          reclen = 0;    while(reclen < 8 && loc < prog_mem_size	  && prog_mem[loc] != INVALID_INSTR) {      loc++;      reclen++;    }    write_hex_record(fp, reclen, loc-reclen, &prog_mem[loc-reclen], format);  }  /* PIC ID */  if(pic_id[0] != INVALID_ID) {    switch(pic_type->instr_set) {      case PIC12BIT:        write_hex_record(fp, 4, prog_mem_size, pic_id, format);	break;      case PIC14BIT:	write_hex_record(fp, 4, 0x2000, pic_id, format);	break;    }  }  /* config fuses */  if(config_fuses != INVALID_CONFIG) {    write_hex_record(fp, 1, pic_type->fuse_addr, &config_fuses, format);  }  if(pic_type->eeprom_size > 0) { /* data EEPROM */    for(loc = 0;;) {      while(loc < pic_type->eeprom_size && data_eeprom[loc] >= 0x100)	loc++;              if(loc >= pic_type->eeprom_size)	break;              reclen = 0;      while(reclen < 8 && loc < pic_type->eeprom_size	    && data_eeprom[loc] < 0x100) {	loc++;	reclen++;      }      write_hex_record(fp, reclen, 0x2100+loc-reclen,		       &data_eeprom[loc-reclen], format);    }  }  fputs(":00000001FF" HEX_EOL , fp); /* end record */  fclose(fp);}/* * Write one line to listing file (if listing is enabled) */voidwrite_listing_line(int cond_flag){  int i;  if(list_fp != NULL && listing_on) {    fprintf(list_fp, "%04d%c%c",	    ++total_line_count,	    (current_file != NULL && current_file->type == INC_MACRO ?	     '+' : ' '),	    (cond_flag ? '!' : ' '));    if(line_buffer[0] != '\0') {      if(list_flags & LIST_VAL)	{	fprintf(list_fp, "%08lX  ", list_val);      } else {	if(list_flags & LIST_LOC)	  fprintf(list_fp, "%04X", list_loc);	else	  fputs("    ", list_fp);	if((list_flags & (LIST_PROG|LIST_EDATA|LIST_PTR)) != 0) {	  fputc(((list_flags & LIST_FORWARD) ? '?' : ' '), list_fp);	  if(list_flags & LIST_PROG) {	    fprintf(list_fp, "%04X ", prog_mem[list_loc]);	  } else if(list_flags & LIST_EDATA) {	    fprintf(list_fp, "%04X ", data_eeprom[list_loc]);	  } else if(list_flags & LIST_PTR) {	    fprintf(list_fp, "%04X ", *list_ptr++);	  }	} else {	  fputs("      ", list_fp);	}      }      fputs(line_buffer, list_fp);      if(line_buffer[0] != '\0'	 && line_buffer[strlen(line_buffer)-1] != '\n')	fputc('\n', list_fp);      list_len--;      for(i = 0; i < list_len; i++) {	list_loc++;	fprintf(list_fp, "%04d%c ",		total_line_count,		(current_file != NULL		 && current_file->type == INC_MACRO ?		 '+' : ' '));	if(list_flags & LIST_LOC)	  fprintf(list_fp, "%04X", list_loc);	else	  fputs("    ", list_fp);	if(list_flags & LIST_PROG) {	  fprintf(list_fp, " %04X\n", prog_mem[list_loc]);	} else if(list_flags & LIST_EDATA) {	  fprintf(list_fp, " %04X\n", data_eeprom[list_loc]);	} else if(list_flags & LIST_PTR) {	  fprintf(list_fp, " %04X\n", *list_ptr++);	}      }    }    if(listing_on < 0)      listing_on = 0;  }  list_flags = 0;  list_len = 0;}/* * parse and handle OPT-directive * (this is special as it must be done as macro definition time *  if inside a macro) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -