예제 #1
0
        private static void GenerateHeader(IGenerator gen, StreamWriter sw)
        {
            DisasmProject proj      = gen.Project;
            Formatter     formatter = gen.SourceFormatter;

            // Check for header comment.
            if (proj.LongComments.TryGetValue(DisplayList.Line.HEADER_COMMENT_OFFSET,
                                              out MultiLineComment headerComment))
            {
                List <string> formatted = headerComment.FormatText(formatter, string.Empty);
                foreach (string str in formatted)
                {
                    gen.OutputLine(str);
                }
            }

            gen.OutputAsmConfig();

            // Format symbols.
            foreach (DefSymbol defSym in proj.ActiveDefSymbolList)
            {
                // Use an operand length of 1 so things are shown as concisely as possible.
                string valueStr = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                gen.Localizer.LabelMap, defSym.DataDescriptor, defSym.Value, 1, false);
                gen.OutputEquDirective(defSym.Label, valueStr, defSym.Comment);
            }

            // If there was at least one symbol, output a blank line.
            if (proj.ActiveDefSymbolList.Count != 0)
            {
                gen.OutputLine(string.Empty);
            }
        }
예제 #2
0
        //- instructions ------------------------------------------------------

        public PseudoOp handlePseudoOp(Token token)
        {
            PseudoOp pseudo = null;

            switch (token.strval)
            {
            case "DB":
            case "DW":
            case "DD":
            case "DQ":
            case "DT":
                char    ch   = token.strval[1];
                int     size = (ch == 'B') ? 1 : (ch == 'W') ? 2 : (ch == 'D') ? 4 : (ch == 'Q') ? 8 : 10;
                Operand val  = getOperand();
                pseudo = new DataDefinition(size, val);
                break;
            }

            //skip any trailing junk & goto eoln
            while (token.type != TokenType.EOLN)
            {
                token = prep.getToken();
            }
            return(pseudo);
        }
예제 #3
0
 // IGenerator
 public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs,
                                      LocalVariableTable allDefs)
 {
     foreach (DefSymbol defSym in newDefs)
     {
         string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter,
                                                         Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1,
                                                         PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
         OutputLine(SourceFormatter.FormatVariableLabel(defSym.Label),
                    SourceFormatter.FormatPseudoOp(sDataOpNames.VarDirective),
                    valueStr, SourceFormatter.FormatEolComment(defSym.Comment));
     }
 }
예제 #4
0
파일: AsmCc65.cs 프로젝트: X65/6502bench
 // IGenerator
 public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs,
                                      LocalVariableTable allDefs)
 {
     foreach (DefSymbol defSym in newDefs)
     {
         // Use an operand length of 1 so values are shown as concisely as possible.
         string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter,
                                                         Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1,
                                                         PseudoOp.FormatNumericOpFlags.None);
         OutputLine(SourceFormatter.FormatVariableLabel(defSym.Label),
                    SourceFormatter.FormatPseudoOp(sDataOpNames.VarDirective),
                    valueStr, SourceFormatter.FormatEolComment(defSym.Comment));
     }
 }
예제 #5
0
파일: AsmAcme.cs 프로젝트: X65/6502bench
        // IGenerator
        public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs,
                                             LocalVariableTable allDefs)
        {
            OutputLine(string.Empty, "!zone", "Z" + offset.ToString("x6"), string.Empty);
            for (int i = 0; i < allDefs.Count; i++)
            {
                DefSymbol defSym = allDefs[i];

                string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter,
                                                                Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1,
                                                                PseudoOp.FormatNumericOpFlags.None);
                OutputEquDirective(SourceFormatter.FormatVariableLabel(defSym.Label),
                                   valueStr, defSym.Comment);
            }
        }
예제 #6
0
        // IGenerator
        public void UpdateCharacterEncoding(FormatDescriptor dfd)
        {
            CharEncoding.Encoding newEnc = PseudoOp.SubTypeToEnc(dfd.FormatSubType);
            if (newEnc == CharEncoding.Encoding.Unknown)
            {
                // probably not a character operand
                return;
            }
            if (newEnc != mCurrentEncoding)
            {
                switch (newEnc)
                {
                case CharEncoding.Encoding.Ascii:
                    OutputLine(string.Empty, ".enc", '"' + ASCII_ENC_NAME + '"', string.Empty);
                    break;

                case CharEncoding.Encoding.HighAscii:
                    // If this is a numeric operand (not string), and we're currently in
                    // ASCII mode, the "| $80" in the delimiter will handle this without
                    // the need for a .enc.  Much less clutter for sources that have plain
                    // ASCII strings but test high ASCII constants.
                    if (mCurrentEncoding == CharEncoding.Encoding.Ascii && !dfd.IsString)
                    {
                        newEnc = mCurrentEncoding;
                    }
                    else
                    {
                        OutputLine(string.Empty, ".enc", '"' + HIGH_ASCII_ENC_NAME + '"',
                                   string.Empty);
                    }
                    break;

                case CharEncoding.Encoding.C64Petscii:
                    OutputLine(string.Empty, ".enc", "\"none\"", string.Empty);
                    break;

                case CharEncoding.Encoding.C64ScreenCode:
                    OutputLine(string.Empty, ".enc", "\"screen\"", string.Empty);
                    break;

                default:
                    Debug.Assert(false);
                    break;
                }
                mCurrentEncoding = newEnc;
            }
        }
예제 #7
0
        private static void GenerateHeader(IGenerator gen, StreamWriter sw)
        {
            DisasmProject proj      = gen.Project;
            Formatter     formatter = gen.SourceFormatter;

            // Check for header comment.
            if (proj.LongComments.TryGetValue(LineListGen.Line.HEADER_COMMENT_OFFSET,
                                              out MultiLineComment headerComment))
            {
                List <string> formatted = headerComment.FormatText(formatter, string.Empty);
                foreach (string str in formatted)
                {
                    gen.OutputLine(str);
                }
            }

            gen.OutputAsmConfig();

            // Format symbols.
            bool prevConst = false;

            foreach (DefSymbol defSym in proj.ActiveDefSymbolList)
            {
                if (prevConst && !defSym.IsConstant)
                {
                    // Output a blank line between the constants and the address equates.
                    gen.OutputLine(string.Empty);
                }
                // Use an operand length of 1 so values are shown as concisely as possible.
                string valueStr = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                gen.Localizer.LabelMap, defSym.DataDescriptor, defSym.Value, 1,
                                                                PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                string labelStr = gen.Localizer.ConvLabel(defSym.Label);
                gen.OutputEquDirective(labelStr, valueStr, defSym.Comment);

                prevConst = defSym.IsConstant;
            }

            // If there was at least one symbol, output a blank line.
            if (proj.ActiveDefSymbolList.Count != 0)
            {
                gen.OutputLine(string.Empty);
            }
        }
