Slight revamp of the optimisation system, featuring: strengthened flag parser, slight...
authorggn <ggn.dbug@gmail.com>
Fri, 17 Jul 2020 20:23:08 +0000 (23:23 +0300)
committerShamus Hammons <jlhamm@acm.org>
Fri, 17 Jul 2020 23:20:19 +0000 (18:20 -0500)
eagen0.c
mach.c
parmode.h
rmac.c
rmac.h
sect.c

index 2df5eceea09d11eb470232e8796d48c950bca594..60b7e4a6c40d564b76f526cb78186f952a15ff91 100644 (file)
--- a/eagen0.c
+++ b/eagen0.c
@@ -40,7 +40,7 @@ int eaNgen(WORD siz)
                        if (tdb)
                                MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
 
                        if (tdb)
                                MarkRelocatable(cursect, sloc, tdb, MWORD, NULL);
 
-                       if ((v == 0) && CHECK_OPTS(OPT_INDIRECT_DISP) && !movep)
+                       if ((v == 0) && CHECK_OPTS(OPT_OUTER_DISP) && !movep)
                        {
                                // If expr is 0, size optimise the opcode. Generally the lower
                                // 6 bits of the opcode for expr(ax) are 101rrr where rrr=the
                        {
                                // If expr is 0, size optimise the opcode. Generally the lower
                                // 6 bits of the opcode for expr(ax) are 101rrr where rrr=the
@@ -64,7 +64,7 @@ int eaNgen(WORD siz)
                                        chptr_opcode[1] |= 0x0080 & 255;          // slap in 010 bits
                                }
 
                                        chptr_opcode[1] |= 0x0080 & 255;          // slap in 010 bits
                                }
 
-                               if (sbra_flag)
+                               if (optim_warn_flag)
                                        warn("0(An) converted to (An)");
 
                                return OK;
                                        warn("0(An) converted to (An)");
 
                                return OK;
