Compare commits

...

26 Commits

Author SHA1 Message Date
Stephen Heumann
740f75cff5 Add script to set filetypes. 2023-08-06 17:49:51 -05:00
Stephen Heumann
ac725a6207 Bump version number to 2.1.0 final. 2023-06-29 19:53:22 -05:00
Stephen Heumann
850952d612 Treat ORG records as giving a signed offset from the current location.
This is the way they are defined in the GS/OS Reference, as well as the way they seem to be used by all assemblers and all other linkers that I could check (ORCA/M, MPW AsmIIGS, Apple LinkIIGS, old ORCA/APW LINKED, 8-bit ORCA linker).

Previously, this linker treated ORG records as giving an absolute address to ORG to (but with a bug in the address computation). The OMF spec in appendix B of the ORCA/M manual defines them this way, but this is inconsistent with the spec in the GS/OS Reference and with the way ORG records are generated by ORCA/M itself (for an ORG *+expression directive). Therefore, I think this is just an error and the specification in the GS/OS Reference should be regarded as correct.

We still do not support going backward (using a negative ORG operand). Trying to do so will just give an error.
2022-09-26 21:32:28 -05:00
Stephen Heumann
9f232e883a Avoid spurious errors when evaluating EQU/GEQU expressions.
Shifting is now prohibited only for relocatable expressions. It is fine if a shift operator is used with constant operands, simply producing another constant.

Also, spurious errors about using multiple load segments in an expression are no longer reported just because of the load segment "containing" the EQU/GEQU record. Since it does not actually translate to anything in the load file, that segment does not matter.
2022-09-25 21:49:01 -05:00
Stephen Heumann
da13b94a43 Properly evaluate non-constant expressions in EQU/GEQU records.
Previously, the values of such expressions were essentially ignored, resulting in incorrect output.

This affected code like the following example:

test1   start
        lda     >p
        rtl
        end

D1      data
p       gequ    val
        end

val     data
        dc      i'123'
        end

Note that the EQU/GEQU expression is evaluated within the context of the location that references it, not the location where it is defined. This affects the value of the location counter, as well as the symbol search behavior. The references for the OMF format do not clearly define which way this should be done, but the current behavior can cause problems with certain object files produced by ORCA/M.
2022-09-25 21:42:20 -05:00
Stephen Heumann
0b275e5b22 Set position-independent flag only if it is set in all object segments.
Previously, the position-independent attribute bit would be set in a load segment if it was set on the first constituent object segment. Now it is only set in the load segment if it is set in all the constituent object segments. This is consistent with the ORCA linker's general approach of conservatively combining the flags from the object segments.
2022-08-30 19:46:22 -05:00
Stephen Heumann
085c7c46ca Add support for auto-segmentation.
This is a new feature where the linker will automatically divide the code into load segments, creating as many segments as necessary to fit it. This relieves the programmer from the need to manually figure out how a large program can be divided into segments.

Auto-segmentation is triggered by the use of the special load segment name AUTOSEG~~~. Using this approach (rather than a flag in the OMF header) allows auto-segmentation to be used with all existing languages that provide a mechanism for specifying load segment names.
2022-08-30 19:32:09 -05:00
Stephen Heumann
3bb2802f2f Update modification date in comment. 2021-08-30 21:39:03 -05:00
Stephen Heumann
390fd96ede Do not report an error when the segment length equals the bank size.
This is legal per the OMF definition in the GS/OS Reference (and it is accepted by the loader), so it should not be treated as an error.
2021-08-26 22:21:44 -05:00
Stephen Heumann
ea3550bfcc Update release notes. 2021-03-03 23:35:07 -06:00
Stephen Heumann
ef5360eddd Fix the make script to use actual names of macro files. 2021-03-03 23:27:28 -06:00
Stephen Heumann
47460f34bb Fix check for valid alignment values.
Previously, the high 16 bits were being ignored. Therefore, the valid alignment value $10000 was rejected, but values that were not a power of 2 may have been accepted. The new code properly enforces that the alignment is a power of 2, and is <= $10000.
2021-03-03 23:26:08 -06:00
Stephen Heumann
8aa3c4e8c7 Give error about excessive alignment at the right time.
The error "Alignment factor must not exceed segment align factor" is now given when an ALIGN record with greater alignment than its segment is encountered. (This is the error that was given erroneously in other circumstances before the last commit.)
2021-03-03 22:53:57 -06:00
Stephen Heumann
aa9a585d19 Do not give spurious errors about segment alignment.
This would happen if a later object segment had a more restrictive alignment than previous object segments that contribute to the same load segment, as in the following example:

s1      start
        jsl s2
        rtl
        end

        align   256
s2      start
        rtl
        end

These alignment requirements can be satisfied by just giving the load segment the most restrictive alignment of any object segment (since all alignments are powers of 2) and inserting space as necessary to align the code from each object segment.
2021-03-03 18:41:45 -06:00
Stephen Heumann
d62fdba4bb Update linker release notes. 2021-02-25 22:31:29 -06:00
Stephen Heumann
2275b137d8 Update linker version number to 2.0.6. 2021-02-25 22:29:56 -06:00
Stephen Heumann
76ba56a36b Allow 2-byte RELEXPR records to be used for branches of + or - 64KB.
Previously, the linker gave an error if the relative displacement was more than + or - 32 KB. But 2-byte RELEXPR records are typically used for the operand of the BRL instruction, and since its address calculation wraps around within the program bank, it can effectively address + or - 64KB (i.e. any location within the program bank). Similar reasoning applies to PER, the other instruction using long relative addressing.

This would give an error in code like the following:

bigbrl  start
        brl     later
        ds      33000  ; realistic examples would have actual code here
later   rtl
        end

(This currently also gives an assembler error due to similar logic in ORCA/M, but the output file can be linked anyway.)

This issue can affect very large functions compiled with ORCA/C or ORCA/Pascal, which may sometimes have branches that go more than 32 KB forward or back.
2021-02-19 18:18:47 -06:00
Stephen Heumann
42734c7433 Update linker release notes. 2018-09-15 16:40:45 -05:00
Stephen Heumann
1a643585e8 Update linker version number to 2.0.5. 2018-09-15 16:40:23 -05:00
Stephen Heumann
170fa09ecc Search for object files under both lower- and upper-case extensions.
This enables the linker to work correctly with object files with either extension case (or a mix), so it can work with objects from any of the ORCA languages even on a case-sensitive filesystem.

If two object files differ only in the case of their extension, the one with the lower-case extension will be used, and the one with the upper-case extension will be ignored.
2018-09-15 16:20:18 -05:00
Stephen Heumann
433b4652d7 Accept DVR, LDF, and FST as valid KeepType values.
Note that ORCA/Shell listings use DRV for type $BB, but the File Type Notes specify DVR.
2018-09-13 18:14:09 -05:00
MikeW50
2cdbebe6e6
Merge pull request #4 from ksherlock/ci-update
use lowercase extensions (.root, .a, etc)
2018-03-25 15:35:09 -06:00
MikeW50
9bca07851b
Merge pull request #2 from ksherlock/gg_support
add makefile and build.ninja file for use with Golden Gate.
2018-03-25 15:34:20 -06:00
Kelvin Sherlock
a8528f35b7 use lowercase extensions (.root, .a, etc) for better compatibility with case-sensitive file systems
(ORCA/C and ORCA/Pascal use lowercase extensions for object files. ORCA/M uses uppercase extensions for object files)
2018-01-02 21:35:34 -05:00
Kelvin Sherlock
1ec542fde5 fix typos. 2017-10-23 09:32:39 -04:00
Kelvin Sherlock
ce65f20394 add makefile and ninja file for use with Golden Gate. 2017-10-02 16:01:45 -04:00
16 changed files with 408 additions and 73 deletions

28
GNUmakefile Normal file
View File