예제 #8
0
        // IGenerator
        public void OutputLocalVariableTable(int offset, List <DefSymbol> newDefs,
                                             LocalVariableTable allDefs)
        {
            // We can do better here, but it requires knowing whether anything in "newDefs"
            // overwrote a previous entry.  If everything is new, we don't need to start
            // a new zone, and can just output newDefs.  (We don't need to start a new zone
            // on a "clear previous".)
            OutputLine(string.Empty, "!zone", "Z" + offset.ToString("x6"), string.Empty);
            for (int i = 0; i < allDefs.Count; i++)
            {
                DefSymbol defSym = allDefs[i];

                string valueStr = PseudoOp.FormatNumericOperand(SourceFormatter,
                                                                Project.SymbolTable, null, defSym.DataDescriptor, defSym.Value, 1,
                                                                PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                OutputEquDirective(SourceFormatter.FormatVariableLabel(defSym.Label),
                                   valueStr, defSym.Comment);
            }
        }
예제 #9
0
        // IGenerator
        public void OutputDataOp(int offset)
        {
            Formatter formatter = SourceFormatter;

            byte[]   data = Project.FileData;
            Anattrib attr = Project.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = mLocalizer.ConvLabel(attr.Symbol.Label);
            }

            string commentStr = SourceFormatter.FormatEolComment(Project.Comments[offset]);
            string opcodeStr, operandStr;

            FormatDescriptor dfd = attr.DataDescriptor;

            Debug.Assert(dfd != null);
            int length = dfd.Length;

            Debug.Assert(length > 0);

            bool multiLine = false;

            switch (dfd.FormatType)
            {
            case FormatDescriptor.Type.Default:
                if (length != 1)
                {
                    Debug.Assert(false);
                    length = 1;
                }
                opcodeStr = sDataOpNames.DefineData1;
                int operand = RawData.GetWord(data, offset, length, false);
                operandStr = formatter.FormatHexValue(operand, length * 2);
                break;

            case FormatDescriptor.Type.NumericLE:
                opcodeStr = sDataOpNames.GetDefineData(length);
                operand   = RawData.GetWord(data, offset, length, false);
                UpdateCharacterEncoding(dfd);
                operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                           mLocalizer.LabelMap, dfd, operand, length,
                                                           PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                break;

            case FormatDescriptor.Type.NumericBE:
                opcodeStr = sDataOpNames.GetDefineBigData(length);
                if ((string.IsNullOrEmpty(opcodeStr)))
                {
                    // Nothing defined, output as comma-separated single-byte values.
                    GenerateShortSequence(offset, length, out opcodeStr, out operandStr);
                }
                else
                {
                    UpdateCharacterEncoding(dfd);
                    operand    = RawData.GetWord(data, offset, length, true);
                    operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                               mLocalizer.LabelMap, dfd, operand, length,
                                                               PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                }
                break;

            case FormatDescriptor.Type.Fill:
                opcodeStr  = sDataOpNames.Fill;
                operandStr = length + "," + formatter.FormatHexValue(data[offset], 2);
                break;

            case FormatDescriptor.Type.Dense:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputDenseHex(offset, length, labelStr, commentStr);
                break;

            case FormatDescriptor.Type.Junk:
                int fillVal = Helper.CheckRangeHoldsSingleValue(data, offset, length);
                if (fillVal >= 0 && GenCommon.CheckJunkAlign(offset, dfd, Project.AddrMap))
                {
                    // .align <expression>[, <fill>]
                    opcodeStr = sDataOpNames.Align;
                    int alignVal = 1 << FormatDescriptor.AlignmentToPower(dfd.FormatSubType);
                    operandStr = alignVal.ToString() +
                                 "," + formatter.FormatHexValue(fillVal, 2);
                }
                else if (fillVal >= 0)
                {
                    // treat same as Fill
                    opcodeStr  = sDataOpNames.Fill;
                    operandStr = length + "," + formatter.FormatHexValue(fillVal, 2);
                }
                else
                {
                    // treat same as Dense
                    multiLine = true;
                    opcodeStr = operandStr = null;
                    OutputDenseHex(offset, length, labelStr, commentStr);
                }
                break;

            case FormatDescriptor.Type.StringGeneric:
            case FormatDescriptor.Type.StringReverse:
            case FormatDescriptor.Type.StringNullTerm:
            case FormatDescriptor.Type.StringL8:
            case FormatDescriptor.Type.StringL16:
            case FormatDescriptor.Type.StringDci:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputString(offset, labelStr, commentStr);
                break;

            default:
                opcodeStr  = "???";
                operandStr = "***";
                break;
            }

            if (!multiLine)
            {
                opcodeStr = formatter.FormatPseudoOp(opcodeStr);
                OutputLine(labelStr, opcodeStr, operandStr, commentStr);
            }
        }