@@ -326,7 +326,7 @@ int eaNgen(WORD siz)
        case ABSL:
                if (w) // Defined
                {
        case ABSL:
                if (w) // Defined
                {
-                       if (optim_pc)
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
                                if (aNexattr&(DEFINED | REFERENCED | EQUATED) == DEFINED | REFERENCED)
                                        return error("relocation not allowed");
 
                                if (aNexattr&(DEFINED | REFERENCED | EQUATED) == DEFINED | REFERENCED)
                                        return error("relocation not allowed");
 
diff --git a/mach.c b/mach.c
index eec74f72b2d2c9d9343adf319049fe057827e88a..1ae8a2def8439d9e2e85f35ebee50e6b247842f6 100644 (file)
--- a/mach.c
+++ b/mach.c
@@ -354,7 +354,8 @@ int m_lea(WORD inst, WORD siz)
        {
                inst = B16(01010000, 01001000) | (((uint16_t)a0exval & 7) << 9) | (a0reg);
                D_word(inst);
        {
                inst = B16(01010000, 01001000) | (((uint16_t)a0exval & 7) << 9) | (a0reg);
                D_word(inst);
-               warn("lea size(An),An converted to addq #size,An");
+               if (optim_warn_flag)
+                       warn("lea size(An),An converted to addq #size,An");
                return OK;
        }
 
                return OK;
        }
 
@@ -458,25 +459,37 @@ int m_abcd(WORD inst, WORD siz)
 //
 int m_adda(WORD inst, WORD siz)
 {
 //
 int m_adda(WORD inst, WORD siz)
 {
-       if (a0exattr & DEFINED)
+       if ((a0exattr & DEFINED) && (am0 == IMMED))
        {
        {
-               if (CHECK_OPTS(OPT_ADDA_ADDQ))
+               if (CHECK_OPTS(OPT_ADDA_ADDQ))
                        if (a0exval > 1 && a0exval <= 8)
                        if (a0exval > 1 && a0exval <= 8)
+                       {
                                // Immediate is between 1 and 8 so let's convert to addq
                                return m_addq(B16(01010000, 00000000), siz);
                                // Immediate is between 1 and 8 so let's convert to addq
                                return m_addq(B16(01010000, 00000000), siz);
-       if (CHECK_OPTS(OPT_ADDA_LEA))
-               if (a0exval > 8 && (a0exval+0x8000)<0x10000)
-               {
-                       // Immediate is larger than 8 and word size so let's convert to lea
-                       am0 = ADISP;    // Change addressing mode
-                       a0reg = a1reg;  // In ADISP a0reg is used instead of a1reg!
-                       if (!(inst & (1 << 14)))
+                               if (optim_warn_flag)
+                                       warn("adda/suba size(An),An converted to addq/subq #size,An");
+                       }
+               if (CHECK_OPTS(OPT_ADDA_LEA))
+                       if (a0exval > 8 && (a0exval + 0x8000) < 0x10000)
                        {
                        {
-                               // We have a suba #x,AREG so let's negate the value
-                               a0exval = -a0exval;
+                               // Immediate is larger than 8 and word size so let's convert to lea
+                               am0 = ADISP;    // Change addressing mode
+                               a0reg = a1reg;  // In ADISP a0reg is used instead of a1reg!
+                               if (!(inst & (1 << 14)))
+                               {
+                                       // We have a suba #x,AREG so let's negate the value
+                                       a0exval = -a0exval;
+                               }
+
+                               // We're going to rely on +o4 for this, so let's ensure that it's on,
+                               // even just for this instruction
+                               int return_value;
+                               int temp_flag = optim_flags[OPT_LEA_ADDQ];
+                               optim_flags[OPT_LEA_ADDQ] = 1;                          // Temporarily save switch state
+                               return_value = m_lea(B16(01000001, 11011000), SIZW);
+                               optim_flags[OPT_LEA_ADDQ] = temp_flag;          // Restore switch state
+                               return return_value;
                        }
                        }
-                       return m_lea(B16(01000001, 11011000), SIZW);
-               }
        }
 
        inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
        }
 
        inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
@@ -732,7 +745,7 @@ int m_move(WORD inst, WORD size)
        {
                m_moveq((WORD)0x7000, (WORD)0);
 
        {
                m_moveq((WORD)0x7000, (WORD)0);
 
-               if (sbra_flag)
+               if (optim_warn_flag)
                        warn("move.l #size,dx converted to moveq");
        }
        else
                        warn("move.l #size,dx converted to moveq");
        }
        else
@@ -890,7 +903,7 @@ int m_br(WORD inst, WORD siz)
                                inst |= v & 0xFF;
                                D_word(inst);
 
                                inst |= v & 0xFF;
                                D_word(inst);
 
-                               if (sbra_flag)
+                               if (optim_warn_flag)
                                        warn("Bcc.w/BSR.w converted to .s");
 
                                return OK;
                                        warn("Bcc.w/BSR.w converted to .s");
 
                                return OK;
@@ -933,7 +946,18 @@ int m_br(WORD inst, WORD siz)
        {
                // .B
                AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr);
        {
                // .B
                AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr);
-               D_word(inst);
+               // So here we have a small issue: this bra.s could be zero offset, but we can never know.
+               // Because unless we know beforehand that the offset will be zero (i.e. "bra.s +0"), it's
+               // going to be a label below this instruction! We do have an optimisation flag that can
+               // check against this during fixups, but we cannot rely on the state of the flag after
+               // all the file(s) have been processed because its state might have changed multiple times
+               // during file parsing. (Yes, there's a very low chance that this will ever happen but
+               // it's not zero!). So, we can use the byte that is going to be filled during fixups
+               // to store the state of the optimisation flag and read it during that stage so each bra.s
+               // will have its state stored neatly. Sleazy? Eh, who cares, like this will ever happen ;)
+               // One final note: we'd better be damn sure that the flag's value is less than 256 or
+               // magical stuff will happen!
+               D_word(inst|optim_flags[OPT_NULL_BRA]);
                return OK;
        }
        else
                return OK;
        }
        else
index 955fade88621de27095dad9fba6f613c8498f76f..b03787eab6170f3260e04c656abff077b27a545c 100644 (file)
--- a/parmode.h
+++ b/parmode.h
@@ -322,7 +322,7 @@ AMn_IXN:                 // Handle any indexed (tok -> a comma)
                        {
                                expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
 
                        {
                                expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
 
-                               if (CHECK_OPTS(OPT_BASE_DISP) && AnBEXVAL == 0 && AnEXATTR != 0)
+                               if (CHECK_OPTS(OPT_020_DISP) && AnBEXVAL == 0 && AnEXATTR != 0)
                                {
                                        // bd=0 so let's optimise it out
                                        AnEXTEN|=EXT_BDSIZE0;
                                {
                                        // bd=0 so let's optimise it out
                                        AnEXTEN|=EXT_BDSIZE0;
@@ -346,12 +346,13 @@ AMn_IXN:                 // Handle any indexed (tok -> a comma)
                                        {
                                                // Defined, absolute values from $FFFF8000..$00007FFF
                                                // get optimized to absolute short
                                        {
                                                // Defined, absolute values from $FFFF8000..$00007FFF
                                                // get optimized to absolute short
-                                               if (CHECK_OPTS(OPT_ABS_SHORT)
+                                               if (CHECK_OPTS(OPT_020_DISP)
                                                        && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
                                                        && (((uint32_t)AnBEXVAL + 0x8000) < 0x10000))
                                                {
                                                        AnEXTEN |= EXT_BDSIZEW;
                                                        && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
                                                        && (((uint32_t)AnBEXVAL + 0x8000) < 0x10000))
                                                {
                                                        AnEXTEN |= EXT_BDSIZEW;
-                                                       warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
+                                                       if (optim_warn_flag)
+                                                               warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
                                                }
                                                else
                                                {
                                                }
                                                else
                                                {
@@ -467,8 +468,7 @@ AMn_IXN:                 // Handle any indexed (tok -> a comma)
                        else if (*tok == ']')
                        {
                                // PC and Xn is suppressed
                        else if (*tok == ']')
                        {
                                // PC and Xn is suppressed
-                               AnREG = 6 << 3;         // stuff 110 to mode field
-                               //AnEXTEN|=EXT_BS|EXT_IS;
+                               AnREG = 6 << 3;         // stuff 110b to mode field
                                AnEXTEN |= EXT_BS;
                        }
                        else
                                AnEXTEN |= EXT_BS;
                        }
                        else
@@ -479,16 +479,16 @@ AMn_IXN:                 // Handle any indexed (tok -> a comma)
                        // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
                        if (*tok == ']')
                        {
                        // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
                        if (*tok == ']')
                        {
-                               //([bd,An/PC],Xn,od)
+                               // ([bd,An/PC],Xn,od)
                                // Check for Xn
                                tok++;
 
                                if (*tok == ')')
                                {
                                // Check for Xn
                                tok++;
 
                                if (*tok == ')')
                                {
-                                       //Xn and od are non existent, get out of jail free card
+                                       // Xn and od are non existent, get out of jail free card
                                        tok++;
                                        AMn = MEMPRE;                   // ([bc,An,Xn],od) with no Xn and od
                                        tok++;
                                        AMn = MEMPRE;                   // ([bc,An,Xn],od) with no Xn and od
-                                       AnEXTEN |= EXT_IS | EXT_IISPREN;        //Suppress Xn and od
+                                       AnEXTEN |= EXT_IS | EXT_IISPREN;        // Suppress Xn and od
                                        goto AnOK;
                                }
                                else if (*tok != ',')
                                        goto AnOK;
                                }
                                else if (*tok != ',')
@@ -510,7 +510,7 @@ AMn_IXN:                 // Handle any indexed (tok -> a comma)
                                }
                                else
                                {
                                }
                                else
                                {
-                                       //No index found, suppress it
+                                       // No index found, suppress it
                                        AnEXTEN |= EXT_IS;
                                        tok--;                                  // Rewind tok to point to the comma
                                        goto IS_SUPPRESSEDn;    // https://xkcd.com/292/ - what does he know anyway?
                                        AnEXTEN |= EXT_IS;
                                        tok--;                                  // Rewind tok to point to the comma
                                        goto IS_SUPPRESSEDn;    // https://xkcd.com/292/ - what does he know anyway?
@@ -605,7 +605,7 @@ CHECKODn:
                                if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
                                        goto badmode;
 
                                if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
                                        goto badmode;
 
-                               if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXATTR & DEFINED) && (AnEXVAL == 0))
+                               if (CHECK_OPTS(OPT_020_DISP) && (AnEXATTR & DEFINED) && (AnEXVAL == 0))
                                {
                                        // od=0 so optimise it out
                                        AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
                                {
                                        // od=0 so optimise it out
                                        AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
@@ -643,13 +643,14 @@ CHECKODn:
 
                                        // Defined, absolute values from $FFFF8000..$00007FFF get
                                        // optimized to absolute short
 
                                        // Defined, absolute values from $FFFF8000..$00007FFF get
                                        // optimized to absolute short
-                                       if (CHECK_OPTS(OPT_ABS_SHORT)
+                                       if (CHECK_OPTS(OPT_020_DISP)
                                                && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
                                                && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
                                        {
                                                AnEXTEN |= EXT_IISPOSW; // Word outer displacement
                                                AMn = MEMPOST;
                                                && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
                                                && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
                                        {
                                                AnEXTEN |= EXT_IISPOSW; // Word outer displacement
                                                AMn = MEMPOST;
-                                               warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+                                               if (optim_warn_flag)
+                                                       warn("absolute value in outer displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
                                        }
 
                                }
                                        }
 
                                }
@@ -694,7 +695,7 @@ IS_SUPPRESSEDn:
 
                                expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
 
 
                                expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
 
-                               if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
+                               if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0))
                                {
                                        // od=0 so optimise it out
                                        AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
                                {
                                        // od=0 so optimise it out
                                        AMn = MEMPOST;           // let's say it's ([bd,An],Xn,od) with od=0 then
@@ -725,12 +726,13 @@ IS_SUPPRESSEDn:
                                        }
                                        // Defined, absolute values from $FFFF8000..$00007FFF get
                                        // optimized to absolute short
                                        }
                                        // Defined, absolute values from $FFFF8000..$00007FFF get
                                        // optimized to absolute short
-                                       else if (CHECK_OPTS(OPT_BASE_DISP)
+                                       else if (CHECK_OPTS(OPT_020_DISP)
                                                && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
                                                && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
                                        {
                                                //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
                                                && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
                                                && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
                                        {
                                                //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
-                                               warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+                                               if (optim_warn_flag)
+                                                       warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
                                        }
                                }
 
                                        }
                                }
 
@@ -858,7 +860,7 @@ IS_SUPPRESSEDn:
                                        if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
                                                goto badmode;
 
                                        if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
                                                goto badmode;
 
-                                       if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0) && (AnEXATTR & DEFINED))
+                                       if (CHECK_OPTS(OPT_020_DISP) && (AnEXVAL == 0) && (AnEXATTR & DEFINED))
                                        {
                                                // od=0 so optimise it out
                                                AMn = MEMPRE;            // let's say it's ([bd,An],Xn,od) with od=0 then
                                        {
                                                // od=0 so optimise it out
                                                AMn = MEMPRE;            // let's say it's ([bd,An],Xn,od) with od=0 then
@@ -889,12 +891,13 @@ IS_SUPPRESSEDn:
 
                                                // Defined, absolute values from $FFFF8000..$00007FFF
                                                // get optimized to absolute short
 
                                                // Defined, absolute values from $FFFF8000..$00007FFF
                                                // get optimized to absolute short
-                                               if (CHECK_OPTS(OPT_BASE_DISP)
+                                               if (CHECK_OPTS(OPT_020_DISP)
                                                        && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
                                                        && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
                                                {
                                                        expr_size = EXT_IISPREW;
                                                        && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
                                                        && (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
                                                {
                                                        expr_size = EXT_IISPREW;
-                                                       warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+                                                       if (optim_warn_flag)
+                                                               warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
                                                }
                                        }
 
                                                }
                                        }
 
@@ -1171,7 +1174,7 @@ CHK_FOR_DISPn:
 
                        // When PC relative is enforced, check for any symbols that aren't 
                        // EQU'd, in this case it's an illegal mode
 
                        // When PC relative is enforced, check for any symbols that aren't 
                        // EQU'd, in this case it's an illegal mode
-                       if (optim_pc)
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
                                if (AnEXATTR & REFERENCED)
                                        if (AnEXATTR & DEFINED)
                                                if (!(AnEXATTR & EQUATED))
                                if (AnEXATTR & REFERENCED)
                                        if (AnEXATTR & DEFINED)
                                                if (!(AnEXATTR & EQUATED))
@@ -1193,7 +1196,7 @@ CHK_FOR_DISPn:
                                {
                                        AMn = ABSW;
 
                                {
                                        AMn = ABSW;
 
-                                       if (sbra_flag)
+                                       if (optim_warn_flag)
                                                warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
                                }
                        }
                                                warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
                                }
                        }
diff --git a/rmac.c b/rmac.c
index 9f52e0b49f94856e1434c7d1006ab90ede01b7df..4fb1582a725c603ff64663bad92b59a63d008ba9 100644 (file)
--- a/rmac.c
+++ b/rmac.c
@@ -32,7 +32,7 @@ int m6502;                                            // 1, assembling 6502 code
 int as68_flag;                                 // as68 kludge mode
 int glob_flag;                                 // Assume undefined symbols are global
 int lsym_flag;                                 // Include local symbols in object file
 int as68_flag;                                 // as68 kludge mode
 int glob_flag;                                 // Assume undefined symbols are global
 int lsym_flag;                                 // Include local symbols in object file
-int sbra_flag;                                 // Warn about possible short branches
+int optim_warn_flag;                   // Warn about possible short branches
 int prg_flag;                                  // !=0, produce .PRG executable (2=symbols)
 int prg_extend;                                        // !=0, output extended .PRG symbols
 int legacy_flag;                               // Do stuff like insert code in RISC assembler
 int prg_flag;                                  // !=0, produce .PRG executable (2=symbols)
 int prg_extend;                                        // !=0, output extended .PRG symbols
 int legacy_flag;                               // Do stuff like insert code in RISC assembler
@@ -53,7 +53,6 @@ char * cmdlnexec;                             // Executable name, pointer to ARGV[0]
 char * searchpath = NULL;              // Search path for include files
 char defname[] = "noname.o";   // Default output filename
 int optim_flags[OPT_COUNT];            // Specific optimisations on/off matrix
 char * searchpath = NULL;              // Search path for include files
 char defname[] = "noname.o";   // Default output filename
 int optim_flags[OPT_COUNT];            // Specific optimisations on/off matrix
-int optim_pc = 0;                              // Enforce PC relative
 int activecpu = CPU_68000;             // Active 68k CPU (68000 by default)
 int activefpu = FPU_NONE;              // Active FPU (none by default)
 int org68k_active = 0;                 // .org switch for 68k (only with RAW output format)
 int activecpu = CPU_68000;             // Active 68k CPU (68000 by default)
 int activefpu = FPU_NONE;              // Active FPU (none by default)
 int org68k_active = 0;                 // .org switch for 68k (only with RAW output format)
@@ -164,17 +163,17 @@ void DisplayHelp(void)
                "  -o file           Output file name\n"
                "  +o[value]         Turn a specific optimisation on\n"
                "                    Available optimisation values and default settings:\n"
                "  -o file           Output file name\n"
                "  +o[value]         Turn a specific optimisation on\n"
                "                    Available optimisation values and default settings:\n"
-               "                    o0: Absolute long adddresses to word        (on)\n"
-               "                    o1: move.l #x,dn/an to moveq                (on)\n"
-               "                    o2: Word branches to short                  (on)\n"
-               "                    o3: Outer displacement 0(an) to (an)        (off)\n"
-               "                    o4: lea size(An),An to addq #size,An        (off)\n"
-               "                    o5: Absolute long base displacement to word (off)\n"
-               "                    o6: Null branches to NOP                    (off)\n"
-               "                    o7: clr.l Dx to moveq #0,Dx                 (off)\n"
-               "                    o8: adda.w/l #x,Dy to addq.w/l #x,Dy        (off)\n"
-               "                    o9: adda.w/l #x,Dy to lea x(Dy),Dy          (off)\n"
-               "                    op: Enforce PC relative                     (off)\n"
+               "                    o0: Absolute long addresses to word                      (on)\n"
+               "                    o1: move.l #x,dn/an to moveq                             (on)\n"
+               "                    o2: Word branches to short                               (on)\n"
+               "                    o3: Outer displacement 0(an) to (an)                     (off)\n"
+               "                    o4: lea size(An),An to addq #size,An                     (off)\n"
+               "                    o5: 68020+ Absolute long base/outer displacement to word (off)\n"
+               "                    o6: Null branches to NOP                                 (off)\n"
+               "                    o7: clr.l Dx to moveq #0,Dx                              (off)\n"
+               "                    o8: adda.w/l #x,Dy to addq.w/l #x,Dy                     (off)\n"
+               "                    o9: adda.w/l #x,Dy to lea x(Dy),Dy                       (off)\n"
+               "                    op: Enforce PC relative                                  (off)\n"
                "  ~o[value]         Turn a specific optimisation off\n"
                "  +oall             Turn all optimisations on\n"
                "  ~oall             Turn all optimisations off\n"
                "  ~o[value]         Turn a specific optimisation off\n"
                "  +oall             Turn all optimisations on\n"
                "  ~oall             Turn all optimisations off\n"
@@ -220,40 +219,54 @@ int ParseOptimization(char * optstring)
 {
        int onoff = 0;
 
 {
        int onoff = 0;
 
-       if (*optstring == '+')
-               onoff = 1;
-       else if (*optstring != '~')
-               return ERROR;
-
-       if ((optstring[2] == 'a' || optstring[2] == 'A')
-               && (optstring[3] == 'l' || optstring[3] == 'L')
-               && (optstring[4] == 'l' || optstring[4] == 'L'))
-       {
-               memset(optim_flags, onoff, OPT_COUNT * sizeof(int));
-               return OK;
-       }
-       else if (optstring[1] == 'o' || optstring[1] == 'O') // Turn on specific optimisation
+       while (*optstring)
        {
        {
-               if (optstring[2] == 'p' || optstring[2] == 'P')
+               if (*optstring == '+')
+                       onoff = 1;
+               else if (*optstring != '~')
+                       return ERROR;
+
+               if ((optstring[2] == 'a' || optstring[2] == 'A')
+                       && (optstring[3] == 'l' || optstring[3] == 'L')
+                       && (optstring[4] == 'l' || optstring[4] == 'L'))
                {
                {
-                       optim_pc = 1;
-                       return OK;
+                       memset(optim_flags, onoff, OPT_COUNT * sizeof(int));
+                       optstring += 5;
                }
                }
-
-               int opt_no = atoi(&optstring[2]);
-
-               if ((opt_no >= 0) && (opt_no < OPT_COUNT))
+               else if (optstring[1] == 'o' || optstring[1] == 'O') // Turn on specific optimisation
                {
                {
-                       optim_flags[opt_no] = onoff;
-                       return OK;
+                       if (optstring[2] == 'p' || optstring[2] == 'P')
+                       {
+                               optim_flags[OPT_PC_RELATIVE] = onoff;
+                               optstring += 3;
+                       }
+                       else
+                       {
+                               int opt_no = atoi(&optstring[2]);
+                               if ((opt_no >= 0) && (opt_no < OPT_COUNT))
+                               {
+                                       optim_flags[opt_no] = onoff;
+                                       optstring += 3;
+                                       // If opt_no is 2 digits then consume an extra character.
+                                       // Sounds a bit sleazy but we know we're not going to hit
+                                       // more than 100 optimisation switches so this should be fine.
+                                       // If we do hit that number then it'll probably be time to burn
+                                       // the whole codebase and start from scratch.
+                                       if (opt_no > 9)
+                                               optstring++;
+                               }
+                               else
+                                       return ERROR;
+                       }
                }
                else
                }
                else
+               {
                        return ERROR;
                        return ERROR;
+               }
+               if (*optstring == ',')
+                       optstring++;
        }
        }
-       else
-       {
-               return ERROR;
-       }
+       return OK;
 }
 
 
 }
 
 
@@ -275,7 +288,7 @@ int Process(int argc, char ** argv)
        verb_flag = perm_verb_flag;             // Initialize verbose flag
        as68_flag = 0;                                  // Initialize as68 kludge mode
        glob_flag = 0;                                  // Initialize .globl flag
        verb_flag = perm_verb_flag;             // Initialize verbose flag
        as68_flag = 0;                                  // Initialize as68 kludge mode
        glob_flag = 0;                                  // Initialize .globl flag
-       sbra_flag = 0;                                  // Initialize short branch flag
+       optim_warn_flag = 0;                    // Initialize short branch flag
        debug = 0;                                              // Initialize debug flag
        searchpath = NULL;                              // Initialize search path
        objfname = NULL;                                // Initialize object filename
        debug = 0;                                              // Initialize debug flag
        searchpath = NULL;                              // Initialize search path
        objfname = NULL;                                // Initialize object filename
@@ -522,9 +535,9 @@ int Process(int argc, char ** argv)
                                default: segpadsize = 2; break; // Effective autoeven();
                                }
                                break;
                                default: segpadsize = 2; break; // Effective autoeven();
                                }
                                break;
-                       case 's':                               // Warn about possible short branches
+                       case 's':                               // Warn about possible short branches and applied optimisations
                        case 'S':
                        case 'S':
-                               sbra_flag = 1;
+                               optim_warn_flag = 1;
                                break;
                        case 'u':                               // Make undefined symbols .globl
                        case 'U':
                                break;
                        case 'u':                               // Make undefined symbols .globl
                        case 'U':
diff --git a/rmac.h b/rmac.h
index 3d23ed55573b8c73554f5aeb0bc78f656a500f51..357d70e7babf507457bcb1c3356a68901946a806 100644 (file)
--- a/rmac.h
+++ b/rmac.h
@@ -284,13 +284,14 @@ enum
        OPT_ABS_SHORT     = 0,
        OPT_MOVEL_MOVEQ   = 1,
        OPT_BSR_BCC_S     = 2,
        OPT_ABS_SHORT     = 0,
        OPT_MOVEL_MOVEQ   = 1,
        OPT_BSR_BCC_S     = 2,
-       OPT_INDIRECT_DISP = 3,
+       OPT_OUTER_DISP    = 3,
        OPT_LEA_ADDQ      = 4,
        OPT_LEA_ADDQ      = 4,
-       OPT_BASE_DISP     = 5,
+       OPT_020_DISP      = 5,          // 020+ base and outer displacements (bd, od) absolute long to short
        OPT_NULL_BRA      = 6,
        OPT_CLR_DX        = 7,
        OPT_ADDA_ADDQ     = 8,
        OPT_ADDA_LEA      = 9,
        OPT_NULL_BRA      = 6,
        OPT_CLR_DX        = 7,
        OPT_ADDA_ADDQ     = 8,
        OPT_ADDA_LEA      = 9,
+       OPT_PC_RELATIVE   = 10,         // Enforce PC relative
        OPT_COUNT   // Dummy, used to count number of optimisation switches
 };
 
        OPT_COUNT   // Dummy, used to count number of optimisation switches
 };
 
@@ -311,13 +312,12 @@ extern int m6502;
 extern int list_flag;
 extern int glob_flag;
 extern int lsym_flag;
 extern int list_flag;
 extern int glob_flag;
 extern int lsym_flag;
-extern int sbra_flag;
+extern int optim_warn_flag;
 extern int obj_format;
 extern int legacy_flag;
 extern int prg_flag;   // 1 = write ".PRG" relocatable executable
 extern LONG PRGFLAGS;
 extern int optim_flags[OPT_COUNT];
 extern int obj_format;
 extern int legacy_flag;
 extern int prg_flag;   // 1 = write ".PRG" relocatable executable
 extern LONG PRGFLAGS;
 extern int optim_flags[OPT_COUNT];
-extern int optim_pc;
 extern int activecpu;
 extern int activefpu;
 extern uint32_t org68k_address;
 extern int activecpu;
 extern int activefpu;
 extern uint32_t org68k_address;
diff --git a/sect.c b/sect.c
index 781a81bda516c5e5fdbf7f0f06351a8a3e63f69e..cdf53ffc1ab5e650848211a030931580eb349a11 100644 (file)
--- a/sect.c
+++ b/sect.c
@@ -416,7 +416,7 @@ int ResolveFixups(int sno)
                        if (evexpr(fup->expr, &eval, &eattr, &esym) != OK)
                                continue;
 
                        if (evexpr(fup->expr, &eval, &eattr, &esym) != OK)
                                continue;
 
-                       if (optim_pc)
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
                                if (eattr & REFERENCED)
                                        if (eattr & DEFINED)
                                                if (!(eattr & EQUATED))
                                if (eattr & REFERENCED)
                                        if (eattr & DEFINED)
                                                if (!(eattr & EQUATED))
@@ -431,7 +431,7 @@ int ResolveFixups(int sno)
                        SYM * sy = fup->symbol;
                        eattr = sy->sattr;
 
                        SYM * sy = fup->symbol;
                        eattr = sy->sattr;
 
-                       if (optim_pc)
+                       if (CHECK_OPTS(OPT_PC_RELATIVE))
                                if (eattr & REFERENCED)
                                        if (eattr & DEFINED)
                                                if (!(eattr & EQUATED))
                                if (eattr & REFERENCED)
                                        if (eattr & DEFINED)
                                                if (!(eattr & EQUATED))
@@ -516,7 +516,7 @@ int ResolveFixups(int sno)
                                        }
                                }
 
                                        }
                                }
 
-                               if (sbra_flag && (dw & FU_LBRA) && (eval + 0x80 < 0x100))
+                               if (optim_warn_flag && (dw & FU_LBRA) && (eval + 0x80 < 0x100))
                                        warn("unoptimized short branch");
                        }
 
                                        warn("unoptimized short branch");
                        }
 
@@ -543,11 +543,13 @@ int ResolveFixups(int sno)
 
                        if (eval == 0)
                        {
 
                        if (eval == 0)
                        {
-                               if (CHECK_OPTS(OPT_NULL_BRA))
+                               if (*locp) // optim_flags[OPT_NULL_BRA] is stored there, check the comment in mach.s under m_br
                                {
                                        // Just output a NOP
                                        *locp++ = 0x4E;
                                        *locp = 0x71;
                                {
                                        // Just output a NOP
                                        *locp++ = 0x4E;
                                        *locp = 0x71;
+                                       if (optim_warn_flag)
+                                               warn("bra.s with zero offset converted to NOP");
                                        continue;
                                }
                                else
                                        continue;
                                }
                                else