2018-09-28 17:05:11 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright 2018 faddenSoft
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
|
|
|
|
|
using Asm65;
|
|
|
|
|
|
|
|
|
|
namespace SourceGen.AsmGen {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Common interface for generating assembler-specific source code.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public interface IGenerator {
|
2018-10-21 23:36:48 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns some strings and format options for use in for the display list, configurable
|
|
|
|
|
/// through the app settings "quick set" feature. These are not used when generating
|
|
|
|
|
/// source code.
|
|
|
|
|
///
|
|
|
|
|
/// This may be called on an unconfigured IGenerator.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="pseudoOps">Table of pseudo-op names.</param>
|
|
|
|
|
/// <param name="formatConfig">Format configuration.</param>
|
|
|
|
|
void GetDefaultDisplayFormat(out PseudoOp.PseudoOpNames pseudoOps,
|
|
|
|
|
out Formatter.FormatConfig formatConfig);
|
|
|
|
|
|
|
|
|
|
|
2018-09-28 17:05:11 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Configure generator. Must be called before calling any other method or using
|
2018-10-21 23:36:48 +00:00
|
|
|
|
/// properties, unless otherwise noted.
|
2018-09-28 17:05:11 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="project">Project to generate source for.</param>
|
|
|
|
|
/// <param name="workDirectory">Directory in which to create output files.</param>
|
|
|
|
|
/// <param name="fileNameBase">Name to use as base for filenames.</param>
|
|
|
|
|
/// <param name="asmVersion">Version of assembler to target. Pass in null
|
|
|
|
|
/// to target latest known version.</param>
|
|
|
|
|
/// <param name="settings">App settings object.</param>
|
|
|
|
|
void Configure(DisasmProject project, string workDirectory, string fileNameBase,
|
|
|
|
|
AssemblerVersion asmVersion, AppSettings settings);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Project object with file data and Anattribs.
|
|
|
|
|
/// </summary>
|
|
|
|
|
DisasmProject Project { get; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Source code formatter.
|
|
|
|
|
/// </summary>
|
|
|
|
|
Formatter SourceFormatter { get; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Application settings.
|
|
|
|
|
/// </summary>
|
|
|
|
|
AppSettings Settings { get; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Assembler-specific behavior. Used to handle quirky behavior for things that
|
|
|
|
|
/// are otherwise managed by common code.
|
|
|
|
|
/// </summary>
|
|
|
|
|
AssemblerQuirks Quirks { get; }
|
|
|
|
|
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Label localization object. Behavior is assembler-specific.
|
|
|
|
|
/// </summary>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
LabelLocalizer Localizer { get; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Generates source files on a background thread. Method must not make any UI calls.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="worker">Async work object, used to report progress updates and
|
|
|
|
|
/// check for cancellation.</param>
|
|
|
|
|
/// <returns>List of pathnames of generated files.</returns>
|
|
|
|
|
List<string> GenerateSource(BackgroundWorker worker);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2018-11-02 20:49:27 +00:00
|
|
|
|
/// Provides an opportunity for the assembler to replace a mnemonic with another, or
|
|
|
|
|
/// output an instruction as hex bytes.
|
2018-09-28 17:05:11 +00:00
|
|
|
|
/// </summary>
|
2018-11-02 20:49:27 +00:00
|
|
|
|
/// <param name="offset">Opcode offset.</param>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="op">Opcode to replace.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
/// <returns>Replacement mnemonic, an empty string if the original is fine, or
|
2018-11-02 20:49:27 +00:00
|
|
|
|
/// null if the op is unsupported or broken and should be emitted as hex.</returns>
|
|
|
|
|
string ModifyOpcode(int offset, OpDef op);
|
2018-09-28 17:05:11 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Generates an opcode/operand pair for a short sequence of bytes (1-4 bytes).
|
|
|
|
|
/// Does not produce any source output.
|
|
|
|
|
/// </summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="offset">Offset to data.</param>
|
|
|
|
|
/// <param name="count">Number of bytes (1-4).</param>
|
|
|
|
|
/// <param name="opcode">Opcode mnemonic.</param>
|
|
|
|
|
/// <param name="operand">Formatted operand.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
void GenerateShortSequence(int offset, int length, out string opcode, out string operand);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Outputs zero or more lines of assembler configuration. This comes after the
|
|
|
|
|
/// header comment but before any directives. Useful for configuring the CPU type
|
|
|
|
|
/// and assembler options.
|
|
|
|
|
/// </summary>
|
|
|
|
|
void OutputAsmConfig();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Outputs one or more lines of data for the specified offset.
|
|
|
|
|
/// </summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="offset">Offset to data.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
void OutputDataOp(int offset);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Outputs an equate directive. The numeric value is already formatted.
|
|
|
|
|
/// </summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="name">Symbol label.</param>
|
|
|
|
|
/// <param name="valueStr">Formatted value.</param>
|
|
|
|
|
/// <param name="comment">End-of-line comment.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
void OutputEquDirective(string name, string valueStr, string comment);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Outputs a code origin directive.
|
|
|
|
|
/// </summary>
|
2018-10-23 23:06:29 +00:00
|
|
|
|
/// <param name="offset">Offset of code targeted to new address.</param>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="address">24-bit address.</param>
|
2018-10-23 23:06:29 +00:00
|
|
|
|
void OutputOrgDirective(int offset, int address);
|
2018-09-28 17:05:11 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Notify the assembler of a change in register width.
|
|
|
|
|
///
|
|
|
|
|
/// Merlin32 always sets both values (e.g. "MX %00"), cc65 sets each register
|
|
|
|
|
/// individually (".A16", ".I8"). We need to accommodate both styles.
|
|
|
|
|
/// </summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="offset">Offset of change.</param>
|
|
|
|
|
/// <param name="prevM">Previous value for M flag.</param>
|
|
|
|
|
/// <param name="prevX">Previous value for X flag.</param>
|
|
|
|
|
/// <param name="newM">New value for M flag.</param>
|
|
|
|
|
/// <param name="newX">New value for X flag.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
void OutputRegWidthDirective(int offset, int prevM, int prevX, int newM, int newX);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// Output a line of source code. All elements must be fully formatted, except for
|
|
|
|
|
/// certain assembler-specific things like ':' on labels. The items will be padded
|
|
|
|
|
/// with spaces to fit specific column widths.
|
2018-09-28 17:05:11 +00:00
|
|
|
|
/// </summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="label">Optional label.</param>
|
|
|
|
|
/// <param name="opcode">Opcode mnemonic.</param>
|
|
|
|
|
/// <param name="operand">Operand; may be empty.</param>
|
|
|
|
|
/// <param name="comment">Optional comment.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
void OutputLine(string label, string opcode, string operand, string comment);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// Output a line of source code. This will be output as-is.
|
2018-09-28 17:05:11 +00:00
|
|
|
|
/// </summary>
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <param name="fullLine">Full text of line to outut.</param>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
void OutputLine(string fullLine);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-02 20:49:27 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Enumeration of quirky or buggy behavior that GenCommon needs to handle.
|
|
|
|
|
/// </summary>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
public class AssemblerQuirks {
|
2018-10-01 22:24:27 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Are the arguments to MVN/MVP reversed?
|
|
|
|
|
/// </summary>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
public bool BlockMoveArgsReversed { get; set; }
|
2018-10-01 22:24:27 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Does the assembler configure assembler widths based on SEP/REP, but doesn't
|
|
|
|
|
/// track the emulation bit?
|
|
|
|
|
/// </summary>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
public bool TracksSepRepNotEmu { get; set; }
|
2018-10-01 22:24:27 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Is the assembler unable to generate relative branches that wrap around banks?
|
|
|
|
|
/// (Note this affects long-distance BRLs that don't appear to wrap.)
|
|
|
|
|
/// </summary>
|
2018-09-28 17:05:11 +00:00
|
|
|
|
public bool NoPcRelBankWrap { get; set; }
|
|
|
|
|
}
|
|
|
|
|
}
|