예제 #10
0
        private static void GenerateInstruction(IGenerator gen, StreamWriter sw,
                                                LocalVariableLookup lvLookup, int offset, int instrBytes, bool doAddCycles)
        {
            DisasmProject proj      = gen.Project;
            Formatter     formatter = gen.SourceFormatter;

            byte[]   data = proj.FileData;
            Anattrib attr = proj.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = gen.Localizer.ConvLabel(attr.Symbol.Label);
            }

            OpDef op       = proj.CpuDef.GetOpDef(data[offset]);
            int   operand  = op.GetOperand(data, offset, attr.StatusFlags);
            int   instrLen = op.GetLength(attr.StatusFlags);

            OpDef.WidthDisambiguation wdis = OpDef.WidthDisambiguation.None;
            if (op.IsWidthPotentiallyAmbiguous)
            {
                wdis = OpDef.GetWidthDisambiguation(instrLen, operand);
            }
            if (gen.Quirks.SinglePassAssembler && wdis == OpDef.WidthDisambiguation.None &&
                (op.AddrMode == OpDef.AddressMode.DP ||
                 op.AddrMode == OpDef.AddressMode.DPIndexX) ||
                op.AddrMode == OpDef.AddressMode.DPIndexY)
            {
                // Could be a forward reference to a direct-page label.  For ACME, we don't
                // care if it's forward or not.
                if ((gen.Quirks.SinglePassNoLabelCorrection && IsLabelReference(gen, offset)) ||
                    IsForwardLabelReference(gen, offset))
                {
                    wdis = OpDef.WidthDisambiguation.ForceDirect;
                }
            }

            string opcodeStr = formatter.FormatOpcode(op, wdis);

            string formattedOperand = null;
            int    operandLen       = instrLen - 1;

            PseudoOp.FormatNumericOpFlags opFlags = PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix;
            bool isPcRelBankWrap = false;

            // Tweak branch instructions.  We want to show the absolute address rather
            // than the relative offset (which happens with the OperandAddress assignment
            // below), and 1-byte branches should always appear as a 4-byte hex value.
            if (op.AddrMode == OpDef.AddressMode.PCRel)
            {
                Debug.Assert(attr.OperandAddress >= 0);
                operandLen = 2;
                opFlags   |= PseudoOp.FormatNumericOpFlags.IsPcRel;
            }
            else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
                     op.AddrMode == OpDef.AddressMode.StackPCRelLong)
            {
                opFlags |= PseudoOp.FormatNumericOpFlags.IsPcRel;
            }
            else if (op.AddrMode == OpDef.AddressMode.Imm ||
                     op.AddrMode == OpDef.AddressMode.ImmLongA ||
                     op.AddrMode == OpDef.AddressMode.ImmLongXY)
            {
                opFlags |= PseudoOp.FormatNumericOpFlags.HasHashPrefix;
            }
            if ((opFlags & PseudoOp.FormatNumericOpFlags.IsPcRel) != 0)
            {
                int branchDist = attr.Address - attr.OperandAddress;
                isPcRelBankWrap = branchDist > 32767 || branchDist < -32768;
            }

            // 16-bit operands outside bank 0 need to include the bank when computing
            // symbol adjustment.
            int operandForSymbol = operand;

            if (attr.OperandAddress >= 0)
            {
                operandForSymbol = attr.OperandAddress;
            }

            // Check Length to watch for bogus descriptors.  (ApplyFormatDescriptors() should
            // now be screening bad descriptors out, so we may not need the Length test.)
            if (attr.DataDescriptor != null && attr.Length == attr.DataDescriptor.Length)
            {
                FormatDescriptor dfd = gen.ModifyInstructionOperandFormat(offset,
                                                                          attr.DataDescriptor, operand);

                // Format operand as directed.
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    // Special handling for the double-operand block move.
                    string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                  gen.Localizer.LabelMap, dfd, operand >> 8, 1,
                                                                  PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                    string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                  gen.Localizer.LabelMap, dfd, operand & 0xff, 1,
                                                                  PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                    if (gen.Quirks.BlockMoveArgsReversed)
                    {
                        string tmp = opstr1;
                        opstr1 = opstr2;
                        opstr2 = tmp;
                    }
                    string hash = gen.Quirks.BlockMoveArgsNoHash ? "" : "#";
                    formattedOperand = hash + opstr1 + "," + hash + opstr2;
                }
                else
                {
                    if (attr.DataDescriptor.IsStringOrCharacter)
                    {
                        gen.UpdateCharacterEncoding(dfd);
                    }
                    formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                     lvLookup, gen.Localizer.LabelMap, dfd,
                                                                     offset, operandForSymbol, operandLen, opFlags);
                }
            }
            else
            {
                // Show operand value in hex.
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    int arg1, arg2;
                    if (gen.Quirks.BlockMoveArgsReversed)
                    {
                        arg1 = operand & 0xff;
                        arg2 = operand >> 8;
                    }
                    else
                    {
                        arg1 = operand >> 8;
                        arg2 = operand & 0xff;
                    }
                    string hash = gen.Quirks.BlockMoveArgsNoHash ? "" : "#";
                    formattedOperand = hash + formatter.FormatHexValue(arg1, 2) + "," +
                                       hash + formatter.FormatHexValue(arg2, 2);
                }
                else
                {
                    if (operandLen == 2)
                    {
                        // This is necessary for 16-bit operands, like "LDA abs" and "PEA val",
                        // when outside bank zero.  The bank is included in the operand address,
                        // but we don't want to show it here.
                        operandForSymbol &= 0xffff;
                    }
                    formattedOperand = formatter.FormatHexValue(operandForSymbol, operandLen * 2);
                }
            }
            string operandStr = formatter.FormatOperand(op, formattedOperand, wdis);

            if (gen.Quirks.StackIntOperandIsImmediate && op.AddrMode == OpDef.AddressMode.StackInt)
            {
                // COP $02 is standard, but some require COP #$02
                operandStr = '#' + operandStr;
            }

            string eolComment = proj.Comments[offset];

            if (doAddCycles)
            {
                bool branchCross = (attr.Address & 0xff00) != (operandForSymbol & 0xff00);
                int  cycles      = proj.CpuDef.GetCycles(op.Opcode, attr.StatusFlags, attr.BranchTaken,
                                                         branchCross);
                if (cycles > 0)
                {
                    if (!string.IsNullOrEmpty(eolComment))
                    {
                        eolComment = cycles.ToString() + "  " + eolComment;
                    }
                    else
                    {
                        eolComment = cycles.ToString();
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(eolComment))
                    {
                        eolComment = (-cycles).ToString() + "+ " + eolComment;
                    }
                    else
                    {
                        eolComment = (-cycles).ToString() + "+";
                    }
                }
            }
            string commentStr = formatter.FormatEolComment(eolComment);

            string replMnemonic = gen.ModifyOpcode(offset, op);

            if (attr.Length != instrBytes)
            {
                // This instruction has another instruction inside it.  Throw out what we
                // computed and just output as bytes.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (isPcRelBankWrap && gen.Quirks.NoPcRelBankWrap)
            {
                // Some assemblers have trouble generating PC-relative operands that wrap
                // around the bank.  Output as raw hex.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (op.AddrMode == OpDef.AddressMode.BlockMove &&
                     gen.Quirks.BlockMoveArgsReversed)
            {
                // On second thought, just don't even output the wrong thing.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (replMnemonic == null)
            {
                // No mnemonic exists for this opcode.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (replMnemonic != string.Empty)
            {
                // A replacement mnemonic has been provided.
                opcodeStr = formatter.FormatMnemonic(replMnemonic, wdis);
            }
            gen.OutputLine(labelStr, opcodeStr, operandStr, commentStr);

            // Assemblers like Merlin32 try to be helpful and track SEP/REP, but they do the
            // wrong thing if we're in emulation mode.  Force flags back to short.
            if (proj.CpuDef.HasEmuFlag && gen.Quirks.TracksSepRepNotEmu && op == OpDef.OpREP_Imm)
            {
                if ((operand & 0x30) != 0 && attr.StatusFlags.E == 1)
                {
                    gen.OutputRegWidthDirective(offset, 0, 0, 1, 1);
                }
            }
        }
예제 #11
0
        private static void GenerateInstruction(IGenerator gen, StreamWriter sw, int offset,
                                                int instrBytes, bool doAddCycles)
        {
            DisasmProject proj      = gen.Project;
            Formatter     formatter = gen.SourceFormatter;

            byte[]   data = proj.FileData;
            Anattrib attr = proj.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = gen.Localizer.ConvLabel(attr.Symbol.Label);
            }

            OpDef op       = proj.CpuDef.GetOpDef(data[offset]);
            int   operand  = op.GetOperand(data, offset, attr.StatusFlags);
            int   instrLen = op.GetLength(attr.StatusFlags);

            OpDef.WidthDisambiguation wdis = OpDef.WidthDisambiguation.None;
            if (op.IsWidthPotentiallyAmbiguous)
            {
                wdis = OpDef.GetWidthDisambiguation(instrLen, operand);
            }

            string replMnemonic = gen.ReplaceMnemonic(op);
            string opcodeStr    = formatter.FormatOpcode(op, wdis);

            string formattedOperand = null;
            int    operandLen       = instrLen - 1;
            bool   isPcRel          = false;
            bool   isPcRelBankWrap  = false;

            // Tweak branch instructions.  We want to show the absolute address rather
            // than the relative offset (which happens with the OperandAddress assignment
            // below), and 1-byte branches should always appear as a 4-byte hex value.
            if (op.AddrMode == OpDef.AddressMode.PCRel)
            {
                Debug.Assert(attr.OperandAddress >= 0);
                operandLen = 2;
                isPcRel    = true;
            }
            else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
                     op.AddrMode == OpDef.AddressMode.StackPCRelLong)
            {
                isPcRel = true;
            }
            if (isPcRel)
            {
                int branchDist = attr.Address - attr.OperandAddress;
                isPcRelBankWrap = branchDist > 32767 || branchDist < -32768;
            }

            // 16-bit operands outside bank 0 need to include the bank when computing
            // symbol adjustment.
            int operandForSymbol = operand;

            if (attr.OperandAddress >= 0)
            {
                operandForSymbol = attr.OperandAddress;
            }

            // Check Length to watch for bogus descriptors (?)
            if (attr.DataDescriptor != null && attr.Length == attr.DataDescriptor.Length)
            {
                // Format operand as directed.
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    // Special handling for the double-operand block move.
                    string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                  gen.Localizer.LabelMap, attr.DataDescriptor, operand >> 8, 1, false);
                    string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                  gen.Localizer.LabelMap, attr.DataDescriptor, operand & 0xff, 1, false);
                    if (gen.Quirks.BlockMoveArgsReversed)
                    {
                        string tmp = opstr1;
                        opstr1 = opstr2;
                        opstr2 = tmp;
                    }
                    formattedOperand = opstr1 + "," + opstr2;
                }
                else
                {
                    formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                     gen.Localizer.LabelMap, attr.DataDescriptor,
                                                                     operandForSymbol, operandLen, isPcRel);
                }
            }
            else
            {
                // Show operand value in hex.
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    int arg1, arg2;
                    if (gen.Quirks.BlockMoveArgsReversed)
                    {
                        arg1 = operand & 0xff;
                        arg2 = operand >> 8;
                    }
                    else
                    {
                        arg1 = operand >> 8;
                        arg2 = operand & 0xff;
                    }
                    formattedOperand = formatter.FormatHexValue(arg1, 2) + "," +
                                       formatter.FormatHexValue(arg2, 2);
                }
                else
                {
                    if (operandLen == 2)
                    {
                        // This is necessary for 16-bit operands, like "LDA abs" and "PEA val",
                        // when outside bank zero.  The bank is included in the operand address,
                        // but we don't want to show it here.
                        operandForSymbol &= 0xffff;
                    }
                    formattedOperand = formatter.FormatHexValue(operandForSymbol, operandLen * 2);
                }
            }
            string operandStr = formatter.FormatOperand(op, formattedOperand, wdis);

            string eolComment = proj.Comments[offset];

            if (doAddCycles)
            {
                bool branchCross = (attr.Address & 0xff00) != (operandForSymbol & 0xff00);
                int  cycles      = proj.CpuDef.GetCycles(op.Opcode, attr.StatusFlags, attr.BranchTaken,
                                                         branchCross);
                if (cycles > 0)
                {
                    eolComment = cycles.ToString() + "  " + eolComment;
                }
                else
                {
                    eolComment = (-cycles).ToString() + "+ " + eolComment;
                }
            }
            string commentStr = formatter.FormatEolComment(eolComment);

            if (attr.Length != instrBytes)
            {
                // This instruction has another instruction inside it.  Throw out what we
                // computed and just output as bytes.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (isPcRelBankWrap && gen.Quirks.NoPcRelBankWrap)
            {
                // Some assemblers have trouble generating PC-relative operands that wrap
                // around the bank.  Output as raw hex.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (op.AddrMode == OpDef.AddressMode.BlockMove &&
                     gen.Quirks.BlockMoveArgsReversed)
            {
                // On second thought, just don't even output the wrong thing.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (replMnemonic == null)
            {
                // No mnemonic exists for this opcode.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (replMnemonic != string.Empty)
            {
                // A replacement mnemonic has been provided.
                opcodeStr = formatter.FormatMnemonic(replMnemonic, wdis);
            }
            gen.OutputLine(labelStr, opcodeStr, operandStr, commentStr);

            // Assemblers like Merlin32 try to be helpful and track SEP/REP, but they do the
            // wrong thing if we're in emulation mode.  Force flags back to short.
            if (proj.CpuDef.HasEmuFlag && gen.Quirks.TracksSepRepNotEmu && op == OpDef.OpREP_Imm)
            {
                if ((operand & 0x30) != 0 && attr.StatusFlags.E == 1)
                {
                    gen.OutputRegWidthDirective(offset, 0, 0, 1, 1);
                }
            }
        }
예제 #12
0
        // IGenerator
        public void OutputDataOp(int offset)
        {
            Formatter formatter = SourceFormatter;

            byte[]   data = Project.FileData;
            Anattrib attr = Project.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = mLocalizer.ConvLabel(attr.Symbol.Label);
            }

            string commentStr = SourceFormatter.FormatEolComment(Project.Comments[offset]);
            string opcodeStr, operandStr;

            FormatDescriptor dfd = attr.DataDescriptor;

            Debug.Assert(dfd != null);
            int length = dfd.Length;

            Debug.Assert(length > 0);

            bool multiLine = false;

            switch (dfd.FormatType)
            {
            case FormatDescriptor.Type.Default:
                if (length != 1)
                {
                    Debug.Assert(false);
                    length = 1;
                }
                opcodeStr = sDataOpNames.DefineData1;
                int operand = RawData.GetWord(data, offset, length, false);
                operandStr = formatter.FormatHexValue(operand, length * 2);
                break;

            case FormatDescriptor.Type.NumericLE:
                opcodeStr  = sDataOpNames.GetDefineData(length);
                operand    = RawData.GetWord(data, offset, length, false);
                operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                           mLocalizer.LabelMap, dfd, operand, length, false);
                break;

            case FormatDescriptor.Type.NumericBE:
                opcodeStr = sDataOpNames.GetDefineBigData(length);
                if (opcodeStr == null)
                {
                    // Nothing defined, output as comma-separated single-byte values.
                    GenerateShortSequence(offset, length, out opcodeStr, out operandStr);
                }
                else
                {
                    operand    = RawData.GetWord(data, offset, length, true);
                    operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                               mLocalizer.LabelMap, dfd, operand, length, false);
                }
                break;

            case FormatDescriptor.Type.Fill:
                opcodeStr  = sDataOpNames.Fill;
                operandStr = length + "," + formatter.FormatHexValue(data[offset], 2);
                break;

            case FormatDescriptor.Type.Dense:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputDenseHex(offset, length, labelStr, commentStr);
                break;

            case FormatDescriptor.Type.String:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputString(offset, labelStr, commentStr);
                break;

            default:
                opcodeStr  = "???";
                operandStr = "***";
                break;
            }

            if (!multiLine)
            {
                opcodeStr = formatter.FormatPseudoOp(opcodeStr);
                OutputLine(labelStr, opcodeStr, operandStr, commentStr);
            }
        }
