Browse Source

Import PpHd's patch to ld-tigcc as one big chunk.

git-svn-id: file:///var/svn/tigccpp/branches/ld-tigcc-flashos-improvements@1271 9552661e-59e3-4036-b4f2-dbe53926924f
debrouxl 15 years ago
parent
commit
8c5abd0888
7 changed files with 255 additions and 17 deletions
  1. 185 0
      bincode/fix_m68k.c
  2. 4 0
      bincode/m68k.h
  3. 25 15
      export/exp_os.c
  4. 2 0
      intrface.h
  5. 2 0
      main.c
  6. 10 0
      main_opt.inc
  7. 27 2
      special.c

+ 185 - 0
bincode/fix_m68k.c

@@ -27,6 +27,10 @@
 
 #include <stdlib.h>
 
+#ifdef FLASH_OS_SUPPORT
+static void M68kFixBssAbs16 (RELOC *Reloc, OPTIMIZE_INFO *OptimizeInfo);
+#endif
+
 // Apply generic code fixes and optimizations to a section.
 void M68kFixCode (SECTION *Section)
 {
@@ -80,6 +84,12 @@ void M68kFixCodePreMerge (SECTION *Dest, SECTION *Src, SIZE DestSize)
 					// Fix and possibly optimize or remove the reloc.
 					M68kFixReloc (Reloc, TargetDistance, OptimizeInfo);
 				}
+#ifdef FLASH_OS_SUPPORT
+                                // If we are for a flash os program, and the target is a BSS Section.
+                                if (Dest->Parent->Type == PT_FLASH_OS && Reloc->Target.Symbol
+                                    && Reloc->Target.Symbol->Parent == Reloc->Parent->Parent->BSSSection)
+                                  M68kFixBssAbs16 (Reloc, OptimizeInfo);
+#endif
 			}
 		}
 		
@@ -667,6 +677,181 @@ void M68kFixReloc (RELOC *Reloc, OFFSET TargetDistance, OPTIMIZE_INFO *OptimizeI
 	}
 }
 
