diff --git a/SourceGen/DataAnalysis.cs b/SourceGen/DataAnalysis.cs index 7853a80..9f8bb81 100644 --- a/SourceGen/DataAnalysis.cs +++ b/SourceGen/DataAnalysis.cs @@ -165,6 +165,8 @@ namespace SourceGen { // Check for a relocation. It'll be at offset+1 because it's on the operand, // not the opcode byte. (Make sure to check the length, or an RTS followed // by relocated data will freak out.) + // TODO(someday): this won't get the second byte of an MVN/MVP, which is fine + // since we don't currently support two formats on one instruction. if (mAnalysisParams.UseRelocData) { if (attr.Length > 1 && mProject.RelocList.TryGetValue(offset + 1, out DisasmProject.RelocData reloc)) { diff --git a/SourceGen/Res/Strings.xaml b/SourceGen/Res/Strings.xaml index ff3a8b8..0bf9313 100644 --- a/SourceGen/Res/Strings.xaml +++ b/SourceGen/Res/Strings.xaml @@ -130,7 +130,7 @@ limitations under the License. Visualization ignored no files available No exported symbols found. - Segment {0:D2}: Kind={1}, Attrs={2}, Name='{3}' + Segment {0:D2}: Kind={1}; Attrs={2}; Name='{3}' Segment {0:D2}: {3} {1,-9} Name='{2}', Length={4} Seg{0:D2}: {1} '{2}' The file doesn't exist. diff --git a/SourceGen/SGTestData/20212-reloc-data b/SourceGen/SGTestData/20212-reloc-data new file mode 100644 index 0000000..05efc89 Binary files /dev/null and b/SourceGen/SGTestData/20212-reloc-data differ diff --git a/SourceGen/SGTestData/20212-reloc-data.dis65 b/SourceGen/SGTestData/20212-reloc-data.dis65 new file mode 100644 index 0000000..c86fc02 --- /dev/null +++ b/SourceGen/SGTestData/20212-reloc-data.dis65 @@ -0,0 +1,326 @@ +### 6502bench SourceGen dis65 v1.0 ### +{ +"_ContentVersion":4, +"FileDataLength":255, +"FileDataCrc32":-527039020, +"ProjectProps":{ +"CpuName":"65816", +"IncludeUndocumentedInstr":false, +"TwoByteBrk":false, +"EntryFlags":12780031, +"AutoLabelStyle":"Simple", +"AnalysisParams":{ +"AnalyzeUncategorizedData":true, +"DefaultTextScanMode":"LowHighAscii", +"MinCharsForString":4, +"SeekNearbyTargets":true, +"UseRelocData":true, +"SmartPlpHandling":true}, + +"PlatformSymbolFileIdentifiers":["RT:Apple/Cxxx-IO.sym65", +"RT:Apple/IIgs-ROM.sym65", +"RT:Apple/GSOS.sym65"], +"ExtensionScriptFileIdentifiers":["RT:Apple/GSOS.cs", +"RT:Apple/IIgs-Toolbox.cs"], +"ProjectSyms":{ +}}, + +"AddressMap":[{ +"Offset":0, +"Addr":196608}, + +{ +"Offset":110, +"Addr":327648}, + +{ +"Offset":142, +"Addr":327680}, + +{ +"Offset":162, +"Addr":144470}, + +{ +"Offset":188, +"Addr":524288}, + +{ +"Offset":242, +"Addr":393216}], +"TypeHints":[{ +"Low":0, +"High":0, +"Hint":"Code"}], +"StatusFlagOverrides":{ +}, + +"Comments":{ +}, + +"LongComments":{ +"0":{ +"Text":"Segment 02: Kind=Code; Attrs=NoSpecial; Name=\u0027 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"110":{ +"Text":"Segment 03: Kind=Data; Attrs=BankRel, Dynamic; Name=\u0027PosFFE0 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"162":{ +"Text":"Segment 04: Kind=Code; Attrs=NoSpecial; Name=\u0027Bank2 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"188":{ +"Text":"Segment 05: Kind=Code; Attrs=AbsBank, Dynamic; Name=\u0027Bank8 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"242":{ +"Text":"Segment 06: Kind=Data; Attrs=0; Name=\u0027Filler \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}}, + +"Notes":{ +"0":{ +"Text":"Seg02: 03/0000 \u0027 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"110":{ +"Text":"Seg03: 04/ffe0 \u0027PosFFE0 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"162":{ +"Text":"Seg04: 02/3456 \u0027Bank2 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"188":{ +"Text":"Seg05: 08/0000 \u0027Bank8 \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}, + +"242":{ +"Text":"Seg06: 06/0000 \u0027Filler \u0027", +"BoxMode":false, +"MaxWidth":80, +"BackgroundColor":0}}, + +"UserLabels":{ +}, + +"OperandFormats":{ +}, + +"LvTables":{ +}, + +"Visualizations":[], +"VisualizationAnimations":[], +"VisualizationSets":{ +}, + +"RelocList":{ +"82":{ +"Width":2, +"Shift":0, +"Value":196677}, + +"91":{ +"Width":2, +"Shift":0, +"Value":196695}, + +"94":{ +"Width":2, +"Shift":0, +"Value":200773}, + +"98":{ +"Width":2, +"Shift":0, +"Value":196717}, + +"5":{ +"Width":3, +"Shift":0, +"Value":196608}, + +"85":{ +"Width":2, +"Shift":-8, +"Value":196677}, + +"88":{ +"Width":1, +"Shift":-16, +"Value":196677}, + +"10":{ +"Width":3, +"Shift":0, +"Value":144470}, + +"14":{ +"Width":3, +"Shift":0, +"Value":524288}, + +"18":{ +"Width":3, +"Shift":0, +"Value":144470}, + +"31":{ +"Width":3, +"Shift":0, +"Value":524313}, + +"102":{ +"Width":3, +"Shift":0, +"Value":327648}, + +"105":{ +"Width":3, +"Shift":0, +"Value":327648}, + +"100":{ +"Width":2, +"Shift":0, +"Value":327648}, + +"22":{ +"Width":2, +"Shift":0, +"Value":144470}, + +"63":{ +"Width":2, +"Shift":0, +"Value":144478}, + +"35":{ +"Width":2, +"Shift":0, +"Value":524313}, + +"47":{ +"Width":2, +"Shift":0, +"Value":524313}, + +"60":{ +"Width":2, +"Shift":0, +"Value":524326}, + +"76":{ +"Width":2, +"Shift":0, +"Value":524313}, + +"25":{ +"Width":1, +"Shift":0, +"Value":144470}, + +"27":{ +"Width":1, +"Shift":-8, +"Value":144470}, + +"29":{ +"Width":1, +"Shift":-16, +"Value":144470}, + +"38":{ +"Width":1, +"Shift":0, +"Value":524313}, + +"40":{ +"Width":1, +"Shift":-8, +"Value":524313}, + +"42":{ +"Width":1, +"Shift":-16, +"Value":524313}, + +"50":{ +"Width":2, +"Shift":-8, +"Value":524313}, + +"53":{ +"Width":1, +"Shift":-16, +"Value":524313}, + +"66":{ +"Width":1, +"Shift":-16, +"Value":144478}, + +"67":{ +"Width":1, +"Shift":-16, +"Value":524326}, + +"79":{ +"Width":1, +"Shift":-16, +"Value":524313}, + +"110":{ +"Width":3, +"Shift":0, +"Value":327648}, + +"167":{ +"Width":2, +"Shift":0, +"Value":144494}, + +"163":{ +"Width":3, +"Shift":0, +"Value":144470}, + +"193":{ +"Width":2, +"Shift":0, +"Value":524313}, + +"189":{ +"Width":3, +"Shift":0, +"Value":524288}, + +"213":{ +"Width":3, +"Shift":0, +"Value":524313}, + +"217":{ +"Width":3, +"Shift":0, +"Value":144470}}} diff --git a/SourceGen/SGTestData/Expected/20212-reloc-data_64tass.S b/SourceGen/SGTestData/Expected/20212-reloc-data_64tass.S new file mode 100644 index 0000000..d3b51eb --- /dev/null +++ b/SourceGen/SGTestData/Expected/20212-reloc-data_64tass.S @@ -0,0 +1,140 @@ + .cpu "65816" + .enc "sg_ascii" + .cdef $20,$7e,$20 +;Segment 02: Kind=Code; Attrs=NoSpecial; Name=' ' +* = $030000 + .al + .xl +L30000 clc + xce + .as + .xs + sep #$30 + lda L30000 + nop + jsl _L23456 + jsl _L80000 + lda _L23456 + lda _L23456 & $ffff + lda #<_L23456 + lda #>_L23456 + lda #`_L23456 + lda _L80019 + lda @w_L80019 & $ffff + lda #<_L80019 + lda #>_L80019 + lda #`_L80019 + nop + rep #$30 + .al + .xl + lda #_L80019 & $ffff + lda #_L80019 >> 8 + lda #_L80019 >> 16 + nop + lda #$000f + ldx #_L80026 & $ffff + ldy #_L2345E & $ffff + mvn #(`_L2345E)+6,#`_L2345E + nop +_L30045 pea $0000 + pea $f000 + pea _L80019 & $ffff + pea _L80019 >> 16 + pea _L30045 & $ffff + pea _L30045 >> 8 +_L30057 pea _L30045 >> 16 + pea _L30057 & $ffff + pea $1045 + nop + jmp _L3006D + + .word _L4FFE0 & $ffff + .long _L4FFE0 + .long _L4FFE0 + .byte $00 + +_L3006D rts + +;Segment 03: Kind=Data; Attrs=BankRel, Dynamic; Name='PosFFE0 ' + .logical $04ffe0 +_L4FFE0 .long _L4FFE0 + .byte $00 + .byte $00 + .byte $01 + .byte $02 + .byte $03 + .byte $04 + .byte $05 + .byte $06 + .byte $07 + .byte $08 + .byte $09 + .byte $0a + .byte $0b + .byte $0c + .byte $0d + .byte $0e + .byte $0f + .byte $10 + .byte $11 + .byte $12 + .byte $13 + .byte $14 + .byte $15 + .byte $16 + .byte $17 + .byte $18 + .byte $19 + .byte $1a + .byte $1b + .here + .logical $050000 + .byte $1c + .byte $1d + .byte $1e + .byte $1f + .text " !",$22,"#$%&'()*+,-./" + +;Segment 04: Kind=Code; Attrs=NoSpecial; Name='Bank2 ' + .here + .logical $023456 + .as + .xs +_L23456 lda _L23456 + jsr _L2346E + rtl + +_L2345E .fill 16,$00 + +_L2346E nop + rts + +;Segment 05: Kind=Code; Attrs=AbsBank, Dynamic; Name='Bank8 ' + .here + .logical $080000 +_L80000 lda _L80000 + lda @w_L80019 & $ffff + nop + lda $010000 + lda $020000 + lda L30000 + lda _L80000 + rtl + +_L80019 .long _L80019 + .byte $00 + .long _L23456 + .byte $00 + .byte $80 + .byte $00 + .byte $10 + .byte $08 + .byte $00 +_L80026 .text "This is a test." + .byte $00 +;Segment 06: Kind=Data; Attrs=0; Name='Filler ' + .here + .logical $060000 + .text "hello, world!" + .here diff --git a/SourceGen/SGTestData/Expected/20212-reloc-data_Merlin32.S b/SourceGen/SGTestData/Expected/20212-reloc-data_Merlin32.S new file mode 100644 index 0000000..12c8d8f --- /dev/null +++ b/SourceGen/SGTestData/Expected/20212-reloc-data_Merlin32.S @@ -0,0 +1,128 @@ +;Segment 02: Kind=Code; Attrs=NoSpecial; Name=' ' + org $030000 + mx %00 +L30000 clc + xce + mx %11 + sep #$30 + ldal L30000 + nop + jsl :L23456 + jsl :L80000 + ldal :L23456 + lda :L23456 + lda #<:L23456 + lda #>:L23456 + lda #^:L23456 + ldal :L80019 + lda: :L80019 + lda #<:L80019 + lda #>:L80019 + lda #^:L80019 + nop + rep #$30 + mx %00 + lda #:L80019 + lda #>:L80019 + lda #^:L80019 + nop + lda #$000f + ldx #:L80026 + ldy #:L2345E + mvn #^:L2345E+$60000,#^:L2345E + nop +:L30045 pea $0000 + pea $f000 + pea :L80019 + pea ^:L80019 + pea :L30045 + pea >:L30045 +:L30057 pea ^:L30045 + pea :L30057 + pea $1045 + nop + jmp :L3006D + + dw :L4FFE0 + adr :L4FFE0 + adr :L4FFE0 + dfb $00 + +:L3006D rts + +;Segment 03: Kind=Data; Attrs=BankRel, Dynamic; Name='PosFFE0 ' + org $04ffe0 +:L4FFE0 adr :L4FFE0 + dfb $00 + dfb $00 + dfb $01 + dfb $02 + dfb $03 + dfb $04 + dfb $05 + dfb $06 + dfb $07 + dfb $08 + dfb $09 + dfb $0a + dfb $0b + dfb $0c + dfb $0d + dfb $0e + dfb $0f + dfb $10 + dfb $11 + dfb $12 + dfb $13 + dfb $14 + dfb $15 + dfb $16 + dfb $17 + dfb $18 + dfb $19 + dfb $1a + dfb $1b + org $050000 + dfb $1c + dfb $1d + dfb $1e + dfb $1f + asc ' !"#$%&',27,'()*+,-./' + +;Segment 04: Kind=Code; Attrs=NoSpecial; Name='Bank2 ' + org $023456 + mx %11 +:L23456 ldal :L23456 + jsr :L2346E + rtl + +:L2345E ds 16 + +:L2346E nop + rts + +;Segment 05: Kind=Code; Attrs=AbsBank, Dynamic; Name='Bank8 ' + org $080000 +:L80000 ldal :L80000 + lda: :L80019 + nop + ldal $010000 + ldal $020000 + ldal L30000 + ldal :L80000 + rtl + +:L80019 adr :L80019 + dfb $00 + adr :L23456 + dfb $00 + dfb $80 + dfb $00 + dfb $10 + dfb $08 + dfb $00 +:L80026 asc 'This is a test.' + dfb $00 +;Segment 06: Kind=Data; Attrs=0; Name='Filler ' + org $060000 + asc 'hello, world!' diff --git a/SourceGen/SGTestData/Expected/20212-reloc-data_acme.S b/SourceGen/SGTestData/Expected/20212-reloc-data_acme.S new file mode 100644 index 0000000..db1e891 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20212-reloc-data_acme.S @@ -0,0 +1,12 @@ +;ACME can't handle 65816 code that lives outside bank zero +* = $0000 + !pseudopc $030000 { + !hex 18fbe230af000003ea2256340222000008af563402ad5634a956a934a902af19 + !hex 0008ad1900a919a900a908eac230a91900a90008a90800eaa90f00a22600a05e + !hex 34540208eaf40000f400f0f41900f40800f44500f40003f40300f45700f44510 + !hex ea4c6d00e0ffe0ff04e0ff040060e0ff0400000102030405060708090a0b0c0d + !hex 0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d + !hex 2e2faf563402206e346b00000000000000000000000000000000ea60af000008 + !hex ad1900eaaf000001af000002af000003af0000086b1900080056340200800010 + !hex 080054686973206973206120746573742e0068656c6c6f2c20776f726c6421 + } ;!pseudopc diff --git a/SourceGen/SGTestData/Expected/20212-reloc-data_cc65.S b/SourceGen/SGTestData/Expected/20212-reloc-data_cc65.S new file mode 100644 index 0000000..60537eb --- /dev/null +++ b/SourceGen/SGTestData/Expected/20212-reloc-data_cc65.S @@ -0,0 +1,139 @@ + .setcpu "65816" +;Segment 02: Kind=Code; Attrs=NoSpecial; Name=' ' +; .segment "SEG000" + .org $030000 + .a16 + .i16 +L30000: clc + xce + .a8 + .i8 + sep #$30 + lda L30000 + nop + jsl @L23456 + jsl @L80000 + lda f:@L23456 + lda @L23456 & $ffff + lda #<@L23456 + lda #>@L23456 + lda #^@L23456 + lda f:@L80019 + lda a:@L80019 & $ffff + lda #<@L80019 + lda #>@L80019 + lda #^@L80019 + nop + rep #$30 + .a16 + .i16 + lda #@L80019 & $ffff + lda #@L80019 >> 8 + lda #@L80019 >> 16 + nop + lda #$000f + ldx #@L80026 & $ffff + ldy #@L2345E & $ffff + mvn #^@L2345E+6,#^@L2345E + nop +@L30045: pea $0000 + pea $f000 + pea @L80019 & $ffff + pea @L80019 >> 16 + pea @L30045 & $ffff + pea @L30045 >> 8 +@L30057: pea @L30045 >> 16 + pea @L30057 & $ffff + pea $1045 + nop + jmp @L3006D & $ffff + + .word @L4FFE0 & $ffff + .faraddr @L4FFE0 + .faraddr @L4FFE0 + .byte $00 + +@L3006D: rts + +;Segment 03: Kind=Data; Attrs=BankRel, Dynamic; Name='PosFFE0 ' +; .segment "SEG001" + .org $04ffe0 +@L4FFE0: .faraddr @L4FFE0 + .byte $00 + .byte $00 + .byte $01 + .byte $02 + .byte $03 + .byte $04 + .byte $05 + .byte $06 + .byte $07 + .byte $08 + .byte $09 + .byte $0a + .byte $0b + .byte $0c + .byte $0d + .byte $0e + .byte $0f + .byte $10 + .byte $11 + .byte $12 + .byte $13 + .byte $14 + .byte $15 + .byte $16 + .byte $17 + .byte $18 + .byte $19 + .byte $1a + .byte $1b +; .segment "SEG002" + .org $050000 + .byte $1c + .byte $1d + .byte $1e + .byte $1f + .byte " !",$22,"#$%&'()*+,-./" + +;Segment 04: Kind=Code; Attrs=NoSpecial; Name='Bank2 ' +; .segment "SEG003" + .org $023456 + .a8 + .i8 +@L23456: lda @L23456 + jsr @L2346E & $ffff + rtl + +@L2345E: .res 16,$00 + +@L2346E: nop + rts + +;Segment 05: Kind=Code; Attrs=AbsBank, Dynamic; Name='Bank8 ' +; .segment "SEG004" + .org $080000 +@L80000: lda @L80000 + lda a:@L80019 & $ffff + nop + lda $010000 + lda $020000 + lda L30000 + lda @L80000 + rtl + +@L80019: .faraddr @L80019 + .byte $00 + .faraddr @L23456 + .byte $00 + .byte $80 + .byte $00 + .byte $10 + .byte $08 + .byte $00 +@L80026: .byte "This is a test." + .byte $00 +;Segment 06: Kind=Data; Attrs=0; Name='Filler ' +; .segment "SEG005" + .org $060000 + .byte "hello, world!" diff --git a/SourceGen/SGTestData/Expected/20212-reloc-data_cc65.cfg b/SourceGen/SGTestData/Expected/20212-reloc-data_cc65.cfg new file mode 100644 index 0000000..1772cf0 --- /dev/null +++ b/SourceGen/SGTestData/Expected/20212-reloc-data_cc65.cfg @@ -0,0 +1,21 @@ +# 6502bench SourceGen generated linker script for 20212-reloc-data +MEMORY { + MAIN: file=%O, start=%S, size=65536; +# MEM000: file=%O, start=$30000, size=110; +# MEM001: file=%O, start=$4ffe0, size=32; +# MEM002: file=%O, start=$50000, size=20; +# MEM003: file=%O, start=$23456, size=26; +# MEM004: file=%O, start=$80000, size=54; +# MEM005: file=%O, start=$60000, size=13; +} +SEGMENTS { + CODE: load=MAIN, type=rw; +# SEG000: load=MEM000, type=rw; +# SEG001: load=MEM001, type=rw; +# SEG002: load=MEM002, type=rw; +# SEG003: load=MEM003, type=rw; +# SEG004: load=MEM004, type=rw; +# SEG005: load=MEM005, type=rw; +} +FEATURES {} +SYMBOLS {} diff --git a/SourceGen/SGTestData/Source/20212-reloc-data-bank2.S b/SourceGen/SGTestData/Source/20212-reloc-data-bank2.S new file mode 100644 index 0000000..6d3ab61 --- /dev/null +++ b/SourceGen/SGTestData/Source/20212-reloc-data-bank2.S @@ -0,0 +1,17 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Segment #3 : code, load at specific address ($02/3456) + + REL ;generate relocatable code + +BANK2_START ENT +start ldal start + jsr later + rtl + +BANK2_MOV_DST ENT + ds 16 + +later nop + rts diff --git a/SourceGen/SGTestData/Source/20212-reloc-data-bank8.S b/SourceGen/SGTestData/Source/20212-reloc-data-bank8.S new file mode 100644 index 0000000..b0b7a3f --- /dev/null +++ b/SourceGen/SGTestData/Source/20212-reloc-data-bank8.S @@ -0,0 +1,30 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 +; +; Segment #4 : code, loads somewhere in bank 8 + + REL ;generate relocatable code + +BANK2_START EXT + +BANK8_START ENT +start ldal start + lda addr + nop + ldal $010000 + ldal $020000 + ldal $030000 + ldal $080000 + rtl + +BANK8_ADDR ENT +addr + adrl addr + adrl BANK2_START + dfb $80 + adrl $081000 + +BANK8_MOV_SRC ENT + asc 'This is a test.',$00 diff --git a/SourceGen/SGTestData/Source/20212-reloc-data-filler.S b/SourceGen/SGTestData/Source/20212-reloc-data-filler.S new file mode 100644 index 0000000..1d1ee40 --- /dev/null +++ b/SourceGen/SGTestData/Source/20212-reloc-data-filler.S @@ -0,0 +1,11 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 +; +; Segment #5 : filler + + REL ;generate relocatable code + + asc 'hello, world!' + diff --git a/SourceGen/SGTestData/Source/20212-reloc-data-lnk.S b/SourceGen/SGTestData/Source/20212-reloc-data-lnk.S new file mode 100644 index 0000000..81a207d --- /dev/null +++ b/SourceGen/SGTestData/Source/20212-reloc-data-lnk.S @@ -0,0 +1,60 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Merlin 32 link file. +; +; According to the documentation we can use ORG directives to set the segment +; load addresses, but in practice Merlin 32 rejects them. Also, DS +; directives are ignored, and KND uses a different default value than +; what the documentation says. +; +; cf. https://github.com/apple2accumulator/merlin32/issues/39 +; +; Instructions: +; - Assemble this file with Merlin32. It will pull everything in. +; - Open out.20212 with the segment viewer and find the start offsets +; of the segments. Set the ORG field with a hex editor. It's a +; 4-byte field at +$18. (Easy way in a v2.0 header: find the start +; of the SEGNAME and back up $1e bytes.) +; "PosFFE0" -> E0 FF 00 +; "Bank2" -> 56 34 02 +; "Bank8" -> 00 10 08 +; - Convert out.20212 to "20212-reloc-data" with OMF converter. +; - The project file generally requires no edits, except to delete the +; header comment. Leaving the segment-start comments in seems fine. + + DSK out.20212 ;output file name, must be ProDOS-compat + TYP $b3 ;S16 + XPL ;add ~ExpressLoad + +; Segment #1 + ASM 20212-reloc-data-main.S + KND $1000 ;Code; NoSpec +; SNA + + +; Segment #2 + ASM 20212-reloc-data-relover.S + KND $8101 ;Data; Dynamic, BankRel + ALI None +; BSZ 0 +; ORG $00ffe0 ;load in any bank, at $ffe0 + SNA PosFFE0 + +; Segment #3 + ASM 20212-reloc-data-bank2.S + KND $1000 + DS 256 +; ORG $023456 ;load exactly here + SNA Bank2 + +; Segment #4 + ASM 20212-reloc-data-bank8.S + KND $8800 ;Code; Dynamic, AbsBank +; ORG $081000 ;load in bank 8, at any address + SNA Bank8 + +; Segment #5 + ASM 20212-reloc-data-filler.S + KND $0001 ;Data + SNA Filler diff --git a/SourceGen/SGTestData/Source/20212-reloc-data-main.S b/SourceGen/SGTestData/Source/20212-reloc-data-main.S new file mode 100644 index 0000000..fd4f8d7 --- /dev/null +++ b/SourceGen/SGTestData/Source/20212-reloc-data-main.S @@ -0,0 +1,80 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 +; +; Segment #1 : code; main segment, loads anywhere + +BANK2_START EXT +BANK2_MOV_DST EXT +BANK8_START EXT +BANK8_ADDR EXT +BANK8_MOV_SRC EXT +ADDR_FFE0 EXT + + REL ;generate relocatable code + +start + clc + xce + sep #$30 + mx %11 + + ldal start + nop + + jsl BANK2_START + jsl BANK8_START + + ldal BANK2_START + lda BANK2_START + lda #BANK2_START + lda #^BANK2_START + + ldal BANK8_ADDR + lda BANK8_ADDR + lda #BANK8_ADDR + lda #^BANK8_ADDR + nop + +; Do some stuff with 16-bit registers. Merlin 32 treats <>^ as shift +; operations rather than byte selectors. + rep #$30 + mx %00 + lda #BANK8_ADDR + lda #^BANK8_ADDR + nop + +; Check MVN/MVP. Handing them correctly requires having two different +; symbol refs on a single instruction. + lda #15 + ldx #BANK8_MOV_SRC + ldy #BANK2_MOV_DST + mvn #^BANK8_MOV_SRC,#^BANK2_MOV_DST + nop + +check_pea + pea $0000 + pea $f000 + pea BANK8_ADDR + pea ^BANK8_ADDR + pea check_pea + pea >check_pea + pea ^check_pea + pea check_pea+18 + pea check_pea+$1000 + nop + + jmp :skipdata + +; Generate 2/3/4-byte refs. The OMF reloc entry generated by Merlin32 +; for ADRL is only 3 bytes wide. + dw ADDR_FFE0 + adr ADDR_FFE0 + adrl ADDR_FFE0 + +:skipdata + rts diff --git a/SourceGen/SGTestData/Source/20212-reloc-data-relover.S b/SourceGen/SGTestData/Source/20212-reloc-data-relover.S new file mode 100644 index 0000000..00fedca --- /dev/null +++ b/SourceGen/SGTestData/Source/20212-reloc-data-relover.S @@ -0,0 +1,15 @@ +; Copyright 2020 faddenSoft. All Rights Reserved. +; See the LICENSE.txt file for distribution terms (Apache 2.0). +; +; Assembler: Merlin 32 +; +; Segment #2 : data, loads at $FFE0 in arbitrary bank and overflows + + REL ;generate relocatable code + +ADDR_FFE0 ENT + +start adrl start + hex 000102030405060708090a0b0c0d0e0f + hex 101112131415161718191a1b1c1d1e1f + hex 202122232425262728292a2b2c2d2e2f diff --git a/SourceGen/Tools/Omf/Loader.cs b/SourceGen/Tools/Omf/Loader.cs index 8d9762e..db1716a 100644 --- a/SourceGen/Tools/Omf/Loader.cs +++ b/SourceGen/Tools/Omf/Loader.cs @@ -157,6 +157,9 @@ namespace SourceGen.Tools.Omf { // would mean you can't set the "absolute bank" flag to position code or // data in bank 0. I'm going to assume that's intentional, since people // (a) shouldn't be doing that, and (b) can use DP/Stack instead (?). + // + // It also means that "bank relative" can't be used to set the position + // to zero, which is probably fine since you can do that with ALIGN=$10000. continue; } @@ -195,15 +198,30 @@ namespace SourceGen.Tools.Omf { int addr; - if (omfSeg.Org != 0) { - // Specific address requested. + // We want to put the segment at a specific offset in an arbitrary bank + // if ORG is nonzero, the BankRel flag is set, and the AbsBank flag is clear. + bool bankRel = omfSeg.Org != 0 && + (omfSeg.Attrs & OmfSegment.SegmentAttribute.BankRel) != 0 && + (omfSeg.Attrs & OmfSegment.SegmentAttribute.AbsBank) == 0; + // We want to put the segment at an arbitrary offset in a specific bank + // if ORG is nonzero, the BankRel flag is clear, and the AbsBank flag is set. + bool fixedBank = omfSeg.Org != 0 && + (omfSeg.Attrs & OmfSegment.SegmentAttribute.BankRel) == 0 && + (omfSeg.Attrs & OmfSegment.SegmentAttribute.AbsBank) != 0; + // We want to put the segment at a specific offset and bank + // if ORG is nonzero, and BankRel and FixedBank are either both set or + // both clear. + bool fixedAddr = omfSeg.Org != 0 && (bankRel ^ fixedBank) == false; + + if (fixedAddr || fixedBank) { + // Specific bank requested. addr = omfSeg.Org; if ((omfSeg.Attrs & OmfSegment.SegmentAttribute.AbsBank) != 0) { // just keep the bank addr &= 0x00ff0000; } } else { - // Find next available spot with enough space. + // Find next available bank with enough space. while (true) { while (nextBank < 256 && inUse[nextBank]) { nextBank++; @@ -225,11 +243,20 @@ namespace SourceGen.Tools.Omf { } addr = nextBank << 16; + if (bankRel) { + // TODO(maybe): reject if incompatible with BANKSIZE + addr |= omfSeg.Org & 0x0000ffff; + } // Advance nextBank. We do this by identifying the last address touched, - // and moving to the next bank. + // then incrementing the bank number. int lastAddr = addr + omfSeg.Length - 1; nextBank = (lastAddr >> 16) + 1; + if (nextBank >= 0x0100) { + // Overflowed the 65816 address space. + Debug.WriteLine("Bank exceeded $ff"); + return false; + } } SegmentMapEntry ent = new SegmentMapEntry(omfSeg, addr);