Browse Source

Start implementing ExportPackedTIOSFile.

git-svn-id: file:///var/svn/tigccpp/trunk@1146 9552661e-59e3-4036-b4f2-dbe53926924f
kevinkofler 17 years ago
parent
commit
e670151683
3 changed files with 126 additions and 6 deletions
  1. 118 0
      tigcc/ld-tigcc/export/exp_tios.c
  2. 5 0
      tigcc/ld-tigcc/export/exp_tios.h
  3. 3 6
      tigcc/ld-tigcc/export/export.c

+ 118 - 0
tigcc/ld-tigcc/export/exp_tios.c

@@ -20,8 +20,11 @@
 
 #ifdef TIOS_SUPPORT
 
+#include <string.h>
+
 #include "../manip.h"
 #include "../special.h"
+#include "../formats/tios.h"
 
 // Get the file size needed to export the program into a TIOS file.
 // Returns 0 on failure.
@@ -169,4 +172,119 @@ BOOLEAN ExportTIOSFile (const PROGRAM *Program, EXP_FILE *File, SIZE FileSize, P
 #undef FailWithError
 }
 
+#ifdef PUCRUNCH_SUPPORT
+// Export the internal data structures into a packed TIOS file.
+BOOLEAN ExportPackedTIOSFile (const PROGRAM *Program, EXP_FILE *File, SIZE FileSize, ProgramCalcs DestCalc)
+{
+	// Some macros to make the code more readable.
+#define FailWithError(Err...) ({ Error (Err); return FALSE; })
+#define BufferWrite(P,L,C) (memcpy (Buffer + CurPos, P, (L) * (C)), CurPos += (L) * (C))
+#define BufferWriteTI2(D) ({ WriteTI2 (*((TI2 *) (Buffer + CurPos)), D); CurPos += 2; })
+	
+	const char *SectionFileName = NULL;
+	OFFSET DataStart = 0;
+	
+	COUNT EmittedRelocCount = 0;
+	
+	// Calculate the size needed for the two size bytes and the
+	// tag.
+	SIZE VarFileSize = 2 + FileSize + 1;
+	I1 Buffer[VarFileSize];
+	OFFSET CurPos = 0;
+	
+	// Write out the 2 size bytes.
+	BufferWriteTI2 (VarFileSize - 2);
+	
+	// Get a pointer to the main section.
+	SECTION *MainSection = Program->MainSection;
+	
+	if (!MainSection)
+		FailWithError (NULL, "No main section.");
+	
+	SectionFileName = MainSection->FileName;
+	
+	// In nostub mode, execution simply starts at the beginning of
+	// the first section. But ideally, startup code should always be
+	// marked as such. When merging sections, the destination startup
+	// number is kept, so in the end, the complete code is marked as
+	// a startup section (which makes sense; it is startable).
+	if (!(MainSection->StartupNumber || (Program->Type == PT_NOSTUB)))
+		FailWithError (SectionFileName, "No startup section(s) defined.");
+	
+	if (!(MainSection->Data))
+		FailWithError (SectionFileName, "No section contents.");
+	
+	// Write out the section contents first.
+	DataStart = CurPos;
+	BufferWrite (MainSection->Data, MainSection->Size, 1);
+	
+	// Write out two zero bytes as a separator.
+	BufferWriteTI2 (0);
+	
+	if (!(IsEmpty (MainSection->Relocs)))
+	{
+		RELOC *Reloc;
+		
+		// Write out the relocation table.
+		for (Reloc = GetLast (MainSection->Relocs); Reloc; Reloc = GetPrev (Reloc))
+		{
+			// Get the current file name for error messages.
+			const char *CurFileName = GetFileName (MainSection, Reloc->Location);
+			
+			// If this can be resolved to a calculator-dependent value, write the
+			// value into the section data.
+			if (EmitCalcBuiltinValue (Reloc, DestCalc, File, FileSize, DataStart))
+				continue;
+			
+			// We can only emit relocs with a target symbol in the same section.
+			if (!(Reloc->Target.Symbol))
+				FailWithError (CurFileName, "Unresolved reference to `%s'.", Reloc->Target.SymbolName);
+			if (Reloc->Target.Symbol->Parent != MainSection)
+				FailWithError (CurFileName, "Cannot emit reloc to `%s' in different section.", Reloc->Target.SymbolName);
+			
+			// We can only emit 4-byte absolute relocs.
+			if (Reloc->Relative || (Reloc->Size != 4))
+				FailWithError (CurFileName, "Cannot emit %ld byte %s reloc to `%s'.", (long) Reloc->Size, Reloc->Relative ? "relative" : "absolute", Reloc->Target.SymbolName);
+			
+			if (((I2) Reloc->Location) != Reloc->Location)
+				FailWithError (CurFileName, "Cannot emit reloc outside of limited program range to `%s'.", Reloc->Target.SymbolName);
+			
+			{
+				OFFSET TargetLocation = GetLocationOffset (MainSection, &(Reloc->Target)) + Reloc->FixedOffset;
+				
+				if (((I2) TargetLocation) != TargetLocation)
+					FailWithError (CurFileName, "Cannot emit reloc to `%s' (Offset %ld; Location 0x%lX) outside of limited program range.", Reloc->Target.SymbolName, (long) (Reloc->Target.Offset + Reloc->FixedOffset), (long) (TargetLocation));
+				
+				// Everything seems to be correct.
+				BufferWriteTI2 (TargetLocation);
+				BufferWriteTI2 (Reloc->Location);
+				
+				// Increase the statistics.
+				EmittedRelocCount++;
+			}
+		}
+	}
+	
+	if ((!(IsEmpty (MainSection->ROMCalls))) && (!(MainSection->ROMCalls.Handled)))
+		FailWithError (SectionFileName, "ROM calls are not supported in this mode.");
+	
+	if ((!(IsEmpty (MainSection->RAMCalls))) && (!(MainSection->RAMCalls.Handled)))
+		FailWithError (SectionFileName, "RAM calls are not supported in this mode.");
+	
+	if ((!(IsEmpty (MainSection->LibCalls))) && (!(MainSection->LibCalls.Handled)))
+		FailWithError (SectionFileName, "Library calls are not supported in this mode.");
+	
+	// Write out the final ASM tag.
+	Buffer[CurPos] = TIOS_TAG_ASM;
+	
+	if (Program->OptimizeInfo->NativeRelocCount < EmittedRelocCount)
+		Program->OptimizeInfo->NativeRelocCount = EmittedRelocCount;
+	
+	return TRUE;
+	
+#undef FailWithError
+}
+
+#endif /* PUCRUNCH_SUPPORT */
+
 #endif /* TIOS_SUPPORT */