+
+#ifdef FLASH_OS_SUPPORT
+static void M68kFixBssAbs16 (RELOC *Reloc, OPTIMIZE_INFO *OptimizeInfo)
+{
+  SECTION *Section = Reloc->Parent;
+  I1 *Data = Section->Data;
+  OFFSET RelocLocation = Reloc->Location;
+  OFFSET OpcodeLocation;
+  I1 *Opcode;
+
+  // Return if there is no data, the reloc is not optimizable or if the reloc size is not 4 bytes.
+  // If the section doesn't support the cut ranges, it doesn't worth the effort (we don't any reloc to emit).
+  if (!Data || Reloc->Unoptimizable || Reloc->Size != 4 || !Section->CanCutRanges)
+    return;
+  if (!(Reloc->Target.Symbol))
+    return;
+
+  // Test is the reloc is optimizable: the absolute address muse be < 2^15
+  OpcodeLocation  = GetLocationOffset (Reloc->Target.Symbol->Parent, &(Reloc->Target)) + Reloc->FixedOffset;
+  OpcodeLocation += (OFFSET) (OptimizeInfo->FlashOSBSSStart);
+  if (OpcodeLocation >= 0x7FFF)
+    return;
+
+  // Most opcodes are two bytes long, and the reloc follows immediately.
+  OpcodeLocation = RelocLocation - 2;
+  // Safety check before accessing the section data.
+  if (!IsBinaryDataRange (Section, OpcodeLocation, OpcodeLocation + 6, Reloc))
+    return;
+
+  Opcode = Data + OpcodeLocation;
+
+  // *** Move Optimization ***
+  // Optimize LEA(.L) var.L,reg into LEA(.w) var.W),reg.
+  if ((((Opcode [0] & M68K_LEA_ABS_MASK_0) == M68K_LEA_ABS_0) && ((Opcode [1] & M68K_LEA_ABS_MASK_1) == M68K_LEA_ABS_1))
+      // Optimize PEA(.L) var.L into PEA(.L) var.W(%PC).
+      || ((Opcode [0] == M68K_PEA_ABS_0) && (Opcode [1] == M68K_PEA_ABS_1))
+      // Optimize MOVE.x var.L,reg/(reg)/(reg)+ into
+      // MOVE.x var.W(%PC),reg/(reg)/(reg)+.
+      || (((Opcode [0] & M68K_MOVE_ABS_REG_MASK_0) == M68K_MOVE_ABS_REG_0) && ((Opcode [1] & M68K_MOVE_ABS_REG_MASK_1) == M68K_MOVE_ABS_REG_1)
+          && (!((Opcode [0] & M68K_MOVE_ABS_REG_INV_0_MASK_0) == M68K_MOVE_ABS_REG_INV_0_0))
+          && (!(((Opcode [0] & M68K_MOVE_ABS_REG_INV_1_MASK_0) == M68K_MOVE_ABS_REG_INV_1_0) && ((Opcode [1] & M68K_MOVE_ABS_REG_INV_1_MASK_1) == M68K_MOVE_ABS_REG_INV_1_1))))
+      // Optimize MOVE.x var.L,-(reg) into
+      // MOVE.x var.W(%PC),-(reg).
+      || (((Opcode [0] & M68K_MOVE_ABS_PREDEC_MASK_0) == M68K_MOVE_ABS_PREDEC_0) && ((Opcode [1] & M68K_MOVE_ABS_PREDEC_MASK_1) == M68K_MOVE_ABS_PREDEC_1)
+          && (!((Opcode [0] & M68K_MOVE_ABS_PREDEC_INV_0_MASK_0) == M68K_MOVE_ABS_PREDEC_INV_0_0))))
+    {
+      OptimizeInfo->OptimizeMovesResult++;
+      if (OptimizeInfo->OptimizeMoves)
+        {
+          // Turn the opcode into an abs16 one.
+          M68K_MAKE_ABS16_OPCODE_1 (Opcode [1]);
+          // Change the reloc to 2-byte absolute.
+          Reloc->Size = 2;
+          // Cut or fill the gained space.
+          M68kCutOrFillRange (Section, OpcodeLocation + 4, OpcodeLocation + 6, OptimizeInfo);
+        }
+      return;
+    }
+
+  // *** Test Optimization ***
+  // Optimize CMP.x var.L,reg into CMP.x var.W(%PC),reg.
+  if ((((Opcode [0] & M68K_CMP_ABS_REG_MASK_0) == M68K_CMP_ABS_REG_0) && ((Opcode [1] & M68K_CMP_ABS_REG_MASK_1) == M68K_CMP_ABS_REG_1)
+       && (!((Opcode [1] & M68K_CMP_ABS_REG_INV_0_MASK_1) == M68K_CMP_ABS_REG_INV_0_1)))
+      // Optimize BTST reg,var.L into BTST reg,var.W(%PC).
+      || (((Opcode [0] & M68K_BTST_REG_ABS_MASK_0) == M68K_BTST_REG_ABS_0) && ((Opcode [1] & M68K_BTST_REG_ABS_MASK_1) == M68K_BTST_REG_ABS_1)))
+    {
+      OptimizeInfo->OptimizeTestsResult++;
+      if (OptimizeInfo->OptimizeTests)
+        {
+          // Turn the opcode into a abs16 one.
+          M68K_MAKE_ABS16_OPCODE_1 (Opcode [1]);
+          // Change the reloc to 2-byte absolute.
+          Reloc->Size = 2;
+          // Cut or fill the gained space.
+          M68kCutOrFillRange (Section, OpcodeLocation + 4, OpcodeLocation + 6, OptimizeInfo);
+        }
+      return;
+    }
+
+  // *** Calculation Optimization ***
+  // Optimize ADD/SUB.x var.L,reg into
+  // ADD/SUB.x var.W(%PC),reg.
+  if ((((Opcode [0] & M68K_ADDSUB_ABS_REG_0_MASK_0) == M68K_ADDSUB_ABS_REG_0_0) && ((Opcode [1] & M68K_ADDSUB_ABS_REG_0_MASK_1) == M68K_ADDSUB_ABS_REG_0_1))
+      || (((Opcode [0] & M68K_ADDSUB_ABS_REG_1_MASK_0) == M68K_ADDSUB_ABS_REG_1_0) && ((Opcode [1] & M68K_ADDSUB_ABS_REG_1_MASK_1) == M68K_ADDSUB_ABS_REG_1_1))
+      // Optimize MUL/DIV.x var.L,reg into
+      // MUL/DIV.x var.W(%PC),reg.
+      || (((Opcode [0] & M68K_MULDIV_ABS_REG_MASK_0) == M68K_MULDIV_ABS_REG_0) && ((Opcode [1] & M68K_MULDIV_ABS_REG_MASK_1) == M68K_MULDIV_ABS_REG_1))
+      // Optimize AND/OR.x var.L,reg into
+      // AND/OR.x var.W(%PC),reg.
+      || (((Opcode [0] & M68K_ANDOR_ABS_REG_MASK_0) == M68K_ANDOR_ABS_REG_0) && ((Opcode [1] & M68K_ANDOR_ABS_REG_MASK_1) == M68K_ANDOR_ABS_REG_1)))
+    {
+      OptimizeInfo->OptimizeCalcsResult++;
+      if (OptimizeInfo->OptimizeCalcs)
+        {
+          // Turn the opcode into a abs16 one.
+          M68K_MAKE_ABS16_OPCODE_1 (Opcode [1]);
+          // Change the reloc to 2-byte .
+          Reloc->Size = 2;
+          // Cut or fill the gained space.
+          M68kCutOrFillRange (Section, OpcodeLocation + 4, OpcodeLocation + 6, OptimizeInfo);
+        }
+      return;
+    }
+
+  // Check opcodes of 8 bytes without prefix
+  if (!IsBinaryDataRange (Section, OpcodeLocation, OpcodeLocation + 8, Reloc))
+    return;
+
+  // Optimize MOVE.x var.L,ofs(reg) into
+  // MOVE.x var.W,ofs(reg)
+  // We cannot handle this above because of the
+  // offset, which comes after the reloc.
+  if (((Opcode [0] & M68K_MOVE_ABS_OFSREG_MASK_0) == M68K_MOVE_ABS_OFSREG_0) && ((Opcode [1] & M68K_MOVE_ABS_OFSREG_MASK_1) == M68K_MOVE_ABS_OFSREG_1)
+      && (!((Opcode [0] & M68K_MOVE_ABS_OFSREG_INV_0_MASK_0) == M68K_MOVE_ABS_OFSREG_INV_0_0)))
+    {
+      OptimizeInfo->OptimizeMovesResult++;
+      if (OptimizeInfo->OptimizeMoves)
+        {
+          // Turn the opcode into a abs16 one.
+          M68K_MAKE_ABS16_OPCODE_1 (Opcode [1]);
+          // Move the offset to the correct place.
+          Opcode [4] = Opcode [6];
+          Opcode [5] = Opcode [7];
+          // Change the reloc to 2-byte abs16.
+          Reloc->Size = 2;
+          // Cut or fill the gained space.
+          M68kCutOrFillRange (Section, OpcodeLocation + 6, OpcodeLocation + 8, OptimizeInfo);
+        }
+      return;
+    }
+
+  // Now Opcode are bigger (8 bytes)
+  OpcodeLocation = RelocLocation - 4;
+  Opcode = Data + OpcodeLocation;
+
+  if (!IsBinaryDataRange (Section, OpcodeLocation, OpcodeLocation + 8, Reloc))
+    return;
+
+  // Optimize MOVEM.x var.L,regs into
+  // MOVEM var.W,regs.
+  if (((Opcode [0] & M68K_MOVEM_ABS_REGS_MASK_0) == M68K_MOVEM_ABS_REGS_0) && ((Opcode [1] & M68K_MOVEM_ABS_REGS_MASK_1) == M68K_MOVEM_ABS_REGS_1))
+    {
+      OptimizeInfo->OptimizeMovesResult++;
+      if (OptimizeInfo->OptimizeMoves)
+        {
+          // Turn the opcode into a abs16 one.
+          M68K_MAKE_ABS16_OPCODE_1 (Opcode [1]);
+          // Change the reloc to 2-byte relative.
+          Reloc->Size = 2;
+          // Cut or fill the gained space.
+          M68kCutOrFillRange (Section, OpcodeLocation + 6, OpcodeLocation + 8, OptimizeInfo);
+        }
+    }
+
+  // Optimize BTST #num,var.L into
+  // BTST #num,var.W
+  if ((Opcode [0] == M68K_BTST_IMM_ABS_0) && (Opcode [1] == M68K_BTST_IMM_ABS_1) && (Opcode [2] == M68K_BTST_IMM_ABS_2))
+    {
+      OptimizeInfo->OptimizeTestsResult++;
+      if (OptimizeInfo->OptimizeTests)
+        {
+          // Turn the opcode into a abs16 one.
+          M68K_MAKE_ABS16_OPCODE_1 (Opcode [1]);
+          // Change the reloc to 2-byte absolute.
+          Reloc->Size = 2;
+          // Cut or fill the gained space.
+          M68kCutOrFillRange (Section, OpcodeLocation + 6, OpcodeLocation + 8, OptimizeInfo);
+        }
+    }
+
+  // Nothing can be done
+  return;
+}
+#endif
+
 // Checks if a specific reloc might be optimizable. This is currently
 // limited to 4-bytes absolute relocs because that is the only case
 // this is needed for.