@ -0,0 +1,28 @@
SRC = exp.asm file.asm linker.asm out.asm pass1.asm pass2.asm \
seg.asm symbol.asm util.asm
OBJECTS = $(SRC:%.asm=obj/%.A) $(SRC:%.asm=obj/%.ROOT)
# link order is important.
linker: $(OBJECTS)
iix link \
obj/linker obj/util obj/file obj/pass1 obj/pass2 obj/seg \
obj/symbol obj/exp obj/out \
keep=$@
iix chtyp -a 0xdb01 $@
.PHONY: clean
clean:
$(RM) obj/*.A obj/*.ROOT obj/*.a obj.*.root
$(RM) linker
# fix the filetype on these headers
# since they have no extension.
ftype:
iix chtyp -l asm directpage
obj/%.A : %.asm %.mac directpage
iix compile $< keep=obj/$*

50
build.ninja Normal file
View File

@ -0,0 +1,50 @@
# ninja build file.
builddir = obj
o = obj
rule compile
command = iix compile $in keep=$o/$keep
description = build $out
rule link
command = iix link $orca-in keep=$out
description = link $out
build linker : link $o/exp.a $o/exp.root $o/file.a $o/file.root $
$o/linker.a $o/linker.root $o/out.a $o/out.root $o/pass1.a $o/pass1.root $
$o/pass2.a $o/pass2.root $o/seg.a $o/seg.root $o/symbol.a $o/symbol.root $
$o/util.a $o/util.root
orca-in = $o/linker $o/util $o/file $o/pass1 $o/pass2 $o/seg $
$o/symbol $o/exp $o/out
build $o/exp.a $o/exp.root : compile exp.asm | exp.mac directpage
keep = exp
build $o/file.a $o/file.root : compile file.asm | file.mac directpage
keep = file
build $o/linker.a $o/linker.root : compile linker.asm | linker.mac directpage
keep = linker
build $o/out.a $o/out.root : compile out.asm | out.mac directpage
keep = out
build $o/pass1.a $o/pass1.root : compile pass1.asm | pass1.mac directpage
keep = pass1
build $o/pass2.a $o/pass2.root : compile pass2.asm | pass2.mac directpage
keep = pass2
build $o/seg.a $o/seg.root : compile seg.asm | seg.mac directpage
keep = seg
build $o/symbol.a $o/symbol.root : compile symbol.asm | symbol.mac directpage
keep = symbol
build $o/util.a $o/util.root : compile util.asm | util.mac directpage
keep = util
default linker
build all : phony linker
# eof

View File

@ -727,6 +727,7 @@ addr dc a'EndExp' $00 End
* shiftFlag - 1 if the value is shifted, else 0
* shiftValue - expression result before shifting
* shiftCount - shift counter
* symbolRelocatable - non-zero if sym is relocatable
* returns the value of the expression
*
****************************************************************

View File

@ -8,6 +8,18 @@
*
****************************************************************
*
* Linker 2.1.0 prepared Jun 23 by Stephen Heumann
*
****************************************************************
*
* Linker 2.0.6 prepared Aug 21 by Stephen Heumann
*
****************************************************************
*
* Linker 2.0.5 prepared Sep 18 by Stephen Heumann
*
****************************************************************
*
* Linker 2.0.4 prepared Oct 17 by Stephen Heumann
*
****************************************************************
@ -290,7 +302,7 @@ sf8 anop
;
lda progress
beq wh1
puts #'Link Editor 2.0.4',cr=t
puts #'Link Editor 2.1.0',cr=t
putcr
wh1 anop
;

View File

@ -1,8 +1,53 @@
ORCA/Linker 2.0.4
ORCA/Linker 2.1.0
Copyright 1996, Byte Works Inc.
Updated 2023
-- Change List --------------------------------------------------------------
2.1.0 1. The linker can now automatically divide a large program into
segments. See "Auto-Segmentation," below.
2. A load segment is now flagged as position-independent only if
all the constituent object segments have that attribute set.
3. Fixed bug that caused EQU or GEQU expressions with non-constant
operands to be evaluated incorrectly.
4. The numeric value in an ORG record is now treated as a signed
offset from the current location, consistent with its
definition in the GS/OS Reference. However, negative offset
values are not supported and will produce an error.
2.0.6 1. The linker could give a spurious error about the relative
address calculation for a BRL instruction if it branched
forward or backward more than 32 KB. Since the address
calculation for BRL wraps around within the program bank, it
can branch forward or backward by up to 64 KB (to any location
in the program bank), and the linker now allows this.
2. Fixed several problems related to alignment. Previously,
the linker both reported spurious errors about alignment in
certain cases and failed to detect errors in other cases.
With these fixes, a segment alignment of $10000 is now
permitted. Also, the linker can now link together multiple
object segments with different alignment requirements into a
single load segment, regardless of the order of the object
segments. The alignment of the load segment will be the most
restrictive alignment of any of the object segments, and the
alignment requirements of each object segment will be obeyed.
3. A spurious error is no longer reported for code segments that
are exactly $10000 bytes long (the full size of a bank).
2.0.5 1. On case-sensitive filesystems (which are not normally used
natively on the Apple IIGS, but may be used through emulation
tools or network file servers), the linker can now find object
files with either upper-case or lower-case file extensions.
(Kelvin Sherlock, Stephen Heumann)
2. KeepType values of "DVR", "LDF", and "FST" are now accepted.
2.0.4 1. Fixed bugs that could cause spurious errors to be reported.
(Stephen Heumann)
@ -29,4 +74,24 @@ Copyright 1996, Byte Works Inc.
-- Documentation Update -----------------------------------------------------
No changes.
ORCA/M Manual, p. 492
The operand in an ORG record is a signed offset from the current location, not an absolute address. (This is consistent with the definition in the GS/OS Reference, and with the behavior of ORCA/M and other assemblers and linkers.)
-- Changes introduced in ORCA/Linker 2.1.0 ----------------------------------
Auto-Segmentation
-----------------
On the Apple IIGS, programs with more than 64 KB of code have to be divided into multiple load segments. This can be done using the segment directives in the various ORCA languages, but the programmer has to manually manage them, working out how much code would fit in each segment. Changes to a program's code or its compilation options (e.g. debugging or optimization settings) could alter the size of the generated machine code, requiring its segmentation to be changed.
The ORCA linker can now automatically assign code to load segments, avoiding the need to manually change the segmentation based on the code size. If code uses the special load segment name AUTOSEG~~~, the linker will automatically place it into load segments named AUTOSEG~00, AUTOSEG~01, etc., creating as many load segments as necessary to fit the code.
To use this feature in ORCA/C, ORCA/Pascal, or ORCA/Modula-2, simply use those languages' segment directives to specify the load segment name as AUTOSEG~~~ :
segment "AUTOSEG~~~"; (in ORCA/C)
(*$Segment 'AUTOSEG~~~'*) (in ORCA/Pascal or ORCA/Modula-2)
You can place a directive like this at the top of each of your source files or (for ORCA/C) in a pre-include file.
It is also possible to use auto-segmentation for assembly code, but the code must be written to account for the fact that any two program segments using auto-segmentation may wind up in different load segments, and therefore might be placed in different banks at run time.

View File

@ -3,12 +3,13 @@
resource rVersion(1) {
{
2, /* Major revision */
0, /* Minor revision */
4, /* Bug version */
1, /* Minor revision */
0, /* Bug version */
release, /* Release stage */
0, /* Non-final release # */
},
verUS, /* Region code */
"ORCA/Linker", /* Short version number */
"Copyright 1996, Byte Works, Inc." /* Long version number */
"Copyright 1996, Byte Works, Inc.\n" /* Long version number */
"Updated 2023"
};

