gnupic: [PATCH] code_pack / gpvo newer object file support


Previous by date: 14 Jan 2006 04:11:29 +0000 Re: [gnupic] gpasm - __CONFIG, Chen Xiao Fan
Next by date: 14 Jan 2006 04:11:29 +0000 picp 0.6.8 beta 1, Jeff
Previous in thread:
Next in thread:

Subject: [PATCH] code_pack / gpvo newer object file support
From: Michael Ballbach ####@####.####
Date: 14 Jan 2006 04:11:29 +0000
Message-Id: <20060114041124.GC2130@wayreth.rten.net>

Attached find two patches. One adds support for code_pack sections, and
the other allows gpvo to dump the (newer) COFF files that MPLAB is
spitting out these days. I've also attached the ASM I used for testing
in MPASM / GPASM.

About code_pack:

This was a little difficult to setup in the code since it tends to track
everything as words - so the solution is far from elegant. However, it
seems to do what MPLAB does, with a few caveats:

 o the listing output is not the same, most notably, you see full words
   in byteswapped order like you do for opcodes. MPASM outputs code pack
   sections in the listing as separate bytes.

   (example:

   0200 01        00045 blabel0 db 1
   0201   02      00046 blabel1 db 2
   0202 0403      00047 blabel2 db 3, 4)

 o MPASM does not emit padding bytes to pad a code_pack section to a
   word boundary (which means code_pack sections can be of an odd size),
   but the patch does emit 0xFF as a padding byte. The end result in the
   device should be equivalent because even MPASM doesn't allow starting
   a code_pack section on a non-word aligned boundary, and even if
   omitted once programmed that byte will take an 0xFF anyway. The main
   difference is that in object and hex files produced with gputils and
   this patch, you'll see the FF, and sections can't be an odd length.

 o I'm not sure how to go about integrating the test ASM into the test
   suite, since, because of the point above, the HEX file and the object
   files will be a little different.

 o MPASM does not emit line numbers (into the object file) for code_pack
   data, GPASM does.

About COFF:

Microchip made some changes to their COFF format. The only thing this
patch does is take into account the different offsets and symbol sizes
in the new format, it doesn't try to take any of the new information
into account.

This change also affects sections of a non-word aligned size. Previously
the odd byte would be lost. The patch will add the 0xFF padding byte and
add it as though it were a full word. This was primarily so that I could
use gpvo to dump the MPASM and GPASM versions of my test assembly for
comparison.

Both of these are reasonably tested but I did them very quickly and this
is my first exposure to the GPUTILS source, so they should be treated as
experimental.

Is anyone working on the CONFIG support?

-- 
Michael Ballbach, N0ZTQ
####@####.#### -- PGP KeyID: 0xA05D5555
http://www.rten.net/

diff -ru gputils-0.13.3-orig/gpasm/directive.c gputils-0.13.3/gpasm/directive.c
--- gputils-0.13.3-orig/gpasm/directive.c	2005-07-02 10:10:13.000000000 -0700
+++ gputils-0.13.3/gpasm/directive.c	2006-01-13 19:42:18.000000000 -0800
@@ -112,6 +112,7 @@
 
 int packed_hi_lo = 0;
 static int packed_byte = 0;