+ 4 - 0
bincode/m68k.h

@@ -37,6 +37,10 @@
 // Make a relative opcode out of an absolute one.
 #define M68K_MAKE_REL_OPCODE_1(Opcode_1) ((Opcode_1)++)
 
+// Make an absolute 16 bits opcode out of an absolute 32 bits address
+#define M68K_MAKE_ABS16_OPCODE_1(Opcode_1) ((Opcode_1)--)
+#define M68K_MAKE_ABS16_OPCODE_0(Opcode_0) ((Opcode_0)-=2)
+
 // *** General Branches ***
 
 // Opcode of the unconditional absolute JMP instruction.

+ 25 - 15
export/exp_os.c

@@ -111,33 +111,43 @@ BOOLEAN ExportFlashOSFile (const PROGRAM *Program, EXP_FILE *File, SIZE FileSize
 		{
 			// Get the current file name for error messages.
 			const char *CurFileName = GetFileName (MainSection, Reloc->Location);
+                        OFFSET TargetLocation = 0;
 			
 			// 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))
+                        // Or 2-byte absolute relocs to the BSS Section.
+			if (Reloc->Relative || (Reloc->Size != 4 && (Reloc->Size != 2 || Reloc->Target.Symbol->Parent != Program->BSSSection)))
 				FailWithError (CurFileName, "Cannot emit %ld byte %s reloc to `%s'.", (long) Reloc->Size, Reloc->Relative ? "relative" : "absolute", Reloc->Target.SymbolName);
-			
-			{
-				OFFSET TargetLocation = GetLocationOffset (MainSection, &(Reloc->Target)) + Reloc->FixedOffset;
+
+                        // Check for BSS Section
+                        if (Program->OptimizeInfo->FlashOSBSSStart > 0
+                            && Reloc->Target.Symbol->Parent == Program->BSSSection) {
+                          TargetLocation = GetLocationOffset (Program->BSSSection, &(Reloc->Target)) + Reloc->FixedOffset;
+                          TargetLocation += (OFFSET) (Program->OptimizeInfo->FlashOSBSSStart);
+                          ExportSeek (File, DataStart + Reloc->Location);
+                          ExportWriteTI (File, TargetLocation, Reloc->Size, TRUE, TRUE);
+                          continue;
+                        }
+			// We can only emit relocs with a target symbol in the same section.
+			else if (Reloc->Target.Symbol->Parent != MainSection)
+				FailWithError (CurFileName, "Cannot emit reloc to `%s' in different section.", Reloc->Target.SymbolName);
+
+			TargetLocation = GetLocationOffset (MainSection, &(Reloc->Target)) + Reloc->FixedOffset;
 				
-				TargetLocation += (OFFSET) (ROMBase + 0x12000);
-				ExportSeek (File, DataStart + Reloc->Location);
-				ExportWriteTI (File, TargetLocation, Reloc->Size, TRUE, TRUE);
+                        TargetLocation += (OFFSET) (ROMBase + 0x12000);
+                        ExportSeek (File, DataStart + Reloc->Location);
+                        ExportWriteTI (File, TargetLocation, Reloc->Size, TRUE, TRUE);
 				
-				// Do not increase the statistics, since that would give a false
-				// impression that the relocation entries actually take up some
-				// space in the OS.
-			}
+                        // Do not increase the statistics, since that would give a false
+                        // impression that the relocation entries actually take up some
+                        // space in the OS.
 		}
 		ExportSeek (File, DataEnd);
 	}