예제 #13
0
        // IGenerator
        public void OutputDataOp(int offset)
        {
            Formatter formatter = SourceFormatter;

            byte[]   data = Project.FileData;
            Anattrib attr = Project.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = mLocalizer.ConvLabel(attr.Symbol.Label);
            }

            string commentStr = SourceFormatter.FormatEolComment(Project.Comments[offset]);
            string opcodeStr, operandStr;

            FormatDescriptor dfd = attr.DataDescriptor;

            Debug.Assert(dfd != null);
            int length = dfd.Length;

            Debug.Assert(length > 0);

            bool multiLine = false;

            switch (dfd.FormatType)
            {
            case FormatDescriptor.Type.Default:
                if (length != 1)
                {
                    Debug.Assert(false);
                    length = 1;
                }
                opcodeStr = sDataOpNames.DefineData1;
                int operand = RawData.GetWord(data, offset, length, false);
                operandStr = formatter.FormatHexValue(operand, length * 2);
                break;

            case FormatDescriptor.Type.NumericLE:
                opcodeStr  = sDataOpNames.GetDefineData(length);
                operand    = RawData.GetWord(data, offset, length, false);
                operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                           mLocalizer.LabelMap, dfd, operand, length,
                                                           PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                break;

            case FormatDescriptor.Type.NumericBE:
                opcodeStr = sDataOpNames.GetDefineBigData(length);
                if ((string.IsNullOrEmpty(opcodeStr)))
                {
                    // Nothing defined, output as comma-separated single-byte values.
                    GenerateShortSequence(offset, length, out opcodeStr, out operandStr);
                }
                else
                {
                    operand    = RawData.GetWord(data, offset, length, true);
                    operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                               mLocalizer.LabelMap, dfd, operand, length,
                                                               PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                }
                break;

            case FormatDescriptor.Type.Fill:
                opcodeStr  = sDataOpNames.Fill;
                operandStr = length + "," + formatter.FormatHexValue(data[offset], 2);
                break;

            case FormatDescriptor.Type.Dense:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputDenseHex(offset, length, labelStr, commentStr);
                break;

            case FormatDescriptor.Type.Junk:
                // The ca65 .align directive has a dependency on the alignment of the
                // segment as a whole.  We're not currently declaring multiple segments,
                // so we can't use .align without generating complaints.
                int fillVal = Helper.CheckRangeHoldsSingleValue(data, offset, length);
                if (fillVal >= 0)
                {
                    // treat same as Fill
                    opcodeStr  = sDataOpNames.Fill;
                    operandStr = length + "," + formatter.FormatHexValue(fillVal, 2);
                }
                else
                {
                    // treat same as Dense
                    multiLine = true;
                    opcodeStr = operandStr = null;
                    OutputDenseHex(offset, length, labelStr, commentStr);
                }
                break;

            case FormatDescriptor.Type.StringGeneric:
            case FormatDescriptor.Type.StringReverse:
            case FormatDescriptor.Type.StringNullTerm:
            case FormatDescriptor.Type.StringL8:
            case FormatDescriptor.Type.StringL16:
            case FormatDescriptor.Type.StringDci:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputString(offset, labelStr, commentStr);
                break;

            default:
                opcodeStr  = "???";
                operandStr = "***";
                break;
            }

            if (!multiLine)
            {
                opcodeStr = formatter.FormatPseudoOp(opcodeStr);
                OutputLine(labelStr, opcodeStr, operandStr, commentStr);
            }
        }