+gp_boolean _16packed_byte_acc;
 
 static void emit_packed(unsigned int value, unsigned int mode)
 {
@@ -157,7 +158,8 @@
 
 static void data(struct sllist *L, int flavor, int lit_mask)
 {
-
+  if(state.obj.section)
+    state.obj.section->emitted_pack_byte = false;
 
   if (L) {
 
@@ -170,9 +172,24 @@
 
       value = reloc_evaluate(list->p, RELOCT_ALL);
 
-      if(lit_mask & PACKING_BYTES)
-	emit_packed(value | flavor, lit_mask);
-      else {
+      if(lit_mask & PACKING_BYTES) {
+	if(!_16packed_byte_acc)
+	  emit_packed(value | flavor, lit_mask);
+        else {
+          if (state.pass == 2) {
+	    /* read what's in the current org - pack our byte with it using emit() directly */
+    	    i_memory_put(state.i_memory, state.org - 1,
+		         (i_memory_get(state.i_memory, state.org - 1) & ~0xff00) | (value << 8));
+	  }
+
+	  /* reset status */
+	  _16packed_byte_acc = false;
+	  if(state.obj.section) {
+	    state.obj.section->have_pack_byte = false;
+            state.obj.section->emitted_pack_byte = true;
+	  }
+	}
+      } else {
 	if((value > lit_mask) || (value < 0)) {
           gpwarning(GPW_RANGE,NULL);
 	}
@@ -193,9 +210,20 @@
 
   }
 
-  if(packed_hi_lo) 
-    emit_packed(flavor, lit_mask);
-  
+  if(packed_hi_lo) {
+    if(!(state.obj.new_sec_flags & STYP_BPACK)) {
+      emit_packed(flavor, lit_mask);
+    } else {
+      /* 
+       * still pad, but do so with 0xff (to match mplab), it will be
+       * overwritten if there is more db data.
+       */
+      emit_packed(flavor | 0xff, lit_mask);
+      _16packed_byte_acc = true;
+      if(state.obj.section)
+	state.obj.section->have_pack_byte = true;
+    }
+  }
 }
 
 
@@ -562,6 +590,50 @@
   return r;
 }
 
+static gpasmVal do_code_pack(gpasmVal r,
+		             char *name,
+		             int arity,
+		             struct pnode *parms)
+{
+  struct pnode *p;
+
+  if(!_16bit_core)
+    gperror(GPE_UNKNOWN, "code_pack is only supported on 16bit cores");
+  else {
+    state.lst.line.linetype = sec;
+    state.next_state = state_section;
+    _16packed_byte_acc = false;
+    if(state.obj.section) {
+      state.obj.section->have_pack_byte = false;
+      state.obj.section->emitted_pack_byte = false;
+    }
+
+    if (state.mode == absolute) {
+      gperror(GPE_OBJECT_ONLY, NULL);
+    } else {
+      switch (arity) {
+      case 0:
+        /* new relocatable section */
+        strncpy(state.obj.new_sec_name, ".code", sizeof(state.obj.new_sec_name));
+        state.obj.new_sec_addr = 0;
+        state.obj.new_sec_flags = STYP_TEXT | STYP_BPACK;
+        break;
+      case 1:
+        /* new absolute section */
+        p = HEAD(parms);
+        strncpy(state.obj.new_sec_name, ".code", sizeof(state.obj.new_sec_name));
+        state.obj.new_sec_addr = maybe_evaluate(p) >> _16bit_core;
+        state.obj.new_sec_flags = STYP_TEXT | STYP_ABS | STYP_BPACK;
+        break;
+      default:
+        enforce_arity(arity, 1);
+      }
+    }
+  }
+
+  return r;
+}
+
 static gpasmVal do_constant(gpasmVal r,
 		       char *name,
 		       int arity,
@@ -3429,6 +3501,7 @@
 
 struct insn op_0[] = {
   { "code",       0, (long int)do_code,      INSN_CLASS_FUNC,   0 },
+  { "code_pack",  0, (long int)do_code_pack, INSN_CLASS_FUNC,   0 },
   { "constant",   0, (long int)do_constant,  INSN_CLASS_FUNC,   0 },
   { "else",       0, (long int)do_else,      INSN_CLASS_FUNC,   ATTRIB_COND },
   { "endif",      0, (long int)do_endif,     INSN_CLASS_FUNC,   ATTRIB_COND },
diff -ru gputils-0.13.3-orig/gpasm/lst.c gputils-0.13.3/gpasm/lst.c
--- gputils-0.13.3-orig/gpasm/lst.c	2005-01-03 14:21:19.000000000 -0800
+++ gputils-0.13.3/gpasm/lst.c	2006-01-13 19:42:10.000000000 -0800
@@ -219,7 +219,7 @@
   unsigned int emitted = 0;
 
   assert(src_line != NULL);
-  
+
   switch (state.lst.line.linetype) {
   case equ: 
   case set:
@@ -239,17 +239,38 @@
 		         state.device.id_location + 1) & 0xffff);
     break;
   case insn:
-    snprintf(m, sizeof(m), "%04X ", state.lst.line.was_org << _16bit_core);
-    emitted = state.org - state.lst.line.was_org;
+    emitted = state.org - state.lst.line.was_org
+	     				+ (state.obj.section &&
+					   state.obj.section->emitted_pack_byte ? 1 : 0);
+    snprintf(m, sizeof(m), "%04X ", (state.lst.line.was_org << _16bit_core)
+	     				- (state.obj.section &&
+					   ((emitted == 0 && 
+					     state.obj.section->have_pack_byte) ||
+					    state.obj.section->emitted_pack_byte) ? 1 : 0));
+
     if (emitted >= 1) {
-      snprintf(buf, sizeof(buf), "%04X ", i_memory_get(state.i_memory, 
-			               state.lst.line.was_org) & 0xffff);
+      if(state.obj.section && state.obj.section->have_pack_byte && emitted == 1)
+	snprintf(buf, sizeof(buf), "%02X   ", i_memory_get(state.i_memory, state.lst.line.was_org) & 0xff);
+      else if(state.obj.section && state.obj.section->emitted_pack_byte)
+	snprintf(buf, sizeof(buf), "  %02X ", (i_memory_get(state.i_memory, state.lst.line.was_org - 1) & 0xff00) >> 8);
+      else
+        snprintf(buf, sizeof(buf), "%04X ", i_memory_get(state.i_memory, 
+			                 state.lst.line.was_org) & 0xffff);
+
       strncat(m, buf, sizeof(m));
     } else
       strncat(m, "     ", sizeof(m));
+
     if (emitted >= 2) {
-      snprintf(buf, sizeof(buf), "%04X ", i_memory_get(state.i_memory, 
-			               state.lst.line.was_org + 1) & 0xffff);
+      if(state.obj.section && state.obj.section->have_pack_byte && emitted == 2)
+        snprintf(buf, sizeof(buf), "%02X   ", i_memory_get(state.i_memory, 
+	  		                  state.lst.line.was_org
+				          + (state.obj.section->emitted_pack_byte ? 0 : 1)) & 0xffff);
+      else
+        snprintf(buf, sizeof(buf), "%04X ", i_memory_get(state.i_memory, 
+	  		                  state.lst.line.was_org
+				          + (state.obj.section &&
+					     state.obj.section->emitted_pack_byte ? 0 : 1)) & 0xffff);
       strncat(m, buf, sizeof(buf));
     } else
       strncat(m, "     ", sizeof(m));
@@ -355,23 +376,41 @@
     int i;
 
     for (i = 2; i < emitted; i += 2) {
+      unsigned int org = state.lst.line.was_org + i -
+			  (state.obj.section && state.obj.section->emitted_pack_byte ? 1 : 0);
+
       if ((i + 1) < emitted)
-        snprintf(m, sizeof(m), "%04X %04X %04X",
-                 ((state.lst.line.was_org + i) << _16bit_core),
-                 i_memory_get(state.i_memory, 
-                              state.lst.line.was_org + i) & 0xffff,
-		 i_memory_get(state.i_memory, 
-                              state.lst.line.was_org + i + 1) & 0xffff);
-      else
-        snprintf(m, sizeof(m), "%04X %04X",
-		 ((state.lst.line.was_org + i) << _16bit_core),
-		 i_memory_get(state.i_memory, 
-			      state.lst.line.was_org + i) & 0xffff);
-        lst_line(m);
+        if(state.obj.section && state.obj.section->have_pack_byte)
+          snprintf(m, sizeof(m), "%04X %04X %02X   ",
+                   org << _16bit_core,
+                   i_memory_get(state.i_memory, org) & 0xffff,
+		   i_memory_get(state.i_memory, org + 1) & 0xff);
+     	else
+          snprintf(m, sizeof(m), "%04X %04X %04X",
+                   org << _16bit_core,
+                   i_memory_get(state.i_memory, org) & 0xffff,
+	  	   i_memory_get(state.i_memory, org + 1) & 0xffff);
+      else {
+        if(state.obj.section && state.obj.section->have_pack_byte)
+	  snprintf(m, sizeof(m), "%04X %02X   ", 
+		   ((state.lst.line.was_org + i) << _16bit_core),
+		   i_memory_get(state.i_memory,
+			        state.lst.line.was_org + i) & 0xff);
+	else
+          snprintf(m, sizeof(m), "%04X %04X",
+		   ((state.lst.line.was_org + i) << _16bit_core),
+		   i_memory_get(state.i_memory, 
+			        state.lst.line.was_org + i) & 0xffff);
       }
+      lst_line(m);
+    }
 
     state.cod.emitting = 0;
   }
+ 
+  /* we reset this here, otherwise labels will display bytes again */
+  if(state.obj.section)
+    state.obj.section->emitted_pack_byte = false;
 }
 
 /* append the symbol table to the .lst file */
diff -ru gputils-0.13.3-orig/gpasm/parse.y gputils-0.13.3/gpasm/parse.y
--- gputils-0.13.3-orig/gpasm/parse.y	2005-01-03 14:21:19.000000000 -0800
+++ gputils-0.13.3/gpasm/parse.y	2006-01-13 19:42:10.000000000 -0800
@@ -39,6 +39,8 @@
 
 int yylex(void);
 extern int _16bit_core;
+extern gp_boolean _16packed_byte_acc;
+static gp_boolean _16packed_offset_labels;
 
 /************************************************************************/
 
@@ -425,7 +427,7 @@
 		set_global($1, $2, PERMANENT, gvt_constant);
 		break;
 	      case insn:
-		set_global($1, $2 << _16bit_core, PERMANENT, gvt_address);
+		set_global($1, ($2 << _16bit_core) - _16packed_offset_labels, PERMANENT, gvt_address);
 		break;
 	      case res:
 		set_global($1, $2, PERMANENT, gvt_static);
@@ -836,6 +838,16 @@
 	LABEL
         { 
           $$ = $1;
+
+	  /*
+	   * statements return their org - but, with 16bit cores, org is a word
+	   * address. for us to know whether a label points at a non word aligned
+	   * address, we must get status from the directive.c module through a
+	   * back channel. however, we must make sure to store this status before
+	   * any statement on the current line is processed, so we must save it here
+	   * before the statement rules run.
+	   */
+	  _16packed_offset_labels = _16packed_byte_acc;
         }
         |
         VARLAB_BEGIN expr ')'
diff -ru gputils-0.13.3-orig/libgputils/gpcoffgen.c gputils-0.13.3/libgputils/gpcoffgen.c
--- gputils-0.13.3-orig/libgputils/gpcoffgen.c	2005-05-22 18:31:33.000000000 -0700
+++ gputils-0.13.3/libgputils/gpcoffgen.c	2006-01-13 19:42:10.000000000 -0800
@@ -99,6 +99,8 @@
   new->reloc_ptr = 0;
   new->lineno_ptr = 0;
   new->next = NULL;
+  new->have_pack_byte = false;
+  new->emitted_pack_byte = false;
 
   return new;
 }