+ 2 - 0
intrface.h

@@ -52,6 +52,8 @@ typedef struct ATTRIBUTE_PACKED {
 		CutRanges,          // Cut unneeded section ranges when optimizing.
 		ReorderSections,    // Reorder sections to shorten references.
 		MergeConstants;     // Merge constants and strings to avoid duplication.
+        B4
+                FlashOSBSSStart;    // Flash OS Start of BSS Section
 	SI4
 		ProgramSize,            // Size of the on-calc program variable.
 		DataSize,               // Size of the data variable.

+ 2 - 0
main.c

@@ -473,6 +473,8 @@ int main (int ArgCount, const char **Args)
 #ifdef FLASH_OS_SUPPORT
 				if (Program.Type == PT_FLASH_OS)
 				{
+                                        if (OptInfo->FlashOSBSSStart > 0 && Program.BSSSection)
+                                          Program.BSSSection->Handled = TRUE;
 					// Flash OS export: merge startup and normal sections separately.
 					// The resulting two parts are merged later, padding the first
 					// part to the full 24 KB of the OS startup area (base 1)

+ 10 - 0
main_opt.inc

@@ -67,6 +67,7 @@
 					        "     --native             Link in TIGCC native mode\n"
 #ifdef FLASH_OS_SUPPORT
 					        "     --flash-os           Create (unsigned) Flash OS\n"
+						"     --flash-os-bss-start=<start> Start of the BSS Section in RAM (For Flash OS)\n"
 #endif /* FLASH_OS_SUPPORT */
 #ifdef FARGO_SUPPORT
 					        "     --fargo              Create Fargo II program\n"
@@ -137,6 +138,15 @@
 					Warning (NULL, "Flash OS support in TIGCC is experimental.");
 				}
 				else
+				if (!(strncmp (Arg, "flash-os-bss-start=", sizeof ("flash-os-bss-start=") - 1)))
+				{
+					char *End;
+					Arg += sizeof ("flash-os-bss-start=") - 1;
+					OptInfo->FlashOSBSSStart = strtoul (Arg, &End, 0);
+					if (End == Arg)
+					   Error (NULL, "Invalid number for flash-os-bss-start");
+				}
+				else
 #endif /* FLASH_OS_SUPPORT */
 #ifdef FARGO_SUPPORT
 				if (ArgMatches ("fargo"))

+ 27 - 2
special.c

@@ -333,8 +333,11 @@ BOOLEAN CreateSpecialGlobalImports (PROGRAM *Program)
 		Result = Result && AddGlobalImport (Program, "__handle_constructors");
 	if (Program->Destructors.Start)
 		Result = Result && AddGlobalImport (Program, "__handle_destructors");
-	if (Program->BSSSection && Program->BSSSection->Initialized)
-		Result = Result && AddGlobalImport (Program, "__initialize_bss");
+	if (Program->BSSSection && Program->BSSSection->Initialized
+#ifdef FLASH_OS_SUPPORT
+            && Program->Type != PT_FLASH_OS
+#endif /* FLASH_OS_SUPPORT */
+          )	Result = Result && AddGlobalImport (Program, "__initialize_bss");
 	
 	// Handle BSS section if any.
 	if (Program->BSSSection && (!(Program->BSSSection->Handled)))
@@ -739,6 +742,16 @@ BOOLEAN ResolveSpecialSymbolLocation (SECTION *Section, LOCATION *Location, BOOL
 				else
 					return TRUE;
 			}
+			else if (SymNameMatches ("bss_even_end"))
+			{
+				if (Program->BSSSection)
+				{
+					NewSymbol = Program->BSSSection->SectionSymbol;
+					NewTargetOffset = (OFFSET) ((unsigned long) (Program->BSSSection->Size + 1) & ~1UL);
+				}
+				else
+					return TRUE;
+			}
 			else if (SymNameMatches ("bss_size"))
 			{
 				if (Program->BSSSection)
@@ -822,6 +835,18 @@ BOOLEAN ResolveSpecialSymbolLocation (SECTION *Section, LOCATION *Location, BOOL
 				else
 					return TRUE;
 			}
+#ifdef FLASH_OS_SUPPORT
+                        else if (SymNameMatches ("archive_start"))
+                          {
+				if (Program->ResolveAllBuiltins && Program->MainSection)
+                                  {
+                                    SetToEntryPoint = TRUE;
+                                    NewValue = (OFFSET) ((unsigned long) (Program->MainSection->Size + 65535) & ~65535UL) - 0x02000;
+                                  }
+				else
+                                  return TRUE;
+                          }
+#endif
 			else if (SymNameMatches ("kernel_export_table"))
 			{
 				BOOLEAN HasExports = FALSE;