18
make
View File

@ -14,47 +14,47 @@ end
if {#} == 0 then
Newer obj/linker.a linker.asm linker.macros directPage
Newer obj/linker.a linker.asm linker.mac directPage
if {Status} != 0
set linker linker
end
Newer obj/util.a util.asm util.macros directPage
Newer obj/util.a util.asm util.mac directPage
if {Status} != 0
set util util
end
Newer obj/file.a file.asm file.macros directPage
Newer obj/file.a file.asm file.mac directPage
if {Status} != 0
set file file
end
Newer obj/pass1.a pass1.asm pass1.macros directPage
Newer obj/pass1.a pass1.asm pass1.mac directPage
if {Status} != 0
set pass1 pass1
end
Newer obj/pass2.a pass2.asm pass2.macros directPage
Newer obj/pass2.a pass2.asm pass2.mac directPage
if {Status} != 0
set pass2 pass2
end
Newer obj/seg.a seg.asm seg.macros directPage
Newer obj/seg.a seg.asm seg.mac directPage
if {Status} != 0
set seg seg
end
Newer obj/symbol.a symbol.asm symbol.macros directPage
Newer obj/symbol.a symbol.asm symbol.mac directPage
if {Status} != 0
set symbol symbol
end
Newer obj/exp.a exp.asm exp.macros directPage
Newer obj/exp.a exp.asm exp.mac directPage
if {Status} != 0
set exp exp
end
Newer obj/out.a out.asm out.2 out.macros directPage
Newer obj/out.a out.asm out.mac directPage
if {Status} != 0
set out out
end

25
out.asm
View File

@ -268,7 +268,7 @@ st1 lda segType or in the or flags
sta loadType
lda segType mask out missing and flags
and #$E200
ora #$3DFF
ora #$1DFF
and loadType
sta loadType
lda loadType get the type without flags
@ -385,10 +385,13 @@ or4 anop
ora loadAlign+2
bne la1
move4 segAlign,loadAlign loadAlign = segAlign
bra la2 else
la1 move4 segAlign,r0 PrepareAlign(segAlign)
bra la3 else
la1 cmpl loadAlign,segAlign if loadAlign < segAlign then
bge la2
move4 segAlign,loadAlign loadAlign = segAlign
la2 move4 segAlign,r0 PrepareAlign(segAlign)
jsr PrepareAlign
la2 anop endif
la3 anop endif
bra sa4
;
; Set the load segment alignment (pass 2)
@ -408,13 +411,9 @@ sa0 lda segAlign skip if alignment is 0
bra sa3 else
sa1 cmpl loadAlign,segAlign if loadAlign < segAlign then
bge sa2
ph4 #0 Error(NULL,22)
ph2 #22
jsr Error
bra sa3 else
sa2 move4 segAlign,r0 DefineAlign(segAlign)
move4 segAlign,loadAlign loadAlign = segAlign
sa2 move4 segAlign,r0 DefineAlign(segAlign)
jsr DefineAlign
! anop endif
sa3 anop endif
jsr CheckAlignOrg check for conflicts between align,org
sa4 anop
@ -2221,7 +2220,7 @@ NamedVariable private
bne lb3 return false
lda #nameEnd-name-3 index into the name array
sta r4
lda #$BA initial file number
lda #$BD initial file number
sta r6
lb1 ldx r4 check for match
ldy #2
@ -2263,6 +2262,9 @@ name dc c'S16' file type mnemonics
dc c'NDA'
dc c'CDA'
dc c'TOL'
dc c'DVR'
dc c'LDF'
dc c'FST'
nameEnd anop
end
@ -2493,6 +2495,7 @@ lb2 add4 length,loadPC update the length of the program
beq lb2a
cmpl loadPC,loadBanksize
blt lb2a
beq lb2a
ph4 #0
ph2 #18
jsr Error

View File

@ -137,13 +137,12 @@ DoOrg private
sta r0
ldy #3
lda [sp],Y
sta r2+2
sta r2
add4 sp,#5
sub4 r0,loadOrg get the disp from the segment start
cmpl pc,r0
bge lb1 if the disp is greater than the pc then
move4 r0,pc update the pc
lda r2
bmi lb1 if the disp is positive
add4 pc,r0 update the pc
lb1 anop
rts
end

View File

@ -26,6 +26,7 @@
****************************************************************
*
Align private
using Common
ldy #1 get the alignment factor
lda [sp],Y
@ -34,7 +35,12 @@ Align private
iny
lda [sp],Y
sta r2
add4 sp,#5 skip the alignment opcode and operand
cmpl segAlign,r0 if alignment factor > segAlign
bge lb1
ph4 #0 Error(NULL,22)
ph2 #22
jsr Error
lb1 add4 sp,#5 skip the alignment opcode and operand
jsr DefineAlign do the align
rts
end
@ -637,13 +643,12 @@ DoOrg private
ldy #1 get the value
lda [sp],Y
sta r4
sta r0
ldy #3
lda [sp],Y
sta r6
sta r2
add4 sp,#5 skip the op code & operand
sub4 pc,r4,r0 calculate the space to insert
lda r2 if space < 0 then
lda r2 if disp < 0 then
bpl lb1
ph4 #0 Error(NULL,3)
ph2 #3
@ -1385,7 +1390,7 @@ lb2 lda t1,X
blt lb2
lda t1-1,Y
bpl lb6
bra lb5
bra lb4a
lb3 lda #$FF
lb4 cmp t1,X
bne lb5
@ -1394,6 +1399,9 @@ lb4 cmp t1,X
blt lb4
lda t1-1,Y
bmi lb6
lb4a lda expLength let BRL wrap around within program bank
cmp #2
bge lb6
lb5 long I,M
ph4 #0
ph2 #11

View File

@ -608,3 +608,12 @@
.d
sta 2+&op
mend
macro
&lab cmpl &n1,&n2
&lab lda 2+&n1
cmp 2+&n2
bne ~&syscnt
lda &n1
cmp &n2
~&syscnt anop
mend

158
seg.asm
View File

@ -24,6 +24,102 @@ isLibrary ds 2 is the file we are processing a library file?
largeLibFile ds 2 largest library file number
libDisp ds 4 disp in library symbol table
suffix ds 2 suffix letter
autoSegCounter ds 2 auto-segmentation counter (hex string)
autoSegLength ds 4 length of current auto segment
autoSegNamePtr ds 4 pointer to current auto-segment name
end
****************************************************************
*
* AutoSegment - perform auto-segmentation
*
* inputs:
* loadNamePtr - load segment name
* segLength - # of bytes of code in the segment
* segAlign - segment alignment factor
*
* outputs:
* loadNamePtr - modified if using auto-segmentation
*
****************************************************************
*
AutoSegment start
using SegCommon
using Common
using OutCommon
move4 loadNamePtr,r0 if load seg name is not 'AUTOSEG~~~'
ldy #nameSize-2
lb0 lda [r0],Y
cmp autoSegStr,Y
beq lb0a
rts return
lb0a dey
dey
bpl lb0
lda segAlign perform alignment if necessary
bne lb1
lda segAlign+2
beq lb2
lda #0
lb1 dec a
bit autoSegLength
beq lb2
ora autoSegLength
inc a
sta autoSegLength
bne lb2
inc autoSegLength+2
lb2 add4 autoSegLength,segLength update auto seg length
lda autoSegLength+2 if it is over $10000 bytes
beq lb5
dec a
ora autoSegLength
beq lb5
move4 segLength,autoSegLength set length to seg length
short M update auto-seg counter
lda autoSegCounter+1
inc a
cmp #'9'+1
bne lb3
lda #'A'
lb3 cmp #'F'+1
bne lb3b
lda autoSegCounter
inc a
cmp #'9'+1
bne lb3a
lda #'A'
lb3a sta autoSegCounter
lda #'0'
lb3b sta autoSegCounter+1
long M
ph4 #nameSize make new auto-seg name string
jsr MLalloc
sta r4
sta autoSegNamePtr
stx r4+2
stx autoSegNamePtr+2
ldy #nameSize-2
lda autoSegCounter
bra lb4a
lb4 lda autoSegStr,Y
lb4a sta [r4],Y
dey
dey
bpl lb4
! set load seg name to auto-seg name
lb5 move4 autoSegNamePtr,loadNamePtr
rts
;
; Local constant
;
autoSegStr dc c'AUTOSEG~~~'
end
****************************************************************
@ -161,7 +257,7 @@ giFiletype ds 2
FindSuffix private
using SegCommon
lda #'A' set the initial suffix
lda #'a' set the initial suffix
sta lsuffix
lb1 lda lsuffix try it out
sta suffix
@ -174,7 +270,7 @@ lb1 lda lsuffix try it out
bra lb1
lb2 lda lsuffix use the last one - it worked (or did
dec A not exist, as in 'A'-1)
dec A not exist, as in 'a'-1)
sta suffix
rts
@ -283,7 +379,17 @@ InitPass start
stz lastFileNumber
stz dataNumber no data areas processed
stz lastDataNumber
lda #'00' initial auto-seg is 'AUTOSEG~00'
sta autoSegCounter
lla autoSegNamePtr,initialAutoSegName
stz autoSegLength initial auto-seg length is 0
stz autoSegLength+2
rts
;
; Local constant
;
initialAutoSegName dc c'AUTOSEG~00'
end
****************************************************************
@ -304,8 +410,8 @@ InitPass start
KeepName private
using SegCommon
lda suffix if suffix = 'A'-1 then
cmp #'A'-1
lda suffix if suffix = 'a'-1 then
cmp #'a'-1
bne kn0
clc return false
rts
@ -336,7 +442,18 @@ kn1 lda #'.'
iny
lda suffix
sta [fname],Y
dec suffix --suffix
long M
phy
ph4 fname if not exists(fname) then
jsr ExistsM
ply
tax
short M
bne kn2
lda suffix uppercase suffix
and #$DF
sta [fname],Y
kn2 dec suffix --suffix
long M
sec
rts
@ -865,6 +982,7 @@ vt0 ldy #version get the segment version number
sta segName+2
move4 segName,loadNamePtr
add4 segName,#10
jsr AutoSegment
jsr FindLoadSegment
ldy #s2numsex verify that numsex = 0
lda [seg],Y
@ -955,6 +1073,7 @@ vo1 cmp #1 branch if not version 1
sta segName+2
move4 segName,loadNamePtr
add4 segName,#10
jsr AutoSegment
jsr FindLoadSegment
ldy #s1numsex verify that numsex = 0
lda [seg],Y
@ -1053,14 +1172,14 @@ blankSeg dc 10c' ' default load segment name
****************************************************************
*
* RootName - Append .ROOT to file name
* RootName - Append .root to file name
*
* inputs:
* basename - base file name
*
* outputs:
* ckname - current keep file name
* tkname - .ROOT appended to contents of kname
* tkname - .root appended to contents of kname
* kltr - suffix letter for the main obj file
*
****************************************************************
@ -1091,15 +1210,32 @@ RootName private
iny
iny
ldx #0
phy
short M
kn1 lda root,X
rn1 lda root,X
sta [fname],Y
iny
inx
cpx #l:root
bne kn1
bne rn1
long M
rts
ph4 fname if not exists(fname) then
jsr ExistsM
ply
tax
bne ret
short M
ldx #1
iny
rn2 lda root,X uppercase suffix
and #$DF
sta [fname],Y
iny
inx
cpx #l:root
bne rn2
long M
ret rts
root dc c'.ROOT'
root dc c'.root'
end