diff -ru gputils-0.13.3-orig/libgputils/gpcoff.h gputils-0.13.3/libgputils/gpcoff.h
--- gputils-0.13.3-orig/libgputils/gpcoff.h	2005-05-22 18:31:33.000000000 -0700
+++ gputils-0.13.3/libgputils/gpcoff.h	2006-01-13 19:42:10.000000000 -0800
@@ -112,6 +112,8 @@
 #define STYP_ACTREC   0x10000
 /* Section has been relocated.  This is a temporary flag used by the linker */
 #define STYP_RELOC    0x20000
+/* Section is byte packed on 16bit devices */
+#define STYP_BPACK    0x40000
 
 /* relocation entry */
 struct reloc
@@ -565,6 +567,18 @@
   /* linenumber pointer, only valid when writing coff file */  
   unsigned long lineno_ptr;
 
+  /*
+   * when the section is STYP_BPACK, this contains the flag as to whether the
+   * next byte would occupy part of the existing org address or start a new one
+   */
+  gp_boolean have_pack_byte;
+
+  /*
+   * when the section is STYP_BPACK, this will be true when we've just emitted
+   * a packed byte. (for synchronizing the listing)
+   */
+  gp_boolean emitted_pack_byte;
+
   struct gp_section_type *next;
 } gp_section_type;
 

