diff -ur ld-tigcc.orig/bincode/fix_m68k.c ld-tigcc/bincode/fix_m68k.c --- ld-tigcc.orig/bincode/fix_m68k.c 2005-02-14 07:25:28.000000000 +0100 +++ ld-tigcc/bincode/fix_m68k.c 2008-02-28 19:46:17.000000000 +0100 @@ -27,6 +27,10 @@ #include +#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 @@ // 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 } } @@ -662,6 +672,181 @@ } } + +#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. diff -ur ld-tigcc.orig/bincode/m68k.h ld-tigcc/bincode/m68k.h --- ld-tigcc.orig/bincode/m68k.h 2004-12-23 00:12:09.000000000 +0100 +++ ld-tigcc/bincode/m68k.h 2008-02-27 19:56:44.000000000 +0100 @@ -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. diff -ur ld-tigcc.orig/export/exp_os.c ld-tigcc/export/exp_os.c --- ld-tigcc.orig/export/exp_os.c 2004-12-23 00:12:09.000000000 +0100 +++ ld-tigcc/export/exp_os.c 2008-02-27 20:57:16.000000000 +0100 @@ -110,33 +110,43 @@ { // 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. } } diff -ur ld-tigcc.orig/intrface.h ld-tigcc/intrface.h --- ld-tigcc.orig/intrface.h 2005-03-31 06:12:52.000000000 +0200 +++ ld-tigcc/intrface.h 2008-02-26 20:42:06.000000000 +0100 @@ -52,6 +52,8 @@ 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. diff -ur ld-tigcc.orig/main.c ld-tigcc/main.c --- ld-tigcc.orig/main.c 2005-04-22 21:34:10.000000000 +0200 +++ ld-tigcc/main.c 2008-02-26 20:42:02.000000000 +0100 @@ -389,6 +389,8 @@ #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) diff -ur ld-tigcc.orig/main_opt.inc ld-tigcc/main_opt.inc --- ld-tigcc.orig/main_opt.inc 2006-07-16 03:58:15.000000000 +0200 +++ ld-tigcc/main_opt.inc 2008-02-28 19:45:06.000000000 +0100 @@ -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 of the BSS Section in RAM (For Flash OS)\n" #endif /* FLASH_OS_SUPPORT */ #ifdef FARGO_SUPPORT " --fargo Create Fargo II program\n" @@ -133,6 +134,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")) diff -ur ld-tigcc.orig/special.c ld-tigcc/special.c --- ld-tigcc.orig/special.c 2005-08-03 02:31:49.000000000 +0200 +++ ld-tigcc/special.c 2008-02-27 19:25:12.000000000 +0100 @@ -332,8 +332,11 @@ 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))) @@ -738,6 +741,16 @@ 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) @@ -789,6 +802,18 @@ 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;