diff --git a/CommonUtil/AddressMap.cs b/CommonUtil/AddressMap.cs
index 8062789..2223a4f 100644
--- a/CommonUtil/AddressMap.cs
+++ b/CommonUtil/AddressMap.cs
@@ -39,18 +39,19 @@ namespace CommonUtil {
/// There are three basic API modes:
/// (1) Structural. Add, modify, and remove regions. Needed by the "edit region" dialog.
/// This matches exactly with the contents of the project file.
- /// (2) Hierarchical. Used when converting an offset to an address, which can't be
+ /// (2) Hierarchical. Used when converting an address to an offset, which can't be
/// accomplished with a simple map because we need to take into account the offset of
- /// the reference. The tree best represents the relationship between regions.
+ /// the reference, and when determining the address of an offset. The tree best
+ /// represents the relationship between regions.
/// (3) Linear. When generating assembly sources or the display list, we need to identify
/// the lines that have an address change event (even if the address doesn't change).
/// This will be done as we walk through the code. For easy interaction with an
/// iterator, we flatten it out.
///
/// These are different enough that it's best to use three different data structures. The
- /// list of regions is the primary structure, and the other two are generated from it. Changes
- /// to the map are very infrequent, and analyzing the file contents may hit the map
- /// frequently, so we want to optimize for "read" accesses.
+ /// structural list of regions is the primary structure, and the other two are generated from
+ /// it. Changes to the map are very infrequent, and analyzing the file contents may hit
+ /// the map frequently, so we want to optimize for "read" accesses.
///
/// A region can be uniquely identified by {offset,length}. There can be multiple regions
/// starting at a given offset, or ending at a given offset, but we disallow regions that
@@ -120,6 +121,16 @@ namespace CommonUtil {
///
public string PreLabel { get; private set; }
+ ///
+ /// Should we prevent address resolution from entering this region?
+ ///
+ public bool DisallowInward { get; private set; }
+
+ ///
+ /// Should we prevent address resolution from traversing outside this region?
+ ///
+ public bool DisallowOutward { get; private set; }
+
///
/// Should we try to generate the directive with an operand that is relative to
/// the current PC?
@@ -130,20 +141,31 @@ namespace CommonUtil {
public bool IsRelative { get; private set; }
///
- /// Constructor.
+ /// Simple constructor.
///
- public AddressMapEntry(int offset, int len, int addr, string preLabel, bool isRelative) {
+ public AddressMapEntry(int offset, int len, int addr)
+ : this(offset, len, addr, string.Empty, false, false, false)
+ { }
+
+ ///
+ /// Full constructor.
+ ///
+ public AddressMapEntry(int offset, int len, int addr, string preLabel,
+ bool disallowInward, bool disallowOutward, bool isRelative) {
Offset = offset;
Length = len;
Address = addr;
PreLabel = preLabel;
+ DisallowInward = disallowInward;
+ DisallowOutward = disallowOutward;
IsRelative = isRelative;
}
public override string ToString() {
return "[AddrMapEnt: +" + Offset.ToString("x6") + " len=$" + Length.ToString("x4") +
" addr=$" + Address.ToString("x4") + " preLab='" + PreLabel +
- "' isRel=" + IsRelative + "]";
+ "' disIn=" + DisallowInward + " disOut=" + DisallowOutward +
+ " isRel=" + IsRelative + "]";
}
public static bool operator ==(AddressMapEntry a, AddressMapEntry b) {
@@ -155,7 +177,8 @@ namespace CommonUtil {
}
// All fields must be equal.
return a.Offset == b.Offset && a.Length == b.Length && a.Address == b.Address &&
- a.PreLabel == b.PreLabel && a.IsRelative == b.IsRelative;
+ a.PreLabel == b.PreLabel && a.DisallowInward == b.DisallowInward &&
+ a.DisallowOutward == b.DisallowOutward && a.IsRelative == b.IsRelative;
}
public static bool operator !=(AddressMapEntry a, AddressMapEntry b) {
return !(a == b);
@@ -164,7 +187,8 @@ namespace CommonUtil {
return obj is AddressMapEntry && this == (AddressMapEntry)obj;
}
public override int GetHashCode() {
- return Offset ^ Length ^ Address ^ PreLabel.GetHashCode() ^ (IsRelative ? 1 : 0);
+ return Offset ^ Length ^ Address ^ PreLabel.GetHashCode() ^
+ (DisallowInward ? 1 : 0) ^ (DisallowOutward ? 2 : 0) ^ (IsRelative ? 4 : 0);
}
}
@@ -225,9 +249,11 @@ namespace CommonUtil {
///
/// Full constructor.
///
- public AddressRegion(int offset, int len, int addr, string preLabel, bool isRelative,
+ public AddressRegion(int offset, int len, int addr, string preLabel,
+ bool disallowInward, bool disallowOutward, bool isRelative,
int actualLen, int preLabelAddr)
- : base(offset, len, addr, preLabel, isRelative) {
+ : base(offset, len, addr, preLabel, disallowInward, disallowOutward, isRelative)
+ {
ActualLength = actualLen;
PreLabelAddress = preLabelAddr;
@@ -238,13 +264,14 @@ namespace CommonUtil {
/// Basic constructor. Not for use when len==FLOATING_LEN.
///
public AddressRegion(int offset, int len, int addr)
- : this(offset, len, addr, string.Empty, false, len, NON_ADDR) {
+ : this(offset, len, addr, string.Empty, false, false, false, len, NON_ADDR) {
Debug.Assert(len != FLOATING_LEN);
}
public override string ToString() {
- return "[AddrRegion: +" + Offset.ToString("x6") + " len=$" +
- Length.ToString("x4") + " addr=$" + Address.ToString("x4") +
+ return "[AddrRegion: +" + Offset.ToString("x6") +
+ " len=" + (Length == FLOATING_LEN ? "float" : "$" + Length.ToString("x4")) +
+ " addr=" + (Address == NON_ADDR ? "NA" : "$" + Address.ToString("x4")) +
" actualLen=$" + ActualLength.ToString("x4") + " isRel=" + IsRelative + "]";
}
}
@@ -283,7 +310,7 @@ namespace CommonUtil {
foreach (AddressMapEntry ent in entries) {
// TODO(maybe): suppress Regenerate() call in AddEntry while we work
AddResult result = AddEntry(ent.Offset, ent.Length, ent.Address, ent.PreLabel,
- ent.IsRelative);
+ ent.DisallowInward, ent.DisallowOutward, ent.IsRelative);
if (result != AddResult.Okay) {
throw new Exception("Unable to add entry (" + result + "): " + ent);
}
@@ -360,16 +387,20 @@ namespace CommonUtil {
///
///
/// We need to verify:
- /// - offset >= 0
- /// - offset < total length of file
- /// - either length is floating, or:
- /// - length > 0
- /// - length < total length of file
- /// - offset + length < total length of file
- /// - either address is NON_ADDR, or:
- /// - addr > 0
- /// - addr <= ADDR_MAX
- /// - preLabel is not null
+ ///
+ /// - offset >= 0
+ /// - offset < total length of file
+ /// - either length is floating, or:
+ /// - length > 0
+ /// - length < total length of file
+ /// - offset + length < total length of file
+ ///
+ /// - either address is NON_ADDR, or:
+ /// - addr > 0
+ /// - addr <= ADDR_MAX
+ ///
+ /// - preLabel is not null
+ ///
///
/// We might want to limit the length to fit within a single 64K bank, unless it's
/// a non-addressable region. That would probably be better as a warning than an error.
@@ -390,7 +421,7 @@ namespace CommonUtil {
/// Address of region start.
/// Failure code.
public AddResult AddEntry(int offset, int length, int addr) {
- return AddEntry(offset, length, addr, string.Empty, false);
+ return AddEntry(offset, length, addr, string.Empty, false, false, false);
}
///
@@ -402,7 +433,7 @@ namespace CommonUtil {
// Slightly inefficient to extract the fields and reassemble them, which we can
// avoid since instances are immutable, but it's not worth coding around.
return AddEntry(entry.Offset, entry.Length, entry.Address, entry.PreLabel,
- entry.IsRelative);
+ entry.DisallowInward, entry.DisallowOutward, entry.IsRelative);
}
///
@@ -412,11 +443,15 @@ namespace CommonUtil {
/// Length of region, or FLOATING_LEN for a floating end point.
/// Address of region start.
/// Pre-region label.
+ /// True if address resolution should not enter this
+ /// region.
+ /// True if address resolution should not traverse outside
+ /// of this region.
/// True if code generator should output relative
/// assembler directive operand.
/// Failure code.
public AddResult AddEntry(int offset, int length, int addr, string preLabel,
- bool isRelative) {
+ bool disallowInward, bool disallowOutward, bool isRelative) {
if (!ValidateArgs(offset, length, addr, preLabel)) {
Debug.WriteLine("AddEntry: invalid arg");
return AddResult.InvalidValue;
@@ -425,7 +460,7 @@ namespace CommonUtil {
AddResult result = FindAddIndex(offset, length, out insIdx);
if (result == AddResult.Okay) {
AddressMapEntry newEntry = new AddressMapEntry(offset, length, addr,
- preLabel, isRelative);
+ preLabel, disallowInward, disallowOutward, isRelative);
mMapEntries.Insert(insIdx, newEntry);
Regenerate();
}
@@ -678,6 +713,11 @@ namespace CommonUtil {
Parent = parent;
// all other fields null/false
}
+
+ public override string ToString() {
+ return "[TreeNode children=" + Children.Count +
+ ", Region=" + Region.ToString() + "]";
+ }
}
///
@@ -696,7 +736,7 @@ namespace CommonUtil {
// explicitly is caught here. It also avoids the need to special-case the top
// part of the file.
AddressRegion globalReg = new AddressRegion(0, mSpanLength, NON_ADDR, string.Empty,
- false, mSpanLength, NON_ADDR);
+ false, false, false, mSpanLength, NON_ADDR);
TreeNode topNode = new TreeNode(globalReg, null);
// Generate the children of this node.
@@ -753,7 +793,8 @@ namespace CommonUtil {
}
}
AddressRegion fixedReg = new AddressRegion(childEnt.Offset,
- FLOATING_LEN, childEnt.Address, childEnt.PreLabel, childEnt.IsRelative,
+ FLOATING_LEN, childEnt.Address, childEnt.PreLabel,
+ childEnt.DisallowInward, childEnt.DisallowOutward, childEnt.IsRelative,
nextStart - childEnt.Offset, preLabelAddr);
children.Add(new TreeNode(fixedReg, parent));
@@ -762,7 +803,8 @@ namespace CommonUtil {
// Add this region to the list, and check for descendants.
AddressRegion newReg = new AddressRegion(childEnt.Offset,
childEnt.Length, childEnt.Address, childEnt.PreLabel,
- childEnt.IsRelative, childEnt.Length, preLabelAddr);
+ childEnt.DisallowInward, childEnt.DisallowOutward, childEnt.IsRelative,
+ childEnt.Length, preLabelAddr);
TreeNode thisNode = new TreeNode(newReg, parent);
children.Add(thisNode);
@@ -833,7 +875,12 @@ namespace CommonUtil {
return offset;
}
- // Didn't find it. Move up one level, but ignore the branch we've already checked.
+ if (startNode.Region.DisallowOutward) {
+ return -1; // can't look at parent or siblings of this node
+ }
+
+ // Didn't find it. Move up one level, but ignore the branch we've already checked
+ // (for efficiency). We need to start checking the "disallow inward" flag.
ignoreNode = startNode;
startNode = startNode.Parent;
if (startNode == null) {
@@ -851,11 +898,18 @@ namespace CommonUtil {
/// Address to find.
/// Offset, or -1 if not found.
private int FindAddress(TreeNode node, TreeNode ignore, int targetAddr) {
+ // We can ignore the DisallowInward flag on the current node, because we're already
+ // in it. We don't want to descend into a child with the flag set. (It's okay to
+ // ascend into a parent that has it set, but that's not handled here.)
+
if (node.Children != null) {
foreach (TreeNode childNode in node.Children) {
if (childNode == ignore) {
continue;
}
+ if (childNode.Region.DisallowInward) {
+ continue; // can't look at siblings with DisallowInward set
+ }
int offset = FindAddress(childNode, null, targetAddr);
if (offset >= 0) {
// Found match in child, return that.
@@ -876,7 +930,8 @@ namespace CommonUtil {
}
// We span the correct range of addresses. See if the requested address
- // falls into a hole spanned by a child.
+ // falls into a hole spanned by a child. (This is independent of DisallowInward,
+ // since it's a hole in the address space whether we look at it or not.)
if (node.Children != null) {
int subPosn = targetAddr - region.Address; // position of target inside node
foreach (TreeNode childNode in node.Children) {
@@ -923,7 +978,8 @@ namespace CommonUtil {
}
///
- /// Recursively descends into the tree to find the node that contains the offset.
+ /// Recursively descends into the tree to find the node that contains the offset. The
+ /// deepest child node that spans the offset will be returned.
///
/// File offset.
/// Node to examine.
@@ -1260,6 +1316,12 @@ namespace CommonUtil {
if (change.IsSynthetic) {
sb.Append(" (auto-generated)");
}
+ if (change.Region.DisallowInward) {
+ sb.Append(" [!in]");
+ }
+ if (change.Region.DisallowOutward) {
+ sb.Append(" [!out]");
+ }
sb.Append(CRLF);
prevOffset = change.Offset;
@@ -1330,6 +1392,9 @@ namespace CommonUtil {
#region Unit tests
+ // Unit test primitives. Set "result" to true at start of test; these will set it to
+ // false on failure.
+
private static void Test_Expect(AddResult expected, ref bool result, AddResult actual) {
if (expected != actual) {
Debug.WriteLine("test failed (expected=" + expected + ", actual=" + actual + ")");
@@ -1342,7 +1407,6 @@ namespace CommonUtil {
result = false;
}
}
-
private static void Test_Expect(int expected, ref bool result, int actual) {
if (expected != actual) {
Debug.WriteLine("test failed (expected=$" + expected.ToString("x4") + "/" +
@@ -1351,12 +1415,14 @@ namespace CommonUtil {
}
}
+ // Test equality and hashcode ops on AddressMapEntry.
private static bool Test_Primitives() {
bool result = true;
- AddressMapEntry ent1 = new AddressMapEntry(0, 1, 2, "three", true);
- AddressMapEntry ent2 = new AddressMapEntry(0, 1, 2, "three", true);
- AddressMapEntry ent3 = new AddressMapEntry(0, 1, 2, "three-A", true);
+ AddressMapEntry ent1 = new AddressMapEntry(0, 1, 2, "three", false, false, true);
+ AddressMapEntry ent2 = new AddressMapEntry(0, 1, 2, "three", false, false, true);
+ AddressMapEntry ent3 = new AddressMapEntry(0, 1, 2, "three-A", false, false, true);
+ AddressMapEntry ent4 = new AddressMapEntry(0, 1, 2, "three-A", false, true, true);
result &= ent1 == ent2;
result &= ent1 != ent3;
@@ -1364,11 +1430,14 @@ namespace CommonUtil {
Test_Expect(true, ref result, result);
AddressRegion reg1 = new AddressRegion(ent1.Offset, ent1.Length, ent1.Address,
- ent1.PreLabel, ent1.IsRelative, ent1.Length, 0);
+ ent1.PreLabel, ent1.DisallowInward, ent1.DisallowOutward, ent1.IsRelative,
+ ent1.Length, 0);
AddressRegion reg2 = new AddressRegion(ent2.Offset, ent2.Length, ent2.Address,
- ent2.PreLabel, ent2.IsRelative, ent2.Length, 0);
+ ent2.PreLabel, ent2.DisallowInward, ent2.DisallowOutward, ent2.IsRelative,
+ ent2.Length, 0);
AddressRegion reg3 = new AddressRegion(ent3.Offset, ent3.Length, ent3.Address,
- ent3.PreLabel, ent3.IsRelative, ent3.Length, 0);
+ ent3.PreLabel, ent3.DisallowInward, ent3.DisallowOutward, ent3.IsRelative,
+ ent3.Length, 0);
result &= reg1 == reg2;
result &= reg1 == ent1;
@@ -1377,33 +1446,37 @@ namespace CommonUtil {
result &= reg3 != ent1;
result &= reg1.Equals(ent2);
result &= ent3 != reg1;
+ result &= ent3 != ent4;
Test_Expect(true, ref result, result);
result &= ent1.GetHashCode() == ent2.GetHashCode();
result &= ent2.GetHashCode() != ent3.GetHashCode();
+ result &= ent3.GetHashCode() != ent4.GetHashCode();
Test_Expect(true, ref result, result);
return result;
}
+ // Test the AddressMap FindRegion() method.
private static bool Test_Find() {
const int mapLen = 0x1000;
AddressMap map = new AddressMap(mapLen);
bool result = true;
- const int off0 = 0x000100;
+ // Map with three nested regions.
+ const int off0 = 0x000100; // region 0: +000100-000fff $2100-$2fff
const int len0 = 0x0f00;
const int adr0 = 0x2100;
- const int off1 = 0x000200;
+ const int off1 = 0x000200; // region 1: +000200-0005ff $2200-$25ff
const int len1 = 0x0400;
const int adr1 = 0x2200;
- const int off2 = 0x000400;
+ const int off2 = 0x000400; // region 2: +000400-0005ff* $2400-25ff
const int len2 = FLOATING_LEN;
const int adr2 = 0x2400;
- AddressMapEntry ent0 = new AddressMapEntry(off0, len0, adr0, string.Empty, false);
- AddressMapEntry ent1 = new AddressMapEntry(off1, len1, adr1, string.Empty, false);
- AddressMapEntry ent2 = new AddressMapEntry(off2, len2, adr2, string.Empty, false);
+ AddressMapEntry ent0 = new AddressMapEntry(off0, len0, adr0);
+ AddressMapEntry ent1 = new AddressMapEntry(off1, len1, adr1);
+ AddressMapEntry ent2 = new AddressMapEntry(off2, len2, adr2);
Test_Expect(AddResult.Okay, ref result, map.AddEntry(ent0));
Test_Expect(AddResult.Okay, ref result, map.AddEntry(ent1));
Test_Expect(AddResult.Okay, ref result, map.AddEntry(ent2));
@@ -1425,18 +1498,20 @@ namespace CommonUtil {
return result;
}
+ // Test basic behavior in a simple linear map.
private static bool Test_SimpleLinear() {
const int mapLen = 0x8000;
AddressMap map = new AddressMap(mapLen);
bool result = true;
- const int off0 = 0x000000;
+ // Simple map with no gaps at start or between.
+ const int off0 = 0x000000; // region 0: +000000-0001ff $1000-$11ff
const int len0 = 0x0200;
const int adr0 = 0x1000;
- const int off1 = 0x000200;
+ const int off1 = 0x000200; // region 1: +000200-0006ff $1200-$16ff
const int len1 = 0x0500;
const int adr1 = 0x1200;
- const int off2 = 0x000700;
+ const int off2 = 0x000700; // region 3: +000700-0009ff $1700-$19ff
const int len2 = 0x0300;
const int adr2 = 0x1700;
@@ -1465,6 +1540,7 @@ namespace CommonUtil {
Test_Expect(true, ref result, map.RemoveEntry(off0, mapLen));
Test_Expect(false, ref result, map.RemoveEntry(off0, mapLen));
+ // Check some address mappings.
Test_Expect(adr0, ref result, map.OffsetToAddress(off0));
Test_Expect(adr1, ref result, map.OffsetToAddress(off1));
Test_Expect(adr2, ref result, map.OffsetToAddress(off2));
@@ -1487,25 +1563,26 @@ namespace CommonUtil {
return result;
}
+ // Test with floating region, and region with non-addressable gap.
private static bool Test_SimpleFloatGap() {
const int mapLen = 0x8000;
AddressMap map = new AddressMap(mapLen);
bool result = true;
- const int off0 = 0x001000;
+ // Map has a non-addressable gap at the start; region #2 is nested non-addr.
+ // Regions 0 and 1 have overlapping address spaces.
+ const int off0 = 0x001000; // region 0: +001000-003fff* $1000-$3fff
const int len0 = FLOATING_LEN;
const int adr0 = 0x1000;
- const int off1 = 0x004000;
+ const int off1 = 0x004000; // region 1: +004000-006fff $1200-51ff
const int len1 = 0x3000;
const int adr1 = 0x1200;
- const int off2 = 0x005000;
+ const int off2 = 0x005000; // region 2: +005000-0050ff N/A
const int len2 = 0x0100;
const int adr2 = NON_ADDR;
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(off0, len0, adr0));
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(off1, len1, adr1));
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(off0, len0, adr0));
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(off1, len1, adr1));
// Try to remove the implicit no-address zone.
Test_Expect(false, ref result, map.RemoveEntry(0, off0));
@@ -1534,42 +1611,43 @@ namespace CommonUtil {
return result;
}
+ // Test construction with various nesting scenarios.
private static bool Test_Nested() {
AddressMap map = new AddressMap(0x8000);
bool result = true;
// Nested with shared start offset.
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000100, 0x0400, 0x4000, "preA0", false));
+ map.AddEntry(0x000100, 0x0400, 0x4000, "preA0", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000100, 0x0100, 0x7000, "preA1", false));
+ map.AddEntry(0x000100, 0x0100, 0x7000, "preA1", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000100, 0x0300, 0x5000, "preA2", false));
+ map.AddEntry(0x000100, 0x0300, 0x5000, "preA2", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000100, 0x0200, 0x6000, "preA3", false));
+ map.AddEntry(0x000100, 0x0200, 0x6000, "preA3", false, false, false));
// Add a couple of floaters.
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x0000ff, FLOATING_LEN, 0x30ff, "preA4", false));
+ map.AddEntry(0x0000ff, FLOATING_LEN, 0x30ff, "preA4", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000101, FLOATING_LEN, 0x3101, "preA5", false));
+ map.AddEntry(0x000101, FLOATING_LEN, 0x3101, "preA5", false, false, false));
Test_Expect(AddResult.OverlapFloating, ref result,
- map.AddEntry(0x000100, FLOATING_LEN, 0x3100, "preA6", false));
+ map.AddEntry(0x000100, FLOATING_LEN, 0x3100, "preA6", false, false, false));
// Nested with shared end offset.
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000fff, FLOATING_LEN, 0x3fff, "preB0", false));
+ map.AddEntry(0x000fff, FLOATING_LEN, 0x3fff, "preB0", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x001200, 0x0200, 0x6000, "preB1", false));
+ map.AddEntry(0x001200, 0x0200, 0x6000, "preB1", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x001000, 0x0400, 0x4000, "preB2", false));
+ map.AddEntry(0x001000, 0x0400, 0x4000, "preB2", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x001100, 0x0300, 0x5000, "preB3", false));
+ map.AddEntry(0x001100, 0x0300, 0x5000, "preB3", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x001300, 0x0100, 0x7000, "preB4", false));
+ map.AddEntry(0x001300, 0x0100, 0x7000, "preB4", false, false, false));
// Single-byte region at start and end.
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x001200, 1, 0x8200, "preB5", false));
+ map.AddEntry(0x001200, 1, 0x8200, "preB5", false, false, false));
Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x0013ff, 1, 0x83ff, "preB6", false));
+ map.AddEntry(0x0013ff, 1, 0x83ff, "preB6", false, false, false));
// Nested with no common edge, building from outside-in.
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002000, 0x0800, 0x4000));
@@ -1607,20 +1685,27 @@ namespace CommonUtil {
return result;
}
+ // Look up addresses from different initial regions.
private static bool Test_Cross() {
const int mapLen = 0x4000;
AddressMap map = new AddressMap(mapLen);
bool result = true;
+ // Region 0: +000000-001fff $8000-9fff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x2000, 0x8000));
+ // Region 1: +002000-003fff $8000-9fff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002000, 0x2000, 0x8000));
+ // Region 2: +002100-0022ff $e100-e2ff (overlaps with region 1).
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002100, 0x0200, 0xe100));
+ // Region 3: +003100-0032ff $f100-f2ff (overlaps with region 1).
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x003100, 0x0200, 0xf100));
+ // Look up address in region 3, from different regions.
Test_Expect(0x003105, ref result, map.AddressToOffset(0x000000, 0xf105));
Test_Expect(0x003105, ref result, map.AddressToOffset(0x002100, 0xf105));
Test_Expect(0x003105, ref result, map.AddressToOffset(0x003100, 0xf105));
+ // Look up address in region 2, from different regions.
Test_Expect(0x002105, ref result, map.AddressToOffset(0x000000, 0xe105));
Test_Expect(0x002105, ref result, map.AddressToOffset(0x002100, 0xe105));
Test_Expect(0x002105, ref result, map.AddressToOffset(0x003100, 0xe105));
@@ -1643,28 +1728,29 @@ namespace CommonUtil {
return result;
}
+ // Test resolution across nested regions with no shared start/end.
private static bool Test_Pyramids() {
const int mapLen = 0xc000;
AddressMap map = new AddressMap(mapLen);
bool result = true;
- // Pyramid shape, all regions start at same address except last.
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x000000, 0x6000, 0x8000));
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x001000, 0x4000, 0x8000));
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x002000, 0x2000, 0x7fff));
+ // Nested pyramid shape, all regions start at same address except last.
+ // Region 0: +000000-005fff $8000-dfff
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x6000, 0x8000));
+ // Region 1: +001000-005fff $8000-bfff
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x001000, 0x4000, 0x8000));
+ // Region 2: +002000-003fff $7fff-9ffe
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x002000, 0x2000, 0x7fff));
// Second pyramid.
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x006000, 0x6000, 0x8000));
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x007000, 0x4000, 0x8000));
- Test_Expect(AddResult.Okay, ref result,
- map.AddEntry(0x008000, 0x2000, 0x8000));
+ // Region 3: +006000-00bfff $8000-dfff
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x006000, 0x6000, 0x8000));
+ // Region 4: +007000-00afff $8000-bfff
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x007000, 0x4000, 0x8000));
+ // Region 5: +008000-009fff $8000-9fff
+ Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x008000, 0x2000, 0x8000));
- // Children take priority over the start node.
+ // Children take priority over the start node. These all resolve in region 2.
Test_Expect(0x002001, ref result, map.AddressToOffset(0x000000, 0x8000));
Test_Expect(0x003000, ref result, map.AddressToOffset(0x000000, 0x8fff));
Test_Expect(0x002001, ref result, map.AddressToOffset(0x001000, 0x8000));
@@ -1672,19 +1758,26 @@ namespace CommonUtil {
Test_Expect(0x002001, ref result, map.AddressToOffset(0x002000, 0x8000));
Test_Expect(0x002000, ref result, map.AddressToOffset(0x000000, 0x7fff));
+ // These resolve in region 0.
Test_Expect(0x005000, ref result, map.AddressToOffset(0x000000, 0xd000));
Test_Expect(0x005000, ref result, map.AddressToOffset(0x003000, 0xd000));
+ // These fail because $c000-cfff only exists in region 0, and maps to
+ // offsets +004000-004fff, but region 1 (its child) spans the same range
+ // of offsets with different addresses.
Test_Expect(-1, ref result, map.AddressToOffset(0x000000, 0xc000));
Test_Expect(-1, ref result, map.AddressToOffset(0x000000, 0xcfff));
+ // These resolve in region 5.
Test_Expect(0x008000, ref result, map.AddressToOffset(0x006000, 0x8000));
Test_Expect(0x008000, ref result, map.AddressToOffset(0x007000, 0x8000));
Test_Expect(0x008000, ref result, map.AddressToOffset(0x008000, 0x8000));
Test_Expect(0x008000, ref result, map.AddressToOffset(0x00bfff, 0x8000));
- // $7fff doesn't exist in second chunk, so we have to go back to first to find it.
+ // $7fff doesn't exist in second pyramid, so we have to go back to first to find it.
Test_Expect(0x002000, ref result, map.AddressToOffset(0x008000, 0x7fff));
+ // Address $a000 exists in region 4, at offset +009000, but that's overlapped
+ // by region 5 (its child) with a different address.
Test_Expect(-1, ref result, map.AddressToOffset(0x008000, 0xa000));
// inside
@@ -1703,28 +1796,38 @@ namespace CommonUtil {
return result;
}
+ // Test some region overlap edge cases.
private static bool Test_OddOverlap() {
const int mapLen = 0x1000;
AddressMap map = new AddressMap(mapLen);
bool result = true;
- // Top region spans full map.
+ // Top region spans full map. +000000-000fff $1000-1fff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, mapLen, 0x1000));
- // Parent region covers next two.
+ // Parent region covers next two. +000000-0003ff $1000-13ff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000000, 0x0400, 0x1000));
- // Floating region.
+ // Floating region. +000100-0001ff* $2000-20ff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000100, FLOATING_LEN, 0x2000));
- // Fixed region follows.
+ // Fixed region follows. +000200-0002ff $3000-30ff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000200, 0x0100, 0x3000));
- //string mapStr = map.FormatAddressMap(); // DEBUG - format the map and
- //Debug.WriteLine(mapStr); // DEBUG - print it to the console
+
+ Test_Expect(0x00017f, ref result, map.AddressToOffset(0x000000, 0x207f));
+ Test_Expect(0x00027f, ref result, map.AddressToOffset(0x000000, 0x307f));
+ Test_Expect(0x000180, ref result, map.AddressToOffset(0x000000, 0x2080));
// Add a region that starts in the middle of the floating region (becoming
// a sibling), and ends after the fixed region (becoming its parent).
+ // +000180-00037f $4000-41ff
Test_Expect(AddResult.Okay, ref result, map.AddEntry(0x000180, 0x0200, 0x4000));
- // Remove it.
+
+ Test_Expect(0x00017f, ref result, map.AddressToOffset(0x000000, 0x207f));
+ Test_Expect(0x00027f, ref result, map.AddressToOffset(0x000000, 0x307f));
+ Test_Expect(-1, ref result, map.AddressToOffset(0x000000, 0x2080));
+
+ // Remove the region we just added. The float region should flex back out.
Test_Expect(true, ref result, map.RemoveEntry(0x000180, 0x0200));
+ Test_Expect(0x000180, ref result, map.AddressToOffset(0x000000, 0x2080));
// Add a region that starts in the middle of the floating region and ends after
// the parent. Since this crosses the parent's end boundary and doesn't share
@@ -1736,6 +1839,151 @@ namespace CommonUtil {
return result;
}
+ // Test interaction between isolated regions.
+ private static bool Test_Isolation() {
+ const int mapLen = 0x8000;
+ bool result = true;
+
+ const int off0 = 0x001000; // region 0: +001000-003fff $1000-$3fff
+ const int len0 = 0x3000;
+ const int adr0 = 0x1000;
+ const int off1 = 0x002000; // region 1: +002000-002fff $2000-$2fff
+ const int len1 = 0x1000;
+ const int adr1 = 0x2000;
+ const int off2 = 0x004000; // region 2: +004000-006fff $4000-$6fff
+ const int len2 = 0x3000;
+ const int adr2 = 0x4000;
+ const int off3 = 0x005000; // region 3: +005000-005fff $8000-$8fff
+ const int len3 = 0x1000;
+ const int adr3 = 0x8000;
+
+ // Map: all open
+ AddressMap map = new AddressMap(mapLen);
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off1, len1, adr1, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off3, len3, adr3, string.Empty, false, false, false));
+
+ Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x5005)); // hole
+
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
+
+ // Map: inner regions 1 and 3 disallow inward
+ map = new AddressMap(mapLen);
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off1, len1, adr1, string.Empty, true, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off3, len3, adr3, string.Empty, true, false, false));
+
+ Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
+ Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
+
+ // Map: inner regions 1 and 3 disallow outward
+ map = new AddressMap(mapLen);
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off1, len1, adr1, string.Empty, false, true, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off3, len3, adr3, string.Empty, false, true, false));
+
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
+
+ // Map: region 0 disallows inward and outward
+ map = new AddressMap(mapLen);
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off0, len0, adr0, string.Empty, true, true, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off1, len1, adr1, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off3, len3, adr3, string.Empty, false, false, false));
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x001000, 0x1005)); // 0 -> 0
+
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
+ Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
+ Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
+
+ // Map: region 3 disallows inward and outward
+ map = new AddressMap(mapLen);
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off0, len0, adr0, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off1, len1, adr1, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off2, len2, adr2, string.Empty, false, false, false));
+ Test_Expect(AddResult.Okay, ref result,
+ map.AddEntry(off3, len3, adr3, string.Empty, true, true, false));
+ Test_Expect(0x005005, ref result, map.AddressToOffset(0x005000, 0x8005)); // 3 -> 3
+
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x001000, 0x2005)); // 0 -> 1
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x001000, 0x4005)); // 0 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x001000, 0x8005)); // 0 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x002000, 0x1005)); // 1 -> 0
+ Test_Expect(0x004005, ref result, map.AddressToOffset(0x002000, 0x4005)); // 1 -> 2
+ Test_Expect(-1, ref result, map.AddressToOffset(0x002000, 0x8005)); // 1 -> 3
+ Test_Expect(0x001005, ref result, map.AddressToOffset(0x004000, 0x1005)); // 2 -> 0
+ Test_Expect(0x002005, ref result, map.AddressToOffset(0x004000, 0x2005)); // 2 -> 1
+ Test_Expect(-1, ref result, map.AddressToOffset(0x004000, 0x8005)); // 2 -> 3
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x1005)); // 3 -> 0
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x2005)); // 3 -> 1
+ Test_Expect(-1, ref result, map.AddressToOffset(0x005000, 0x4005)); // 3 -> 2
+
+ return result;
+ }
+
public static bool Test() {
bool ok = true;
ok &= Test_Primitives();
@@ -1746,6 +1994,11 @@ namespace CommonUtil {
ok &= Test_Cross();
ok &= Test_Pyramids();
ok &= Test_OddOverlap();
+ ok &= Test_Isolation();
+
+ // Do this to get a visualization:
+ //string mapStr = map.FormatAddressMap(); // DEBUG - format the map and
+ //Debug.WriteLine(mapStr); // DEBUG - print it to the console
Debug.WriteLine("AddressMap: test complete (ok=" + ok + ")");
return ok;
diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs
index 2dfd03e..5f36b13 100644
--- a/SourceGen/MainController.cs
+++ b/SourceGen/MainController.cs
@@ -1924,8 +1924,7 @@ namespace SourceGen {
}
// Create a prototype entry with the various values.
- newEntry = new AddressMap.AddressMapEntry(firstOffset,
- selectedLen, addr, string.Empty, false);
+ newEntry = new AddressMap.AddressMapEntry(firstOffset, selectedLen, addr);
Debug.WriteLine("New entry prototype: " + newEntry);
}
diff --git a/SourceGen/ProjectFile.cs b/SourceGen/ProjectFile.cs
index 04d56c2..bbf2400 100644
--- a/SourceGen/ProjectFile.cs
+++ b/SourceGen/ProjectFile.cs
@@ -245,6 +245,8 @@ namespace SourceGen {
public int Addr { get; set; }
public int Length { get; set; }
public string PreLabel { get; set; }
+ public bool DisallowInward { get; set; }
+ public bool DisallowOutward { get; set; }
public bool IsRelative { get; set; }
public SerAddressMapEntry() {
@@ -257,6 +259,8 @@ namespace SourceGen {
Addr = ent.Address;
Length = ent.Length;
PreLabel = ent.PreLabel;
+ DisallowInward = ent.DisallowInward;
+ DisallowOutward = ent.DisallowOutward;
IsRelative = ent.IsRelative;
}
}
@@ -689,7 +693,8 @@ namespace SourceGen {
proj.AddrMap.Clear();
foreach (SerAddressMapEntry addr in spf.AddressMap) {
AddressMap.AddResult addResult = proj.AddrMap.AddEntry(addr.Offset,
- addr.Length, addr.Addr, addr.PreLabel, addr.IsRelative);
+ addr.Length, addr.Addr, addr.PreLabel,
+ addr.DisallowInward, addr.DisallowOutward, addr.IsRelative);
if (addResult != CommonUtil.AddressMap.AddResult.Okay) {
string msg = "off=+" + addr.Offset.ToString("x6") + " len=" +
(addr.Length == CommonUtil.AddressMap.FLOATING_LEN ?
diff --git a/SourceGen/RenderAddressMap.cs b/SourceGen/RenderAddressMap.cs
index 88bbf73..e75965a 100644
--- a/SourceGen/RenderAddressMap.cs
+++ b/SourceGen/RenderAddressMap.cs
@@ -87,6 +87,12 @@ namespace SourceGen {
sb.Append(change.Region.PreLabel);
sb.Append("'");
}
+ if (change.Region.DisallowInward) {
+ sb.Append(" [!in]");
+ }
+ if (change.Region.DisallowOutward) {
+ sb.Append(" [!out]");
+ }
sb.Append(CRLF);
diff --git a/SourceGen/Tools/Omf/Loader.cs b/SourceGen/Tools/Omf/Loader.cs
index b3e11e5..04f6fad 100644
--- a/SourceGen/Tools/Omf/Loader.cs
+++ b/SourceGen/Tools/Omf/Loader.cs
@@ -610,7 +610,7 @@ namespace SourceGen.Tools.Omf {
// Generate an ORG directive.
//int origAddr = proj.AddrMap.OffsetToAddress(bufOffset);
AddressMap.AddressMapEntry addrEnt = new AddressMap.AddressMapEntry(bufOffset,
- AddressMap.FLOATING_LEN, addr, string.Empty, false);
+ AddressMap.FLOATING_LEN, addr);
UndoableChange uc = UndoableChange.CreateAddressChange(null, addrEnt);
cs.Add(uc);
diff --git a/SourceGen/WpfGui/EditAddress.xaml b/SourceGen/WpfGui/EditAddress.xaml
index 14f5f47..6474158 100644
--- a/SourceGen/WpfGui/EditAddress.xaml
+++ b/SourceGen/WpfGui/EditAddress.xaml
@@ -187,6 +187,10 @@ limitations under the License.
+
+
diff --git a/SourceGen/WpfGui/EditAddress.xaml.cs b/SourceGen/WpfGui/EditAddress.xaml.cs
index 0f7486f..14e7321 100644
--- a/SourceGen/WpfGui/EditAddress.xaml.cs
+++ b/SourceGen/WpfGui/EditAddress.xaml.cs
@@ -162,6 +162,18 @@ namespace SourceGen.WpfGui {
}
private bool mUseRelativeAddressing;
+ public bool DisallowInwardRes {
+ get { return mDisallowInwardRes; }
+ set { mDisallowInwardRes = value; OnPropertyChanged(); UpdateControls(); }
+ }
+ private bool mDisallowInwardRes;
+
+ public bool DisallowOutwardRes {
+ get { return mDisallowOutwardRes; }
+ set { mDisallowOutwardRes = value; OnPropertyChanged(); UpdateControls(); }
+ }
+ private bool mDisallowOutwardRes;
+
///
/// Pre-label input TextBox.
///
@@ -309,6 +321,8 @@ namespace SourceGen.WpfGui {
AddressText = Asm65.Address.AddressToString(curRegion.Address, false);
}
PreLabelText = curRegion.PreLabel;
+ DisallowInwardRes = curRegion.DisallowInward;
+ DisallowOutwardRes = curRegion.DisallowOutward;
UseRelativeAddressing = curRegion.IsRelative;
OperationStr = (string)FindResource("str_HdrEdit");
@@ -323,6 +337,7 @@ namespace SourceGen.WpfGui {
// to fixed.
mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset,
curRegion.Length, curRegion.Address, curRegion.PreLabel,
+ curRegion.DisallowInward, curRegion.DisallowOutward,
curRegion.IsRelative);
option1Summ = (string)FindResource("str_OptEditAsIsSummary");
option1Msg = (string)FindResource("str_OptEditAsIs");
@@ -332,6 +347,7 @@ namespace SourceGen.WpfGui {
option2Msg = (string)FindResource("str_OptEditAndFix");
mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset,
curRegion.ActualLength, curRegion.Address, curRegion.PreLabel,
+ curRegion.DisallowInward, curRegion.DisallowOutward,
curRegion.IsRelative);
} else {
option2Summ = string.Empty;
@@ -347,10 +363,10 @@ namespace SourceGen.WpfGui {
// first action is disabled.
mResultEntry1 = new AddressMap.AddressMapEntry(curRegion.Offset,
selectionLen, curRegion.Address, curRegion.PreLabel,
- curRegion.IsRelative);
+ curRegion.DisallowInward, curRegion.DisallowOutward, curRegion.IsRelative);
mResultEntry2 = new AddressMap.AddressMapEntry(curRegion.Offset,
curRegion.Length, curRegion.Address, curRegion.PreLabel,
- curRegion.IsRelative);
+ curRegion.DisallowInward, curRegion.DisallowOutward, curRegion.IsRelative);
option1Summ = (string)FindResource("str_OptResizeSummary");
string fmt = (string)FindResource("str_OptResize");
@@ -396,6 +412,8 @@ namespace SourceGen.WpfGui {
AddressText = Asm65.Address.AddressToString(newEntry.Address, false);
}
PreLabelText = string.Empty;
+ DisallowInwardRes = false;
+ DisallowOutwardRes = false;
UseRelativeAddressing = false;
OperationStr = (string)FindResource("str_HdrCreate");
@@ -417,7 +435,8 @@ namespace SourceGen.WpfGui {
// a fixed region with the same start offset, but can't create a float there.
if (ares1 == AddressMap.AddResult.Okay) {
mResultEntry1 = new AddressMap.AddressMapEntry(newEntry.Offset,
- newRegion1.ActualLength, newEntry.Address, string.Empty, false);
+ newRegion1.ActualLength, newEntry.Address,
+ string.Empty, false, false, false);
option1Summ = (string)FindResource("str_CreateFixedSummary");
string fmt = (string)FindResource("str_CreateFixed");
@@ -439,7 +458,8 @@ namespace SourceGen.WpfGui {
}
if (ares2 == AddressMap.AddResult.Okay) {
mResultEntry2 = new AddressMap.AddressMapEntry(newEntry.Offset,
- AddressMap.FLOATING_LEN, newEntry.Address, string.Empty, false);
+ AddressMap.FLOATING_LEN, newEntry.Address,
+ string.Empty, false, false, false);
option2Summ = (string)FindResource("str_CreateFloatingSummary");
string fmt = (string)FindResource("str_CreateFloating");
@@ -615,7 +635,8 @@ namespace SourceGen.WpfGui {
// Combine base entry with pre-label string and relative addressing checkbox.
ResultEntry = new AddressMap.AddressMapEntry(baseEntry.Offset,
- baseEntry.Length, addr, PreLabelText, UseRelativeAddressing);
+ baseEntry.Length, addr, PreLabelText,
+ DisallowInwardRes, DisallowOutwardRes, UseRelativeAddressing);
Debug.WriteLine("Dialog result: " + ResultEntry);
DialogResult = true;
}