diff -ru gputils-0.13.3-orig/gpasm/directive.c gputils-0.13.3/gpasm/directive.c
--- gputils-0.13.3-orig/gpasm/directive.c	2005-07-02 10:10:13.000000000 -0700
+++ gputils-0.13.3/gpasm/directive.c	2006-01-13 19:44:50.000000000 -0800
@@ -999,7 +999,7 @@
         return r;
       }
       
-      if (i == SYMBOL_SIZE) {
+      if (i == SYMBOL_SIZE_v1) {
         i = 0;
         aux_list = aux_list->next;      
       } else {
diff -ru gputils-0.13.3-orig/gputils/gpvo.c gputils-0.13.3/gputils/gpvo.c
--- gputils-0.13.3-orig/gputils/gpvo.c	2005-05-06 20:18:02.000000000 -0700
+++ gputils-0.13.3/gputils/gpvo.c	2006-01-13 19:44:53.000000000 -0800
@@ -132,8 +132,10 @@
   printf("Data\n");
   while (1) {
     memory = i_memory_get(section->data, org);
-    if ((memory & MEM_USED_MASK) == 0)
+    if ((memory & MEM_USED_MASK) == 0) {
+	  printf("memory is : %x\n", memory);
       break;
+	}
 
     if (section->flags & STYP_TEXT) {
       num_words = gp_disassemble(section->data,
@@ -376,13 +378,13 @@
         break;
       default:
         printf("  ");
-        for (i = 0; i < SYMBOL_SIZE; i++) {
+        for (i = 0; i < object->symbol_size; i++) {
           printf("%02x", aux->_aux_symbol.data[i]);
           if (i & 1) {
             printf(" ");
           }
         }
-        for (i = 0; i < SYMBOL_SIZE; i++) {
+        for (i = 0; i < object->symbol_size; i++) {
           c = aux->_aux_symbol.data[i];
           putchar( (isprint(c)) ? c : '.');
         }
diff -ru gputils-0.13.3-orig/libgputils/gpcoff.h gputils-0.13.3/libgputils/gpcoff.h
--- gputils-0.13.3-orig/libgputils/gpcoff.h	2005-05-22 18:31:33.000000000 -0700
+++ gputils-0.13.3/libgputils/gpcoff.h	2006-01-13 19:44:55.000000000 -0800
@@ -26,7 +26,8 @@
 /* These definitions are for the COFF as stored in a file. */
 
 /* define the typical values, if they aren't found warn the user */
-#define MICROCHIP_MAGIC 0x1234
+#define MICROCHIP_MAGIC_v1 0x1234
+#define MICROCHIP_MAGIC_v2 0x1240
 
 #define OPTMAGIC 0x5678
 
@@ -60,13 +61,14 @@
 struct opthdr
 {
   unsigned short  opt_magic;                   
-  unsigned short  vstamp;         /* version of the compiler assembler */             
+  unsigned long   vstamp;         /* version of the compiler assembler */             
   unsigned long   proc_type;                   
   unsigned long   rom_width_bits;                   
   unsigned long   ram_width_bits;           
 };
 
-#define OPT_HDR_SIZ 16
+#define OPT_HDR_SIZ_v1 16
+#define OPT_HDR_SIZ_v2 18
 
 /* section header format */
 struct scnhdr
@@ -227,7 +229,8 @@
   char            num_auxsym;  /* number of auxiliary symbols */
 };
 
-#define SYMBOL_SIZE 18
+#define SYMBOL_SIZE_v1 18
+#define SYMBOL_SIZE_v2 20
 
 /* Symbol section numbers */
 #define N_DEBUG -2
@@ -469,7 +472,7 @@
       unsigned short nreloc;
       unsigned short nlineno;
     } _aux_scn;
-    char data[SYMBOL_SIZE];
+    char data[SYMBOL_SIZE_v2];
   } _aux_symbol;
   
   struct gp_aux_type *next;
@@ -493,7 +496,7 @@
   struct gp_section_type *section;
 
   /* type */
-  unsigned short type;
+  unsigned long type;
 
   /* storage class */
   char class;
@@ -573,6 +576,12 @@
   /* object filename */
   char *filename;
 
+  /* format version/magic number */
+  int version;
+
+  /* to reduce conditionals, the size of symbols in this object */
+  size_t symbol_size;
+
   /* processor */
   enum pic_processor processor;
   
diff -ru gputils-0.13.3-orig/libgputils/gpreadobj.c gputils-0.13.3/libgputils/gpreadobj.c
--- gputils-0.13.3-orig/libgputils/gpreadobj.c	2005-05-22 18:31:33.000000000 -0700
+++ gputils-0.13.3/libgputils/gpreadobj.c	2006-01-13 19:44:57.000000000 -0800
@@ -37,9 +37,11 @@
   fread(&magic[0], 1, SARMAG, file);
   fclose(file); 
 
-  if (((magic[1]<<8) + magic[0]) == MICROCHIP_MAGIC)
+  if (((magic[1]<<8) + magic[0]) == MICROCHIP_MAGIC_v1)
     return object_file;
-    
+  if (((magic[1]<<8) + magic[0]) == MICROCHIP_MAGIC_v2)
+    return object_file;
+ 
   if (strncmp(magic, ARMAG, SARMAG) == 0)
     return archive_file;
 
@@ -94,17 +96,21 @@
 _read_file_header(gp_object_type *object, char *file)
 {
 
-  if (gp_getl16(&file[0]) != MICROCHIP_MAGIC)
+  if (gp_getl16(&file[0]) != MICROCHIP_MAGIC_v1 && gp_getl16(&file[0]) != MICROCHIP_MAGIC_v2)
     gp_error("invalid magic number in \"%s\"", object->filename);
 
+  object->version      = gp_getl16(&file[0]);
   object->num_sections = gp_getl16(&file[2]);
   object->time         = gp_getl32(&file[4]);
   object->symbol_ptr   = gp_getl32(&file[8]);
   object->num_symbols  = gp_getl32(&file[12]);
   
-  if (gp_getl16(&file[16]) != OPT_HDR_SIZ)
+  if ((object->version == MICROCHIP_MAGIC_v1 && gp_getl16(&file[16]) != OPT_HDR_SIZ_v1) ||
+	  (object->version == MICROCHIP_MAGIC_v2 && gp_getl16(&file[16]) != OPT_HDR_SIZ_v2))
     gp_error("incorrect optional header size in \"%s\"", object->filename);
-    
+
+  object->symbol_size = (object->version == MICROCHIP_MAGIC_v1 ? 
+						 	SYMBOL_SIZE_v1 : SYMBOL_SIZE_v2);
   object->flags = gp_getl16(&file[18]);
 
 }
@@ -112,28 +118,46 @@
 static void
 _read_opt_header(gp_object_type *object, char *file)
 {
- 
+  unsigned long vstamp;
+  size_t offset = 0;
+
   if (gp_getl16(&file[0]) != OPTMAGIC)
-    gp_error("invalid optional magic number in \"%s\"", object->filename);
-  
-  if (gp_getl16(&file[2]) != 1)
-    gp_error("invalid assembler version in \"%s\"", object->filename);
-  
-  object->processor = gp_processor_coff_proc(gp_getl32(&file[4]));
+    gp_error("invalid optional magic number (0x%04x) in \"%s\"", gp_getl16(&file[0]), object->filename);
+ 
+  offset = 2;
+  if (object->version == MICROCHIP_MAGIC_v1) {
+    vstamp = gp_getl16(&file[offset]);
+	offset += 2;
+  } else if (object->version == MICROCHIP_MAGIC_v2) {
+	vstamp = gp_getl32(&file[offset]);
+	offset += 4;
+  } else {
+	/* programmer error */
+    gp_error("logic error: version not handled in \"%s\"", object->filename);
+	vstamp = 0;
+	abort();
+  }
+
+  if (object->version == MICROCHIP_MAGIC_v1 && vstamp != 1)
+    gp_error("invalid assembler version (%d) in \"%s\"", vstamp, object->filename);
+ 
+  object->processor = gp_processor_coff_proc(gp_getl32(&file[offset]));
   if (object->processor == no_processor)
     gp_error("invalid processor type %#04x in \"%s\"",
              gp_getl32(&file[4]),
              object->filename);
+  offset += 4;
 
   object->class = gp_processor_class(object->processor);
   
-  if (gp_processor_rom_width(object->class) != gp_getl32(&file[8]))
+  if (gp_processor_rom_width(object->class) != gp_getl32(&file[offset]))
     gp_error("invalid rom width for selected processor in \"%s\"", 
              object->filename);
+  offset += 4;
   
-  if (gp_getl32(&file[12]) != 8)
-    gp_error("invalid ram width in \"%s\"", object->filename);
-
+  if (gp_getl32(&file[offset]) != 8)
+    gp_error("invalid ram width (%d) in \"%s\"", gp_getl32(&file[offset]), object->filename);
+  offset += 4;
 }
 
 static void 
@@ -231,11 +255,12 @@
   int org;
 
   /* move to the start of the section headers */
-  section_ptr = file + FILE_HDR_SIZ + OPT_HDR_SIZ;
+  section_ptr = file + FILE_HDR_SIZ + 
+	  		(object->version == MICROCHIP_MAGIC_v1 ? OPT_HDR_SIZ_v1 : OPT_HDR_SIZ_v2);
 
   /* setup pointer to string table */
   string_table = &file[object->symbol_ptr + 
-                 (SYMBOL_SIZE * object->num_symbols)];
+                 (object->symbol_size * object->num_symbols)];
 
   object->sections = gp_coffgen_blocksec(object->num_sections);
   current = object->sections;
@@ -257,17 +282,29 @@
 
       loc = &file[current->data_ptr];
       if ((current->flags & STYP_TEXT) || (current->flags & STYP_DATA_ROM)) {
-        /* size is in bytes, but words are stored in memory */
-        number = current->size / 2;
+        /* 
+		 * original comment: size is in bytes, but words are stored in memory
+		 *
+		 * this is true, but when using code_pack sections can have an odd
+		 * size. it looks like what MPLAB does is set the odd byte to 0xff in
+		 * program memory, and it doesn't seem to allow two code pack sections
+		 * to straddle a non-word boundary.
+		 */
+        number = (current->size + 1) / 2;
       } else {
         number = current->size;
       }
       for (j = 0; j < number; j++) {
         if ((current->flags & STYP_TEXT) || (current->flags & STYP_DATA_ROM)) {
-          value = (unsigned int)gp_getl16(&loc[j * 2]);
+		  if (j + 1 == number && current->size % 2 != 0) {
+		    /* an odd byte - use 0xff for the lower half, ala MPLAB */
+		    value = 0xff00 | loc[j * 2];
+		  } else {
+            value = (unsigned int)gp_getl16(&loc[j * 2]);
+		  }
         } else {
           value = (unsigned int)loc[j];
-        }        
+        }
         i_memory_put(current->data, org + j, MEM_USED_MASK | value);
       }
     }
@@ -307,7 +344,7 @@
 }
 
 static void