16
settypes Normal file
View File

@ -0,0 +1,16 @@
filetype -p =.asm src; change -p =.asm asm65816
filetype -p =.mac src; change -p =.mac asm65816
filetype directpage src; change directpage asm65816
filetype smac src; change smac asm65816
filetype linker.rez src; change linker.rez rez
filetype backup src; change backup exec
filetype count src; change count exec
filetype linkit src; change linkit exec
filetype make src; change make exec
filetype settypes src; change settypes exec
filetype build.ninja txt
filetype GNUmakefile txt
filetype LICENSE txt
filetype linker.notes txt
filetype README.md txt
filetype obj:README.txt txt

View File

@ -845,15 +845,10 @@ gb3 ldy #symPriv if sym^.symPriv then
sv1 ldy #symExp if the value is an expression then
lda [sym],Y
jeq sv2
ph2 copiedExpression save volitile variables
ph2 copiedExpression save volatile variables
ph4 shiftCount
ph2 shiftFlag
ph4 shiftValue
ph2 symbolCount
ph2 symbolLength
ph2 symbolRelocatable
ph2 symbolType
ph4 symbolValue
ldy #symVal+2 evaluate the expression
lda [sym],Y
pha
@ -864,23 +859,14 @@ sv1 ldy #symExp if the value is an expression then
jsr Evaluate
sta symbolValue save the value
stx symbolValue+2
lda shiftFlag if the value is shifted then
beq sv1a
ph4 name flag the error
ph2 #2
jsr Error
sv1a lda symbolRelocatable if the symbol is relocatable then
beq sv1c
jsr CheckSegment check for errors
ldy #symSeg set the expression file
lda [sym],Y
sta expSegment
sv1c pl4 symbolValue restore volitile variables
pl2 symbolType
pl2 symbolRelocatable
pl2 symbolLength
pl2 symbolCount
pl4 shiftValue
lda shiftFlag if the value is shifted then
beq sv1c
ph4 name flag the error
ph2 #2
jsr Error
sv1c pl4 shiftValue restore volatile variables
pl2 shiftFlag
pl4 shiftCount
pl2 copiedExpression