예제 #14
0
        private static void GenerateInstruction(IGenerator gen, StreamWriter sw,
                                                LocalVariableLookup lvLookup, int offset, int instrBytes, bool doAddCycles)
        {
            DisasmProject proj      = gen.Project;
            Formatter     formatter = gen.SourceFormatter;

            byte[]   data = proj.FileData;
            Anattrib attr = proj.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = gen.Localizer.ConvLabel(attr.Symbol.Label);
            }

            OpDef op       = proj.CpuDef.GetOpDef(data[offset]);
            int   operand  = op.GetOperand(data, offset, attr.StatusFlags);
            int   instrLen = op.GetLength(attr.StatusFlags);

            OpDef.WidthDisambiguation wdis = OpDef.WidthDisambiguation.None;
            if (op.IsWidthPotentiallyAmbiguous)
            {
                wdis = OpDef.GetWidthDisambiguation(instrLen, operand);
            }
            if (gen.Quirks.SinglePassAssembler && wdis == OpDef.WidthDisambiguation.None &&
                (op.AddrMode == OpDef.AddressMode.DP ||
                 op.AddrMode == OpDef.AddressMode.DPIndexX) ||
                op.AddrMode == OpDef.AddressMode.DPIndexY)
            {
                // Could be a forward reference to a direct-page label.  For ACME, we don't
                // care if it's forward or not.
                if ((gen.Quirks.SinglePassNoLabelCorrection && IsLabelReference(gen, offset)) ||
                    IsForwardLabelReference(gen, offset))
                {
                    wdis = OpDef.WidthDisambiguation.ForceDirect;
                }
            }
            if (wdis == OpDef.WidthDisambiguation.ForceLongMaybe &&
                gen.Quirks.SinglePassAssembler &&
                IsForwardLabelReference(gen, offset))
            {
                // Assemblers like cc65 can't tell if a symbol reference is Absolute or
                // Long if they haven't seen the symbol yet.  Irrelevant for ACME, which
                // doesn't currently handle 65816 outside bank 0.
                wdis = OpDef.WidthDisambiguation.ForceLong;
            }

            string opcodeStr = formatter.FormatOpcode(op, wdis);

            string formattedOperand = null;
            int    operandLen       = instrLen - 1;

            PseudoOp.FormatNumericOpFlags opFlags =
                PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix;
            bool isPcRelBankWrap = false;

            // Tweak branch instructions.  We want to show the absolute address rather
            // than the relative offset (which happens with the OperandAddress assignment
            // below), and 1-byte branches should always appear as a 4-byte hex value.
            // Unless we're outside bank 0 on 65816, in which case most assemblers require
            // them to be 6-byte hex values.
            if (op.AddrMode == OpDef.AddressMode.PCRel ||
                op.AddrMode == OpDef.AddressMode.DPPCRel)
            {
                Debug.Assert(attr.OperandAddress >= 0);
                operandLen = 2;
                opFlags   |= PseudoOp.FormatNumericOpFlags.IsPcRel;
            }
            else if (op.AddrMode == OpDef.AddressMode.PCRelLong ||
                     op.AddrMode == OpDef.AddressMode.StackPCRelLong)
            {
                opFlags |= PseudoOp.FormatNumericOpFlags.IsPcRel;
            }
            else if (op.AddrMode == OpDef.AddressMode.Imm ||
                     op.AddrMode == OpDef.AddressMode.ImmLongA ||
                     op.AddrMode == OpDef.AddressMode.ImmLongXY)
            {
                opFlags |= PseudoOp.FormatNumericOpFlags.HasHashPrefix;
            }
            if ((opFlags & PseudoOp.FormatNumericOpFlags.IsPcRel) != 0)
            {
                int branchDist = attr.Address - attr.OperandAddress;
                isPcRelBankWrap = branchDist > 32767 || branchDist < -32768;
            }
            if (op.IsAbsolutePBR)
            {
                opFlags |= PseudoOp.FormatNumericOpFlags.IsAbsolutePBR;
            }
            if (gen.Quirks.BankZeroAbsPBRRestrict)
            {
                // Hack to avoid having to define a new FormatConfig.ExpressionMode for 64tass.
                // Get rid of this 64tass gets its own exp mode.
                opFlags |= PseudoOp.FormatNumericOpFlags.Is64Tass;
            }

            // 16-bit operands outside bank 0 need to include the bank when computing
            // symbol adjustment.
            int operandForSymbol = operand;

            if (attr.OperandAddress >= 0)
            {
                operandForSymbol = attr.OperandAddress;
            }

            // Check Length to watch for bogus descriptors.  (ApplyFormatDescriptors() should
            // now be screening bad descriptors out, so we may not need the Length test.)
            if (attr.DataDescriptor != null && attr.Length == attr.DataDescriptor.Length)
            {
                FormatDescriptor dfd = gen.ModifyInstructionOperandFormat(offset,
                                                                          attr.DataDescriptor, operand);

                // Format operand as directed.
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    // Special handling for the double-operand block move.
                    string opstr1 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                  gen.Localizer.LabelMap, dfd, operand >> 8, 1,
                                                                  PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                    string opstr2 = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                  gen.Localizer.LabelMap, dfd, operand & 0xff, 1,
                                                                  PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                    if (gen.Quirks.BlockMoveArgsReversed)
                    {
                        string tmp = opstr1;
                        opstr1 = opstr2;
                        opstr2 = tmp;
                    }
                    string hash = gen.Quirks.BlockMoveArgsNoHash ? "" : "#";
                    formattedOperand = hash + opstr1 + "," + hash + opstr2;
                }
                else if (op.AddrMode == OpDef.AddressMode.DPPCRel)
                {
                    // Special handling for double-operand BBR/BBS.  The instruction generally
                    // behaves like a branch, so format that first.
                    string branchStr = PseudoOp.FormatNumericOperand(formatter,
                                                                     proj.SymbolTable, gen.Localizer.LabelMap, dfd,
                                                                     operandForSymbol, operandLen, opFlags);
                    string dpStr = formatter.FormatHexValue(operand & 0xff, 2);
                    formattedOperand = dpStr + "," + branchStr;
                }
                else
                {
                    if (attr.DataDescriptor.IsStringOrCharacter)
                    {
                        gen.UpdateCharacterEncoding(dfd);
                    }
                    formattedOperand = PseudoOp.FormatNumericOperand(formatter, proj.SymbolTable,
                                                                     lvLookup, gen.Localizer.LabelMap, dfd,
                                                                     offset, operandForSymbol, operandLen, opFlags);
                }
            }
            else
            {
                // Show operand value in hex.
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    int arg1, arg2;
                    if (gen.Quirks.BlockMoveArgsReversed)
                    {
                        arg1 = operand & 0xff;
                        arg2 = operand >> 8;
                    }
                    else
                    {
                        arg1 = operand >> 8;
                        arg2 = operand & 0xff;
                    }
                    string hash = gen.Quirks.BlockMoveArgsNoHash ? "" : "#";
                    formattedOperand = hash + formatter.FormatHexValue(arg1, 2) + "," +
                                       hash + formatter.FormatHexValue(arg2, 2);
                }
                else if (op.AddrMode == OpDef.AddressMode.DPPCRel)
                {
                    formattedOperand = formatter.FormatHexValue(operand & 0xff, 2) + "," +
                                       formatter.FormatHexValue(operandForSymbol, operandLen * 2);
                }
                else
                {
                    if (operandLen == 2 && !(op.IsAbsolutePBR && gen.Quirks.Need24BitsForAbsPBR) &&
                        (opFlags & PseudoOp.FormatNumericOpFlags.IsPcRel) == 0)
                    {
                        // This is necessary for 16-bit operands, like "LDA abs" and "PEA val",
                        // when outside bank zero.  The bank is included in the operand address,
                        // but we don't want to show it here.  We may need it for JSR/JMP though,
                        // and the bank is required for relative branch instructions.
                        operandForSymbol &= 0xffff;
                    }
                    formattedOperand = formatter.FormatHexValue(operandForSymbol, operandLen * 2);
                }
            }
            string operandStr = formatter.FormatOperand(op, formattedOperand, wdis);

            if (gen.Quirks.StackIntOperandIsImmediate &&
                op.AddrMode == OpDef.AddressMode.StackInt)
            {
                // COP $02 is standard, but some require COP #$02
                operandStr = '#' + operandStr;
            }

            // The BBR/BBS/RMB/SMB instructions include a bit index (0-7).  The standard way is
            // to make it part of the mnemonic, but some assemblers make it an argument.
            if (gen.Quirks.BitNumberIsArg && op.IsNumberedBitOp)
            {
                // Easy way: do some string manipulation.
                char bitIndex = opcodeStr[opcodeStr.Length - 1];
                opcodeStr  = opcodeStr.Substring(0, opcodeStr.Length - 1);
                operandStr = bitIndex.ToString() + "," + operandStr;
            }

            string eolComment = proj.Comments[offset];

            if (doAddCycles)
            {
                bool branchCross = (attr.Address & 0xff00) != (operandForSymbol & 0xff00);
                int  cycles      = proj.CpuDef.GetCycles(op.Opcode, attr.StatusFlags, attr.BranchTaken,
                                                         branchCross);
                if (cycles > 0)
                {
                    if (!string.IsNullOrEmpty(eolComment))
                    {
                        eolComment = cycles.ToString() + "  " + eolComment;
                    }
                    else
                    {
                        eolComment = cycles.ToString();
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(eolComment))
                    {
                        eolComment = (-cycles).ToString() + "+ " + eolComment;
                    }
                    else
                    {
                        eolComment = (-cycles).ToString() + "+";
                    }
                }
            }
            string commentStr = formatter.FormatEolComment(eolComment);

            string replMnemonic = gen.ModifyOpcode(offset, op);

            if (attr.Length != instrBytes)
            {
                // This instruction has another instruction inside it.  Throw out what we
                // computed and just output as bytes.
                // TODO: in some odd situations we can split something that doesn't need
                //   to be split (see note at end of #107).  Working around the problem at
                //   this stage is a little awkward because I think we need to check for the
                //   presence of labels on one or more later lines.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (isPcRelBankWrap && gen.Quirks.NoPcRelBankWrap)
            {
                // Some assemblers have trouble generating PC-relative operands that wrap
                // around the bank.  Output as raw hex.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (op.AddrMode == OpDef.AddressMode.BlockMove &&
                     gen.Quirks.BlockMoveArgsReversed)
            {
                // On second thought, just don't even output the wrong thing.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (replMnemonic == null)
            {
                // No mnemonic exists for this opcode.
                gen.GenerateShortSequence(offset, instrBytes, out opcodeStr, out operandStr);
            }
            else if (replMnemonic != string.Empty)
            {
                // A replacement mnemonic has been provided.
                opcodeStr = formatter.FormatMnemonic(replMnemonic, wdis);
            }
            gen.OutputLine(labelStr, opcodeStr, operandStr, commentStr);

            // Assemblers like Merlin32 try to be helpful and track SEP/REP, but they do the
            // wrong thing if we're in emulation mode.  Force flags back to short.
            if (proj.CpuDef.HasEmuFlag && gen.Quirks.TracksSepRepNotEmu && op == OpDef.OpREP_Imm)
            {
                if ((operand & 0x30) != 0 && attr.StatusFlags.IsEmulationMode)
                {
                    gen.OutputRegWidthDirective(offset, 0, 0, 1, 1);
                }
            }
        }
예제 #15
0
        /// <summary>
        /// Sets the text displayed in the "preview" text box.
        /// </summary>
        private void SetPreviewText()
        {
            //symbolValueLabel.Text = string.Empty;
            mIsSymbolAuto = false;

            FormatDescriptor dfd = CreateDescriptorFromControls();

            if (dfd == null)
            {
                // Default format.  We can't actually know what this look like, so just
                // clear the box.
                previewTextBox.Text = string.Empty;
                return;
            }

            if (dfd.FormatSubType == FormatDescriptor.SubType.Symbol &&
                string.IsNullOrEmpty(dfd.SymbolRef.Label))
            {
                // no label yet, nothing to show
                previewTextBox.Text = string.Empty;
                return;
            }

            StringBuilder preview = new StringBuilder();

            if (mShowHashPrefix)
            {
                preview.Append('#');
            }

            switch (dfd.FormatSubType)
            {
            case FormatDescriptor.SubType.Hex:
                preview.Append(mFormatter.FormatHexValue(mOperandValue, mPreviewHexDigits));
                break;

            case FormatDescriptor.SubType.Decimal:
                preview.Append(mFormatter.FormatDecimalValue(mOperandValue));
                break;

            case FormatDescriptor.SubType.Binary:
                preview.Append(mFormatter.FormatBinaryValue(mOperandValue, 8));
                break;

            case FormatDescriptor.SubType.Ascii:
                preview.Append(mFormatter.FormatAsciiOrHex(mOperandValue));
                break;

            case FormatDescriptor.SubType.Symbol:
                if (mProject.SymbolTable.TryGetValue(dfd.SymbolRef.Label, out Symbol sym))
                {
                    if (mIsBlockMove)
                    {
                        // For a 24-bit symbol, we grab the high byte.  This is the
                        // expected behavior, according to Eyes & Lichty; see the
                        // explanation of the MVP instruction.  For an 8-bit symbol
                        // the assembler just takes the value.
                        // TODO(someday): allow a different symbol for each part of the
                        // operand.
                        if (sym.Value > 0xff)
                        {
                            radioButtonBank.Checked = true;
                        }
                        else
                        {
                            radioButtonLow.Checked = true;
                        }
                        dfd = CreateDescriptorFromControls();
                    }

                    // Hack to make relative branches look right in the preview window.
                    // Otherwise they show up like "<LABEL" because they appear to be
                    // only 8 bits.
                    int operandLen = dfd.Length - 1;
                    if (operandLen == 1 && mIsPcRelative)
                    {
                        operandLen = 2;
                    }
                    PseudoOp.FormatNumericOpFlags flags;
                    if (mIsPcRelative)
                    {
                        flags = PseudoOp.FormatNumericOpFlags.IsPcRel;
                    }
                    else if (mShowHashPrefix)
                    {
                        flags = PseudoOp.FormatNumericOpFlags.HasHashPrefix;
                    }
                    else
                    {
                        flags = PseudoOp.FormatNumericOpFlags.None;
                    }
                    string str = PseudoOp.FormatNumericOperand(mFormatter,
                                                               mProject.SymbolTable, null, dfd,
                                                               mOperandValue, operandLen, flags);
                    preview.Append(str);

                    if (sym.SymbolSource == Symbol.Source.Auto)
                    {
                        mIsSymbolAuto = true;
                    }
                }
                else
                {
                    preview.Append(dfd.SymbolRef.Label + " (?)");
                    Debug.Assert(!string.IsNullOrEmpty(dfd.SymbolRef.Label));
                    //symbolValueLabel.Text = Properties.Resources.MSG_SYMBOL_NOT_FOUND;
                }
                break;

            default:
                Debug.Assert(false);
                preview.Append("BUG");
                break;
            }
            previewTextBox.Text = preview.ToString();
        }
예제 #16
0
        // IGenerator
        public void OutputDataOp(int offset)
        {
            Formatter formatter = SourceFormatter;

            byte[]   data = Project.FileData;
            Anattrib attr = Project.GetAnattrib(offset);

            string labelStr = string.Empty;

            if (attr.Symbol != null)
            {
                labelStr = mLocalizer.ConvLabel(attr.Symbol.Label);
            }

            string commentStr = SourceFormatter.FormatEolComment(Project.Comments[offset]);
            string opcodeStr, operandStr;

            FormatDescriptor dfd = attr.DataDescriptor;

            Debug.Assert(dfd != null);
            int length = dfd.Length;

            Debug.Assert(length > 0);

            bool multiLine = false;

            switch (dfd.FormatType)
            {
            case FormatDescriptor.Type.Default:
                if (length != 1)
                {
                    Debug.Assert(false);
                    length = 1;
                }
                opcodeStr = sDataOpNames.DefineData1;
                int operand = RawData.GetWord(data, offset, length, false);
                operandStr = formatter.FormatHexValue(operand, length * 2);
                break;

            case FormatDescriptor.Type.NumericLE:
                opcodeStr = sDataOpNames.GetDefineData(length);
                operand   = RawData.GetWord(data, offset, length, false);
                if (length == 1 && dfd.IsStringOrCharacter &&
                    ((operand & 0x7f) == '{' || (operand & 0x7f) == '}'))
                {
                    // Merlin32 can't handle "DFB '{'", so just output hex.
                    operandStr = formatter.FormatHexValue(operand, length * 2);
                }
                else
                {
                    operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                               mLocalizer.LabelMap, dfd, operand, length,
                                                               PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                }
                break;

            case FormatDescriptor.Type.NumericBE:
                opcodeStr = sDataOpNames.GetDefineBigData(length);
                if ((string.IsNullOrEmpty(opcodeStr)))
                {
                    // Nothing defined, output as comma-separated single-byte values.
                    GenerateShortSequence(offset, length, out opcodeStr, out operandStr);
                }
                else
                {
                    operand    = RawData.GetWord(data, offset, length, true);
                    operandStr = PseudoOp.FormatNumericOperand(formatter, Project.SymbolTable,
                                                               mLocalizer.LabelMap, dfd, operand, length,
                                                               PseudoOp.FormatNumericOpFlags.OmitLabelPrefixSuffix);
                }
                break;

            case FormatDescriptor.Type.Fill:
                opcodeStr = sDataOpNames.Fill;
                if (data[offset] == 0)
                {
                    operandStr = length.ToString();
                }
                else
                {
                    operandStr = length + "," + formatter.FormatHexValue(data[offset], 2);
                }
                break;

            case FormatDescriptor.Type.Dense:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputDenseHex(offset, length, labelStr, commentStr);
                break;

            case FormatDescriptor.Type.Uninit:
            case FormatDescriptor.Type.Junk:
                int fillVal = Helper.CheckRangeHoldsSingleValue(data, offset, length);
                if (fillVal >= 0)
                {
                    opcodeStr = sDataOpNames.Fill;
                    if (dfd.FormatSubType == FormatDescriptor.SubType.Align256 &&
                        GenCommon.CheckJunkAlign(offset, dfd, Project.AddrMap))
                    {
                        // special syntax for page alignment
                        if (fillVal == 0)
                        {
                            operandStr = "\\";
                        }
                        else
                        {
                            operandStr = "\\," + formatter.FormatHexValue(fillVal, 2);
                        }
                    }
                    else if (length == 1 && fillVal != 0x00)
                    {
                        // Single-byte HEX looks better than "ds 1,$xx", and will match up
                        // with adjacent multi-byte junk/uninit.
                        multiLine = true;
                        opcodeStr = operandStr = null;
                        OutputDenseHex(offset, length, labelStr, commentStr);
                    }
                    else
                    {
                        if (fillVal == 0)
                        {
                            operandStr = length.ToString();
                        }
                        else
                        {
                            operandStr = length + "," + formatter.FormatHexValue(fillVal, 2);
                        }
                    }
                }
                else
                {
                    // treat same as Dense
                    multiLine = true;
                    opcodeStr = operandStr = null;
                    OutputDenseHex(offset, length, labelStr, commentStr);
                }
                break;

            case FormatDescriptor.Type.StringGeneric:
            case FormatDescriptor.Type.StringReverse:
            case FormatDescriptor.Type.StringNullTerm:
            case FormatDescriptor.Type.StringL8:
            case FormatDescriptor.Type.StringL16:
            case FormatDescriptor.Type.StringDci:
                multiLine = true;
                opcodeStr = operandStr = null;
                OutputString(offset, labelStr, commentStr);
                break;

            default:
                opcodeStr  = "???";
                operandStr = "***";
                break;
            }

            if (!multiLine)
            {
                opcodeStr = formatter.FormatPseudoOp(opcodeStr);
                OutputLine(labelStr, opcodeStr, operandStr, commentStr);
            }
        }