-_read_aux(gp_aux_type *aux, int aux_type, char *file, char *string_table)
+_read_aux(gp_object_type *object, gp_aux_type *aux, int aux_type, char *file, char *string_table)
 {
   
   aux->type = aux_type;
@@ -333,16 +370,17 @@
       aux->_aux_symbol._aux_scn.nlineno = gp_getl16(&file[6]);
       break;
     default:
-      memcpy(&aux->_aux_symbol.data[0], file, SYMBOL_SIZE);
+      memcpy(&aux->_aux_symbol.data[0], file, object->symbol_size);
   }
 
 }
 
 static void 
-_read_symbol(gp_symbol_type *symbol, char *file, char *string_table)
+_read_symbol(gp_object_type *object, gp_symbol_type *symbol, char *file, char *string_table)
 {
   char buffer[9];
   unsigned int offset;
+  size_t file_off = 0;
 
   if (gp_getl32(&file[0]) == 0) {
     /* read name from the string table */
@@ -355,11 +393,16 @@
     symbol->name = strdup(buffer);
   }
 
-  symbol->value = gp_getl32(&file[8]);
-  symbol->section_number = gp_getl16(&file[12]);
-  symbol->type = gp_getl16(&file[14]);
-  symbol->class = file[16];
-  symbol->num_auxsym = file[17];
+  file_off = 8;
+  symbol->value = gp_getl32(&file[file_off]);			file_off += 4;
+  symbol->section_number = gp_getl16(&file[file_off]);	file_off += 2;
+  if(object->version == MICROCHIP_MAGIC_v1) {
+	  symbol->type = gp_getl16(&file[file_off]);		file_off += 2;
+  } else {
+	  symbol->type = gp_getl32(&file[file_off]);		file_off += 4;
+  }
+  symbol->class = file[file_off];						file_off += 1;
+  symbol->num_auxsym = file[file_off];					file_off += 1;
 
   symbol->section = NULL;
   symbol->aux_list = NULL;
@@ -382,17 +425,17 @@
     object->symbols = gp_coffgen_blocksym(number);
 
     /* setup pointer to string table */
-    string_table = &file[object->symbol_ptr + (SYMBOL_SIZE * number)];
+    string_table = &file[object->symbol_ptr + (object->symbol_size * number)];
 
     /* read the symbols */
     file = &file[object->symbol_ptr];
     current = object->symbols;
     for (i = 0; i < number; i++) {
       /* read the symbol */
-      _read_symbol(current, file, string_table);
+      _read_symbol(object, current, file, string_table);
       current->number = i;
       num_auxsym = current->num_auxsym;
-      file += SYMBOL_SIZE;
+      file += object->symbol_size;
 
       if (num_auxsym != 0) {
         current->aux_list = gp_coffgen_blockaux(current->num_auxsym);
@@ -401,9 +444,9 @@
         
         /* read the aux symbols */
         for (j = 0; j < num_auxsym; j++) {
-          _read_aux(current_aux, aux_type, file, string_table);
+          _read_aux(object, current_aux, aux_type, file, string_table);
           current_aux = current_aux->next;
-          file += SYMBOL_SIZE;
+          file += object->symbol_size;
           i++;
         }
 
diff -ru gputils-0.13.3-orig/libgputils/gpreadobj.h gputils-0.13.3/libgputils/gpreadobj.h
--- gputils-0.13.3-orig/libgputils/gpreadobj.h	2005-01-03 14:21:23.000000000 -0800
+++ gputils-0.13.3/libgputils/gpreadobj.h	2006-01-13 19:44:59.000000000 -0800
@@ -25,6 +25,7 @@
 typedef enum gp_coff_type { 
   archive_file, 
   object_file, 
+  object_file_v2, 
   sys_err_file,
   unknown_file
 } gp_coff_type;
diff -ru gputils-0.13.3-orig/libgputils/gpwriteobj.c gputils-0.13.3/libgputils/gpwriteobj.c
--- gputils-0.13.3-orig/libgputils/gpwriteobj.c	2005-01-03 14:21:23.000000000 -0800
+++ gputils-0.13.3/libgputils/gpwriteobj.c	2006-01-13 19:45:00.000000000 -0800
@@ -83,12 +83,12 @@
 static void 
 _gp_coffgen_write_filehdr(gp_object_type *object, FILE *fp) 
 {
-  gp_fputl16(MICROCHIP_MAGIC, fp);
+  gp_fputl16(MICROCHIP_MAGIC_v1, fp);
   gp_fputl16(object->num_sections, fp);
   gp_fputl32(object->time, fp);
   gp_fputl32(object->symbol_ptr, fp);
   gp_fputl32(object->num_symbols, fp);
-  gp_fputl16(OPT_HDR_SIZ, fp);
+  gp_fputl16(OPT_HDR_SIZ_v1, fp);
   gp_fputl16(object->flags, fp);
 
   return;
@@ -338,7 +338,7 @@
   int section_number = 1;
   int symbol_number = 0;
 
-  loc = FILE_HDR_SIZ + OPT_HDR_SIZ + (SEC_HDR_SIZ * object->num_sections);
+  loc = FILE_HDR_SIZ + OPT_HDR_SIZ_v1 + (SEC_HDR_SIZ * object->num_sections);
 
   /* update the data pointers in the section headers */
   section = object->sections;

;
; the idea is to test as many permutations of packed data as possible,
; and to make sure that the label addresses generated are always correct.
;

;
; the labels on the same / different line are important because of how the
; parser works.
;

			list p=18f2455

blech		code_pack	0x100

label0
			db 1
label1
			db 2
label2
			db 3, 4
label4
			db 5
label5
			db 6, 7, 8
label8
			db 9, 0xa, 0xb
label0xb
			db 0xc
label0xc
			db 0xd, 0xe, 0xf, 0x10
label0x10
			db 0x11, 0x12, 0x13, 0x14, 0x15
label0x15	
			db 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b
label0x1b 
			db 0x1c
label0x1c
			db 0x1d, 0x1e
label0x1e
			db 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24
label0x24
			db 0x25
label0x25
			db 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c
label0x2c
			db 0x2d

blech2		code_pack	0x200

blabel0 db 1
blabel1 db 2
blabel2 db 3, 4
blabel4 db 5
blabel5 db 6, 7, 8
blabel8 db 9, 0xa, 0xb
blabel0xb db 0xc
blabel0xc db 0xd, 0xe, 0xf, 0x10
blabel0x10 db 0x11, 0x12, 0x13, 0x14, 0x15
blabel0x15 db 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b
blabel0x1b db 0x1c
blabel0x1c db 0x1d, 0x1e
blabel0x1e db 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24
blabel0x24 db 0x25
blabel0x25 db 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c
blabel0x2c db 0x2d

blech3		code
			movlw	0
			end





[Content type application/pgp-signature not shown. Download]

Previous by date: 14 Jan 2006 04:11:29 +0000 Re: [gnupic] gpasm - __CONFIG, Chen Xiao Fan
Next by date: 14 Jan 2006 04:11:29 +0000 picp 0.6.8 beta 1, Jeff
Previous in thread:
Next in thread:


Powered by ezmlm-browse 0.20.