+ 5 - 0
tigcc/ld-tigcc/export/exp_tios.h

@@ -32,6 +32,11 @@ SIZE GetTIOSFileSize (const PROGRAM *Program);
 // Export the internal data structures into a TIOS file.
 BOOLEAN ExportTIOSFile (const PROGRAM *Program, EXP_FILE *File, SIZE FileSize, ProgramCalcs DestCalc);
 
+#ifdef PUCRUNCH_SUPPORT
+// Export the internal data structures into a packed TIOS file.
+BOOLEAN ExportPackedTIOSFile (const PROGRAM *Program, EXP_FILE *File, SIZE FileSize, ProgramCalcs DestCalc);
+#endif /* PUCRUNCH_SUPPORT */
+
 #endif /* TIOS_SUPPORT */
 
 #endif

+ 3 - 6
tigcc/ld-tigcc/export/export.c

@@ -174,12 +174,8 @@ static BOOLEAN ExportProgramToFormat (const PROGRAM *Program, const EXPORT_STRUC
 }
 
 #ifdef PUCRUNCH_SUPPORT
-#ifndef TARGET_EMBEDDED
 // Specifies whether to pack the main file with pucrunch.
 BOOLEAN Pack = FALSE;
-#else
-#error Pucrunch compression is only supported for the standalone target.
-#endif
 #endif /* PUCRUNCH_SUPPORT */
 
 // Export the internal data structures to external files, creating as many
@@ -237,8 +233,9 @@ BOOLEAN ExportProgram (const PROGRAM *Program, OUTPUT_FILE_FUNCTION GetOutputFil
 #ifdef PUCRUNCH_SUPPORT
 			if (Pack)
 			{
-				ExportStruct.FileType    = TIOS_TAG_OTH;
-				ExportStruct.Extension   = "ppg";
+				ExportStruct.ExportFile = ExportPackedTIOSFile;
+				ExportStruct.FileType   = TIOS_TAG_OTH;
+				ExportStruct.Extension  = "ppg";
 			}
 #endif /* !PUCRUNCH_SUPPORT */
 #else /* !TIOS_SUPPORT */