Example #1
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);
            }
        }
Example #2
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);
            }
        }
Example #3
0
        // IGenerator
        public void OutputArDirective(CommonUtil.AddressMap.AddressChange change)
        {
            // 64tass separates the "compile offset", which determines where the output fits
            // into the generated binary, and "program counter", which determines the code
            // the assembler generates.  Since we need to explicitly specify every byte in
            // the output file, having a distinct compile offset isn't useful here.  We want
            // to set it once before the first line of code, then leave it alone.
            //
            // Any subsequent ORG changes are made to the program counter, and take the form
            // of a pair of ops (".logical <addr>" to open, ".here" to end).  Omitting the .here
            // causes an error.
            //
            // If this is a "streamable" file, meaning it won't actually load into 64K of RAM
            // without wrapping around, then we skip the "* = addr" (same as "* = 0") and just
            // start with ".logical" segments.
            //
            // The assembler's approach is best represented by having an address region that
            // spans the entire file, with one or more "logical" regions inside.  In practice
            // (especially for multi-bank 65816 code) that may not be the case, but the
            // assembler is still expecting us to start with a "* =" and then fit everything
            // inside that.  So we treat the first region specially, whether or not it wraps
            // the rest of the file.
            Debug.Assert(mPcDepth >= 0);
            int nextAddress = change.Address;

            if (nextAddress == Address.NON_ADDR)
            {
                // Start non-addressable regions at zero to ensure they don't overflow bank.
                nextAddress = 0;
            }
            if (change.IsStart)
            {
                if (change.Region.HasValidPreLabel)
                {
                    string labelStr = mLocalizer.ConvLabel(change.Region.PreLabel);
                    OutputLine(labelStr, string.Empty, string.Empty, string.Empty);
                }
                if (mPcDepth == 0 && mFirstIsOpen)
                {
                    mPcDepth++;

                    // Set the "real" PC for the first address change.  If we're in "loadable"
                    // mode, just set "*=".  If we're in "streaming" mode, we set "*=" to zero
                    // and then use a pseudo-PC.
                    if (mOutputMode == OutputMode.Loadable)
                    {
                        OutputLine("*", "=",
                                   SourceFormatter.FormatHexValue(nextAddress, 4), string.Empty);
                        return;
                    }
                    else
                    {
                        // Set the real PC to address zero to ensure we get a full 64KB.  The
                        // assembler assumes this as a default, so it can be omitted.
                        //OutputLine("*", "=", SourceFormatter.FormatHexValue(0, 4), string.Empty);
                    }
                }

                AddressMap.AddressRegion region = change.Region;
                string addrStr;
                if (region.HasValidIsRelative)
                {
                    int    diff = nextAddress - region.PreLabelAddress;
                    string pfxStr;
                    if (diff >= 0)
                    {
                        pfxStr = "*+";
                    }
                    else
                    {
                        pfxStr = "*-";
                        diff   = -diff;
                    }
                    addrStr = pfxStr + SourceFormatter.FormatHexValue(diff, 4);
                }
                else
                {
                    addrStr = SourceFormatter.FormatHexValue(nextAddress, 4);
                }
                OutputLine(string.Empty,
                           SourceFormatter.FormatPseudoOp(sDataOpNames.ArStartDirective),
                           addrStr,
                           string.Empty);
                mPcDepth++;
            }
            else
            {
                mPcDepth--;
                if (mPcDepth > 0 || !mFirstIsOpen)
                {
                    // close previous block
                    OutputLine(string.Empty,
                               SourceFormatter.FormatPseudoOp(sDataOpNames.ArEndDirective),
                               string.Empty, string.Empty);
                }
                else
                {
                    // mark initial "*=" region as closed, but don't output anything
                    mFirstIsOpen = false;
                }
            }
        }
Example #4
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);
            }
        }
Example #5
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);
            }
        }