View File

@ -24,8 +24,14 @@ count equ 1 bit count
sub (4:align),2
stz count count the bits
ldx #16
cmpl align,#$10001 if align > $10000 then
blt lb0
ph4 #0 flag the error (alignment too large)
ph2 #25
jsr Error
lb0 stz count count the bits
ldx #32
lb1 lsr align+2
ror align
bcc lb2
@ -124,6 +130,7 @@ erLev dc I1'8,16,16,2'
dc I1'4,16,2,8'
dc I1'8,4,4,8'
dc I1'8,8,8,8'
dc I1'8'
erAdr dc a'er1-1'
dc a'er2-1'
@ -149,6 +156,7 @@ erAdr dc a'er1-1'
dc a'er22-1'
dc a'er23-1'
dc a'er24-1'
dc a'er25-1'
er1 dw 'Duplicate label'
er2 dw 'Illegal shift operator'
@ -172,6 +180,7 @@ er21 dw 'Alignment and ORG conflict'
er22 dw 'Alignment factor must not exceed segment align factor'
er23 dw 'Alignment factor must be a power of two'
er24 dw 'Expression operand is not in same segment'
er25 dw 'Alignment factor is too large'
end
****************************************************************
@ -382,7 +391,7 @@ lb4 ret
*
* 1: Could not open file <fname>
* 2: Must be an object file: <fname>
* 3: Linker version misatch
* 3: Linker version mismatch
* 4: Illegal header value in <fname>
* 5: Out of memory
* 6: File read error: <fname>
@ -435,7 +444,7 @@ msg dc a'e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15'
e1 dos 'Could not open file '
e2 dos 'Must be an object file: '
e3 dos 'Linker version misatch'
e3 dos 'Linker version mismatch'
e4 dos 'Illegal header value in '
e5 dos 'Out of memory'
e6 dos 'File read error: '

View File

@ -626,3 +626,15 @@
&lab ldx #$0902
jsl $E10000
MEND
macro
&l cmpl &n1,&n2
lclb &yistwo
&l ~setm
~lda.h &n1
~op.h cmp,&n2
bne ~a&SYSCNT
~lda &n1
~op cmp,&n2
~a&SYSCNT anop
~restm
mend