65Org16 Assembler (16-bit bytes, 32-bit address space)
-
teamtempest
- Posts: 443
- Joined: 08 Nov 2009
- Location: Minnesota
- Contact:
Okay, after mulling it over a bit longer I finally realized that a custom loader/programmer would have to be written to handle non-8-bit "bytes" in hexadecimal output files in any case. Call me slow...
The approach outlined above requires awareness of the size of a "byte".
The only other approach I could think of was to adjust the actual address value in 16- or 32-bit bytes back to 8-bit bytes. This is even simpler than what I was thinking of before and keeps compatibility with what 8-bit byte loaders/programmers expect.
However this loses the ability to express at least half the actual address range (a 16-to-8-bit address conversion is made simply by multiplying the actual address by two, so anything in the upper half of the address range goes out of range after multiplication). And the loader/progammer still has to account for the actual address by converting it back.
The first approach seems superior.
So now my thinking is wandering in the direction of how embed information in the output file to let the loader/programmer know it's dealing with non-8-bit "bytes"? That way a single program could handle all formats, thus eliminating one more opportunity for someone to waste time using the wrong utility.
A quick Google search doesn't turn up any "standard" method of extending either format in "non-standard" directions. So some ideas:
1) Introduce a new record type
The 'S4' type is, AFAIK, completely unused in Motorola SRecords. The known Intel types are '00' through '05'. So...'S4' could be used for both
2) Change the start character of each record
Always 'S' and ':', respectively. Could it be 'T' for 16-bit bytes and 'U' for 32-bit bytes?
3) Put the info in the header record
Except that only the Motorola format even has header records. On the other hand, it's probably a good idea to put whatever information is needed into a record that appears before the first data or address record in any case.
Maybe a "PR" for "pragma" data type...or since a loader\programmer has to be written anyway, a new format altogether...
The approach outlined above requires awareness of the size of a "byte".
The only other approach I could think of was to adjust the actual address value in 16- or 32-bit bytes back to 8-bit bytes. This is even simpler than what I was thinking of before and keeps compatibility with what 8-bit byte loaders/programmers expect.
However this loses the ability to express at least half the actual address range (a 16-to-8-bit address conversion is made simply by multiplying the actual address by two, so anything in the upper half of the address range goes out of range after multiplication). And the loader/progammer still has to account for the actual address by converting it back.
The first approach seems superior.
So now my thinking is wandering in the direction of how embed information in the output file to let the loader/programmer know it's dealing with non-8-bit "bytes"? That way a single program could handle all formats, thus eliminating one more opportunity for someone to waste time using the wrong utility.
A quick Google search doesn't turn up any "standard" method of extending either format in "non-standard" directions. So some ideas:
1) Introduce a new record type
The 'S4' type is, AFAIK, completely unused in Motorola SRecords. The known Intel types are '00' through '05'. So...'S4' could be used for both
2) Change the start character of each record
Always 'S' and ':', respectively. Could it be 'T' for 16-bit bytes and 'U' for 32-bit bytes?
3) Put the info in the header record
Except that only the Motorola format even has header records. On the other hand, it's probably a good idea to put whatever information is needed into a record that appears before the first data or address record in any case.
Maybe a "PR" for "pragma" data type...or since a loader\programmer has to be written anyway, a new format altogether...
If you're leaning toward a new format, the hex file format I came up with for The One Page Assembler might be suitable. It could hardly be called a standard, since it has only been used in one application ever, as far as I know. The only extant implementation uses 8-bit data and 16-bit addresses, since it was designed to install The One Page Assembler on a 6502/65C02, but there's nothing about the format itself that restricts the width of data or addresses. I did specifically design it to not limit the width of addresses, to allow both 6502/65C02 16-bit addresses and 65C816 24-bit addresses, but you can use pretty much any address width you choose, and any data width as well (even though that was a specific design consideration).
Although it's a character-oriented format, it can be used as a line-oriented format as well. Tools would simply output lines in a specific format and expect lines of a specific format. In addition, the comment feature could be used to provide an format ID. So you could have something like this:
Specifying the address on every line like that is not necessary, nor is 8 items of data per line, but you could do it if you want the warm fuzzy of something that sorta kinda maybe looks like an S-Record or an Intel HEX file. The 65org16 comment could be treated like an ID.
http://www.lowkey.comuf.com/hexfile.htm
Although it's a character-oriented format, it can be used as a line-oriented format as well. Tools would simply output lines in a specific format and expect lines of a specific format. In addition, the comment feature could be used to provide an format ID. So you could have something like this:
Code: Select all
[65org16]
0001000@0000,0001,0002,0003,0004,0005,0006,0007,
0001008@0008,0009,000A,000B,000C,000D,000E,000F,
0001010@0010,0011,0012,0013,0014,0015,0016,0017,
0001018@0018,0019,001A,001B,001C,001D,001E,001F,
Q
http://www.lowkey.comuf.com/hexfile.htm
-
teamtempest
- Posts: 443
- Joined: 08 Nov 2009
- Location: Minnesota
- Contact:
Interesting. I've taken a look through the various file formats at
http://srecord.sourceforge.net/
and what most of them have in common is (1) no defined way to be extended and (2) no commenting ability. Your format appears similar to one or two of the formats there, with the addition of a commenting ability.
I harp on that because it appears the only way to permit one format to easily support multiple possibilities is to be able to embed some sort of metadata that a loader/progammer can read. A comment is one way to do that.
Right now I'm leaning toward "extending" the Intel and Motorola formats to embed metadata. My latest idea would be for the first data line to have an unmistakable address - the highest the processor permits - followed enough data (more than one 8-bit byte) to push the address past the processor limit if each byte incremented the program counter.
The concept being that the apparent violation should cause the reading program to stop and say "hey, I need to look at this data more closely" and presumably pick out whatever pertinent information it could ("Hey! Bytes are 16 bits long!"). If the reading program couldn't do that, it would presumably just barf, which is okay because it can't handle 16-bit bytes (and the consequent slower address increment rate) anyway.
At any rate that's what I'm thinking today.
As to your idea, one consequence would seem to be that not all output formats HXA offers would always be possible. Yours would presumably always be possible, but sometimes Intel and Motorola would not. I'll mull it over some more.
http://srecord.sourceforge.net/
and what most of them have in common is (1) no defined way to be extended and (2) no commenting ability. Your format appears similar to one or two of the formats there, with the addition of a commenting ability.
I harp on that because it appears the only way to permit one format to easily support multiple possibilities is to be able to embed some sort of metadata that a loader/progammer can read. A comment is one way to do that.
Right now I'm leaning toward "extending" the Intel and Motorola formats to embed metadata. My latest idea would be for the first data line to have an unmistakable address - the highest the processor permits - followed enough data (more than one 8-bit byte) to push the address past the processor limit if each byte incremented the program counter.
The concept being that the apparent violation should cause the reading program to stop and say "hey, I need to look at this data more closely" and presumably pick out whatever pertinent information it could ("Hey! Bytes are 16 bits long!"). If the reading program couldn't do that, it would presumably just barf, which is okay because it can't handle 16-bit bytes (and the consequent slower address increment rate) anyway.
At any rate that's what I'm thinking today.
As to your idea, one consequence would seem to be that not all output formats HXA offers would always be possible. Yours would presumably always be possible, but sometimes Intel and Motorola would not. I'll mull it over some more.
- GARTHWILSON
- Forum Moderator
- Posts: 8774
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
In case it gives you any ideas-- For the PIC16 microcontrollers which have a 13-bit ROM word, the Intel hex file goes like this (the spaces are added here for readability and are not in an actual Intel hex file):
I will only mention what's beyond the usual Intel hex spec. The number of data bytes given at the beginning of the line is twice the number of words. The first group of four digits is the address in the PIC where the first byte in the line goes. Addresses are multiplied by two already; so 400E in the second-to-last line is really 2007. Address words are not expressed low-byte-first like data (ie program) words are. 1E28 in the first like means 281E.
For comments, you could make it so any character besides the hex digits and the colon would make the programmer ignore the rest of the line. Even a space after the hex data before comments would end it. Maybe Intel hex already does that, since the line has to start with a colon (meaning anything else should make the line get ignored), and otherwise it should find the checksum byte after the number of bytes indicated in the count field, and everything after that should be ignored. I haven't tried to see if my EPROM programmer would ignore it. My PIC programmer can do whatever I want it to since I made it and wrote the software too, but I had to make it accept the MPASM output file.
Code: Select all
:02 0000 00 1E28 B8
:08 0008 00 9C00 030E 8312 9D00 11
:10 0010 00 0B11 8C0F 0C28 8D0A 1308 1404 0319 1928 CE
.
.
.
:08 4000 00 0100 0100 0100 0100 B4
:02 400E 00 F73F 7A
:00 0000 01 FFFor comments, you could make it so any character besides the hex digits and the colon would make the programmer ignore the rest of the line. Even a space after the hex data before comments would end it. Maybe Intel hex already does that, since the line has to start with a colon (meaning anything else should make the line get ignored), and otherwise it should find the checksum byte after the number of bytes indicated in the count field, and everything after that should be ignored. I haven't tried to see if my EPROM programmer would ignore it. My PIC programmer can do whatever I want it to since I made it and wrote the software too, but I had to make it accept the MPASM output file.
Last edited by GARTHWILSON on Fri Jun 24, 2011 5:04 pm, edited 1 time in total.
That sounds like a convention to follow, then: addresses in the hex file are not the final word addresses, and the counts are not the word counts. The file acts like an octet-orientated format.
According to the srecord docs, the 'address' for a data record is actually only an offset from a base address (presumably optional and defaulting to zero). So this 16-bit offset, which needs to be halved to become a word address, would be added to a base address previously given, and we don't need to worry about its restricted size.
We would need an Extended Linear Address Record (type 4) to place data beyond the first 32k. We can take the address in that as being a word address - we have to - to give ourselves a full 32-bit addressable space.
How does that sound?
According to the srecord docs, the 'address' for a data record is actually only an offset from a base address (presumably optional and defaulting to zero). So this 16-bit offset, which needs to be halved to become a word address, would be added to a base address previously given, and we don't need to worry about its restricted size.
We would need an Extended Linear Address Record (type 4) to place data beyond the first 32k. We can take the address in that as being a word address - we have to - to give ourselves a full 32-bit addressable space.
How does that sound?
-
teamtempest
- Posts: 443
- Joined: 08 Nov 2009
- Location: Minnesota
- Contact:
Quote:
For comments, you could make it so any character besides the hex digits and the colon would make the programmer ignore the rest of the line.
AFAIK there is no defined method of creating a "comment" record in an Intel hexfile (or Motorola SRecord). Which makes the reaction of programmers to "invalid" records about as varied as the number of programmers, in my understanding.
Quote:
We would need an Extended Linear Address Record (type 4) to place data beyond the first 32k. We can take the address in that as being a word address - we have to - to give ourselves a full 32-bit addressable space.
So the top 32K of the address range is still out of reach. In fact...now that I think about it...isn't it the case that for whatever 16 bits gets put into a type 4 record, if the address range of any following type 0 record is interperted as only 15 bits, there's no way to address more than 2^31 locations (in 32K chunks followed by 32K "holes"). Not the full 2^32 address range of the processor.
Bottom line: I think the address offsets in Intel hex records need to be treated as word address offsets in order to get the full 2^32 address range. Unless I'm mis-interpreting something...?
HXA outputs Intel hex and Motorola SRecords in one or more "chunks", the basis of which isn't important here. But as it's currently written, a single "chunk" for a 32-bit processor with a 16-bit "byte" size will start off something like this for an Intel hex file with base word address $FFFFE000:
Code: Select all
:02 0000 04 FFFF xx
:10 E000 00 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 xx
:10 E010 00 08 00 09 00 0A 00 0B 00 0C 00 0D 00 0E 00 0F 00 xx
Motorola SRecords, which do not split the address into base/offset, but rather outputs it whole in each data record, suffer from the same problem. In either case the first address of a "chunk" will be word-correct but all successive addresses will not.
Now then here's the big question: even if one wished to write a programmer to accept this output and then "correct" the address within itself, how would it know which addresses were word-correct and which weren't?
Someone might say that all that must be done is to use a type 4 record as a flag, and yes that would work for an Intel hex file. There wouldn't be a reliable means to differentiate them in a Motorola SRecord. Moreover, it would mean giving up half the address range for a 16-bit "byte" processor (and 3/4ths for a 32-bit "byte").
What I propose to do is make the addresses in Intel and Motorola output files byte- or word- or long-correct, as required by whatever processor is in use. This enables the full address range and is actually quite easy; I can adjust both formats by altering, um, two lines of code. I can avoid a sticky question regarding 64K boundaries in Intel hex files by altering three. I'd probably also add one line to get rid of a division in a loop boundary check (since the result would be a constant anyway and it seems like a waste of processor power to keep re-computing it).
But given that, how is a programmer/loader/whatever going to know that the addresses are byte- or word- or long-correct?
One solution is to require the user to know, and then pass that knowledge on to the programmer or use a specific programmer that understands just one of those. It solves the problem but seems both error-prone and like a lot of unnecessary effort. It might be acceptable for limited use if nothing better is available.
Hence all the musing about "metadata" and alternative and extended formats. If some convention was arrived at and implemented a programmer/whatever could figure out for itself what it needed to do.
teamtempest wrote:
Quote:
We would need an Extended Linear Address Record (type 4) ...
So the top 32K of the address range is still out of reach.
So, we have to drop these octet-orientated formats, which is what you were suspecting, and explicitly signal that we need word addresses (and 32-bit addresses)
In Intel format, record types 0-5 seem to be defined, so we can pick a new type, such as 14 (decimal), for a data record suiting our purposes.
In Moto format, S0 to S9 are defined: we could pick SE for our purposes.
(That would leave types 15 and SF free for a 32-bit word format for 65Org32)
Or, as you muse, a more self-describing format (with more complexity) could do the trick.
I'd prefer not to have to write a complex loader, though. My current plan is to make minimal changes to Ross Archer's Intel format loader - a variant record type or a variant initial character are both fine for me. ASCII proceeds ':' then ';' then '<' so I might suggest those characters for 8 then 16 then 32-bit word formats.
Cheers
Ed
-
teamtempest
- Posts: 443
- Joined: 08 Nov 2009
- Location: Minnesota
- Contact:
For Intel hex the present HXA "line writer" looks like this at the relevant part:
To change the initial character to one of ":", ";" or "<" this change works for 8-, 16- and 32-bit "bytes":
A similar change to Motorola output gives "S", "T" and "U" as leading initial characters.
To change the record types so they're $00-05 for 8-bit, $10-15 for 16-bit and $20-25 for 32-bit (allowing easy visual inspection by looking at the first character of a record type pair):
where "typeOffset" is set during initialization to whatever it should be ('course it also likely the "initial char" approach would actually do the same to avoid repeated re-calculation of a constant).
Treating the Motorola format the same way works, using perhaps 'SA-SI' ($41-49) and 'SQ-SY' ($51-59) to with 'S0-S9' ($31-39).
Either approach seems fairly simple.
My quandry is my impression that the boosted record type number is "prettier" in the Intel case (and more extensible), but the boosted initial character is "prettier" in the Motorola case (and more extensible). My desire for consistency is in conflict with my esthetic sense.
Code: Select all
prefix = sprintf( ":%02X%04X%02X%s", cnt, offset, type, hex )
Code: Select all
prefix = sprintf( "%c%02X%04X%02X%s", ord(":") + int(byteSize/2), cnt, offset, type, hex )
To change the record types so they're $00-05 for 8-bit, $10-15 for 16-bit and $20-25 for 32-bit (allowing easy visual inspection by looking at the first character of a record type pair):
Code: Select all
prefix = sprintf( ":%02X%04X%02X%s", cnt, offset, type+typeOffset, hex )
Treating the Motorola format the same way works, using perhaps 'SA-SI' ($41-49) and 'SQ-SY' ($51-59) to with 'S0-S9' ($31-39).
Either approach seems fairly simple.
My quandry is my impression that the boosted record type number is "prettier" in the Intel case (and more extensible), but the boosted initial character is "prettier" in the Motorola case (and more extensible). My desire for consistency is in conflict with my esthetic sense.
-
teamtempest
- Posts: 443
- Joined: 08 Nov 2009
- Location: Minnesota
- Contact:
Quote:
I'd prefer not to have to write a complex loader, though. My current plan is to make minimal changes to Ross Archer's Intel format loader - a variant record type or a variant initial character are both fine for me. ASCII proceeds ':' then ';' then '<' so I might suggest those characters for 8 then 16 then 32-bit word formats.
I'm not so sure only 'minimal' changes will be needed, though. I think it'll need a bit of buffering that the present version doesn't have to collect both octets of a 16-bit "byte" before storage, for instance. It'll have to understand at least one more record type. If you want it to be able to figure out what to do based on an initial char or record type, that'll take some additional code as well.
On the plus side, it doesn't seem that difficult. Just a bit more work is all
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
Ok. I have my assembler producing code for this new beast. The test file comes out like this:
Where is the latest opcode table for the FPGA. I need to check if you have the 65SC02 bit instructions and the indirect mode.
Just the linker to patch up now.
Code: Select all
Portable 65016 Assembler - V0.1 (2011-06-26)
.EXTERN ExtLab
.GLOBAL GblLab
.CODE
.EXTERN LABA
.EXTERN LABB
.EXTERN LABC
00000000' = LABD .EQU (LABA-LABB)*2+LABC/3
;==============================================================================
; Test conditional compilation
;------------------------------------------------------------------------------
.IF 1
.IF 1
00000000' 00EA : NOP ;++
.ELSE
- NOP ;--
.ENDIF
.ELSE
.IF 1
- NOP ;--
.ELSE
- NOP ;--
.ENDIF
.ENDIF
;==============================================================================
; Test repeat sections
;------------------------------------------------------------------------------
.IF 1
.REPEAT 4
NOP
.ENDR
00000001' 00EA + NOP
00000002' 00EA + NOP
00000003' 00EA + NOP
00000004' 00EA + NOP
.ELSE
- .REPEAT 4
- CLC
- .ENDR
.ENDIF
;==============================================================================
; Test macros sections
;------------------------------------------------------------------------------
00000005' M1 .MACRO
CLC
Portable 65016 Assembler - V0.1 (2011-06-26)
.REPEAT 3
NOP
.ENDR
CLI
.ENDM
M1
00000005' 0018 + CLC
+ .REPEAT 3
+ NOP
+ .ENDR
00000006' 00EA + NOP
00000007' 00EA + NOP
00000008' 00EA + NOP
00000009' 0058 + CLI
0000000A' M2 .MACRO VA,VB,VC
.BYTE VA,VB,VC
0000000A' L\? .BYTE \0,\1,\2
.ENDM
M2 1,"Hello",2+5
0000000A' 000100480065006C> + .BYTE 1,"Hello",2+5
00000011' 000100480065006C> + L2 .BYTE 1,"Hello",2+5
00000018' M3 .MACRO
M1
M2 2,"World",ExtLab
.ENDM
M3
+ M1
00000018' 0018 + CLC
+ .REPEAT 3
+ NOP
+ .ENDR
00000019' 00EA + NOP
0000001A' 00EA + NOP
0000001B' 00EA + NOP
0000001C' 0058 + CLI
+ M2 2,"World",ExtLab
0000001D' 00020057006F0072> + .BYTE 2,"World",ExtLab
00000024' 00020057006F0072> + L5 .BYTE 2,"World",ExtLab
0000002B' OPCODE .MACRO A,B,C
.WORD ((\0 - '@') << 10) | ((\1 - '@') << 5) | (\2 - '@')
.ENDM
OPCODE 'B','R','K'
0000002B' 0A4B0000 + .WORD (('B' - '@') << 10) | (('R' - '@') << 5) | ('K' - '@')
;==============================================================================
; Test size of address generated for global/external references
Portable 65016 Assembler - V0.1 (2011-06-26)
;------------------------------------------------------------------------------
0000002D' : GblLab:
0000002D' 004C00000000 : JMP GblLab
00000030' 004C00000000 : JMP ExtLab
00000033' 006C00000000 : JMP (GblLab)
00000036' 006C00000000 : JMP (ExtLab)
00000039' 002000000000 : JSR GblLab
0000003C' 002000000000 : JSR ExtLab
000004D2 = FIXED .EQU 1234
00000006' = UNKNWN .EQU ExtLab+2*3
00000000 = COUNT .SET 0
00000001 = COUNT .SET COUNT+1
;==============================================================================
; 65016 Opcodes & Addressing modes
;------------------------------------------------------------------------------
0000003F' 00691234 : ADC #$1234
00000041' 00651234 : ADC <$1234
00000043' 00751234 : ADC <$1234,X
00000045' 006D56781234 : ADC $12345678
00000048' 007D56781234 : ADC $12345678,X
0000004B' 007956781234 : ADC $12345678,Y
0000004E' 00611234 : ADC ($1234,X)
00000050' 00711234 : ADC ($1234),Y
00000052' 00721234 : ADC ($1234)
00000054' 00291234 : AND #$1234
00000056' 00251234 : AND <$1234
00000058' 00351234 : AND <$1234,X
0000005A' 002D56781234 : AND $12345678
0000005D' 003D56781234 : AND $12345678,X
00000060' 003956781234 : AND $12345678,Y
00000063' 00211234 : AND ($1234,X)
00000065' 00311234 : AND ($1234),Y
00000067' 00321234 : AND ($1234)
00000069' 000A : ASL A
0000006A' 00061234 : ASL <$1234
0000006C' 00161234 : ASL <$1234,X
0000006E' 000E56781234 : ASL $12345678
00000071' 001E56781234 : ASL $12345678,X
00000074' 000F12340000 : BBR0 $1234,$+3
00000077' 001F12340000 : BBR1 $1234,$+3
0000007A' 002F12340000 : BBR2 $1234,$+3
0000007D' 003F12340000 : BBR3 $1234,$+3
00000080' 004F12340000 : BBR4 $1234,$+3
00000083' 005F12340000 : BBR5 $1234,$+3
00000086' 006F12340000 : BBR6 $1234,$+3
00000089' 007F12340000 : BBR7 $1234,$+3
0000008C' 008F12340000 : BBS0 $1234,$+3
0000008F' 009F12340000 : BBS1 $1234,$+3
00000092' 00AF12340000 : BBS2 $1234,$+3
Portable 65016 Assembler - V0.1 (2011-06-26)
00000095' 00BF12340000 : BBS3 $1234,$+3
00000098' 00CF12340000 : BBS4 $1234,$+3
0000009B' 00DF12340000 : BBS5 $1234,$+3
0000009E' 00EF12340000 : BBS6 $1234,$+3
000000A1' 00FF12340000 : BBS7 $1234,$+3
000000A4' 00900000 : BCC $+2
000000A6' 00B00000 : BCS $+2
000000A8' 00F00000 : BEQ $+2
000000AA' 00241234 : BIT <$1234
000000AC' 002C56781234 : BIT $12345678
000000AF' 00341234 : BIT <$1234,X
000000B1' 003C56781234 : BIT $12345678,X
000000B4' 00391234 : BIT #$1234
000000B6' 00300000 : BMI $+2
000000B8' 00D00000 : BNE $+2
000000BA' 00100000 : BPL $+2
000000BC' 00800000 : BRA $+2
000000BE' 0000 : BRK
000000BF' 00500000 : BVC $+2
000000C1' 00700000 : BVS $+2
000000C3' 0018 : CLC
000000C4' 00D8 : CLD
000000C5' 0058 : CLI
000000C6' 00B8 : CLV
000000C7' 00C91234 : CMP #$1234
000000C9' 00C51234 : CMP <$1234
000000CB' 00D51234 : CMP <$1234,X
000000CD' 00CD56781234 : CMP $12345678
000000D0' 00DD56781234 : CMP $12345678,X
000000D3' 00D956781234 : CMP $12345678,Y
000000D6' 00C11234 : CMP ($1234,X)
000000D8' 00D11234 : CMP ($1234),Y
000000DA' 00D21234 : CMP ($1234)
000000DC' 00E01234 : CPX #$1234
000000DE' 00E41234 : CPX <$1234
000000E0' 00EC56781234 : CPX $12345678
000000E3' 00C01234 : CPY #$1234
000000E5' 00C41234 : CPY <$1234
000000E7' 00CC56781234 : CPY $12345678
000000EA' 00C61234 : DEC <$1234
000000EC' 00D61234 : DEC <$1234,X
000000EE' 00CE56781234 : DEC $12345678
000000F1' 00DE56781234 : DEC $12345678,X
000000F4' 003A : DEC A
000000F5' 00CA : DEX
000000F6' 0088 : DEY
000000F7' 00491234 : EOR #$1234
000000F9' 00451234 : EOR <$1234
000000FB' 00551234 : EOR <$1234,X
000000FD' 004D56781234 : EOR $12345678
00000100' 005D56781234 : EOR $12345678,X
00000103' 005956781234 : EOR $12345678,Y
00000106' 00411234 : EOR ($1234,X)
00000108' 00511234 : EOR ($1234),Y
Portable 65016 Assembler - V0.1 (2011-06-26)
0000010A' 00521234 : EOR ($1234)
0000010C' 00E61234 : INC <$1234
0000010E' 00F61234 : INC <$1234,X
00000110' 00EE56781234 : INC $12345678
00000113' 00FE56781234 : INC $12345678,X
00000116' 001A : INC A
00000117' 00E8 : INX
00000118' 00C8 : INY
00000119' 004C56781234 : JMP $12345678
0000011C' 006C56781234 : JMP ($12345678)
0000011F' 007C56781234 : JMP ($12345678,X)
00000122' 002056781234 : JSR $12345678
00000125' 00A91234 : LDA #$1234
00000127' 00A51234 : LDA <$1234
00000129' 00B51234 : LDA <$1234,X
0000012B' 00AD56781234 : LDA $12345678
0000012E' 00BD56781234 : LDA $12345678,X
00000131' 00B956781234 : LDA $12345678,Y
00000134' 00A11234 : LDA ($1234,X)
00000136' 00B11234 : LDA ($1234),Y
00000138' 00B21234 : LDA ($1234)
0000013A' 00A21234 : LDX #$1234
0000013C' 00A61234 : LDX <$1234
0000013E' 00B61234 : LDX <$1234,Y
00000140' 00AE56781234 : LDX $12345678
00000143' 00BE56781234 : LDX $12345678,Y
00000146' 00A01234 : LDY #$1234
00000148' 00A41234 : LDY <$1234
0000014A' 00B41234 : LDY <$1234,X
0000014C' 00AC56781234 : LDY $12345678
0000014F' 00BC56781234 : LDY $12345678,X
00000152' 004A : LSR A
00000153' 00461234 : LSR <$1234
00000155' 00561234 : LSR <$1234,X
00000157' 004E56781234 : LSR $12345678
0000015A' 005E56781234 : LSR $12345678,X
0000015D' 00EA : NOP
0000015E' 00091234 : ORA #$1234
00000160' 00051234 : ORA <$1234
00000162' 00151234 : ORA <$1234,X
00000164' 000D56781234 : ORA $12345678
00000167' 001D56781234 : ORA $12345678,X
0000016A' 001956781234 : ORA $12345678,Y
0000016D' 00011234 : ORA ($1234,X)
0000016F' 00111234 : ORA ($1234),Y
00000171' 00121234 : ORA ($1234)
00000173' 0048 : PHA
00000174' 0008 : PHP
00000175' 00DA : PHX
00000176' 005A : PHY
00000177' 0068 : PLA
00000178' 0028 : PLP
00000179' 00FA : PLX
0000017A' 007A : PLY
Portable 65016 Assembler - V0.1 (2011-06-26)
0000017B' 00071234 : RMB0 $1234
0000017D' 00171234 : RMB1 $1234
0000017F' 00271234 : RMB2 $1234
00000181' 00371234 : RMB3 $1234
00000183' 00471234 : RMB4 $1234
00000185' 00571234 : RMB5 $1234
00000187' 00671234 : RMB6 $1234
00000189' 00771234 : RMB7 $1234
0000018B' 002A : ROL A
0000018C' 00261234 : ROL <$1234
0000018E' 00361234 : ROL <$1234,X
00000190' 002E56781234 : ROL $12345678
00000193' 003E56781234 : ROL $12345678,X
00000196' 006A : ROR A
00000197' 00661234 : ROR <$1234
00000199' 00761234 : ROR <$1234,X
0000019B' 006E56781234 : ROR $12345678
0000019E' 007E56781234 : ROR $12345678,X
000001A1' 0040 : RTI
000001A2' 0060 : RTS
000001A3' 00E91234 : SBC #$1234
000001A5' 00E51234 : SBC <$1234
000001A7' 00F51234 : SBC <$1234,X
000001A9' 00ED56781234 : SBC $12345678
000001AC' 00FD56781234 : SBC $12345678,X
000001AF' 00F956781234 : SBC $12345678,Y
000001B2' 00E11234 : SBC ($1234,X)
000001B4' 00F11234 : SBC ($1234),Y
000001B6' 00F21234 : SBC ($1234)
000001B8' 0038 : SEC
000001B9' 00F8 : SED
000001BA' 0078 : SEI
000001BB' 00871234 : SMB0 $1234
000001BD' 00971234 : SMB1 $1234
000001BF' 00A71234 : SMB2 $1234
000001C1' 00B71234 : SMB3 $1234
000001C3' 00C71234 : SMB4 $1234
000001C5' 00D71234 : SMB5 $1234
000001C7' 00E71234 : SMB6 $1234
000001C9' 00F71234 : SMB7 $1234
000001CB' 00851234 : STA <$1234
000001CD' 00951234 : STA <$1234,X
000001CF' 008D56781234 : STA $12345678
000001D2' 009D56781234 : STA $12345678,X
000001D5' 009956781234 : STA $12345678,Y
000001D8' 00811234 : STA ($1234,X)
000001DA' 00911234 : STA ($1234),Y
000001DC' 00921234 : STA ($1234)
000001DE' 00DB : STP
000001DF' 00861234 : STX <$1234
000001E1' 00961234 : STX <$1234,Y
000001E3' 008E56781234 : STX $12345678
000001E6' 00841234 : STY <$1234
000001E8' 00941234 : STY <$1234,X
Portable 65016 Assembler - V0.1 (2011-06-26)
000001EA' 008C56781234 : STY $12345678
000001ED' 00641234 : STZ <$1234
000001EF' 00741234 : STZ <$1234,X
000001F1' 009C56781234 : STZ $12345678
000001F4' 009E56781234 : STZ $12345678,X
000001F7' 00AA : TAX
000001F8' 00A8 : TAY
000001F9' 00141234 : TRB $1234
000001FB' 001C56781234 : TRB $12345678
000001FE' 00041234 : TSB $1234
00000200' 000C56781234 : TSB $12345678
00000203' 00BA : TSX
00000204' 008A : TXA
00000205' 009A : TXS
00000206' 0098 : TYA
00000207' 00CB : WAI
00000208' 0000007E : BRK #$7E ; Test BRK extension
;==============================================================================
; 65SC06 Opcodes & Addressing modes
;------------------------------------------------------------------------------
0000020A' 00691234 : ADC #$1234
0000020C' 00651234 : ADC <$1234
0000020E' 00751234 : ADC <$1234,X
00000210' 006D56781234 : ADC $12345678
00000213' 007D56781234 : ADC $12345678,X
00000216' 007956781234 : ADC $12345678,Y
00000219' 00611234 : ADC ($1234,X)
0000021B' 00711234 : ADC ($1234),Y
0000021D' 00721234 : ADC ($1234)
0000021F' 00291234 : AND #$1234
00000221' 00251234 : AND <$1234
00000223' 00351234 : AND <$1234,X
00000225' 002D56781234 : AND $12345678
00000228' 003D56781234 : AND $12345678,X
0000022B' 003956781234 : AND $12345678,Y
0000022E' 00211234 : AND ($1234,X)
00000230' 00311234 : AND ($1234),Y
00000232' 00321234 : AND ($1234)
00000234' 000A : ASL A
00000235' 00061234 : ASL <$1234
00000237' 00161234 : ASL <$1234,X
00000239' 000E56781234 : ASL $12345678
0000023C' 001E56781234 : ASL $12345678,X
0000023F' 00900000 : BCC $+2
00000241' 00B00000 : BCS $+2
00000243' 00F00000 : BEQ $+2
00000245' 00241234 : BIT <$1234
00000247' 002C56781234 : BIT $12345678
0000024A' 00341234 : BIT <$1234,X
0000024C' 003C56781234 : BIT $12345678,X
0000024F' 00391234 : BIT #$1234
Portable 65016 Assembler - V0.1 (2011-06-26)
00000251' 00300000 : BMI $+2
00000253' 00D00000 : BNE $+2
00000255' 00100000 : BPL $+2
00000257' 00800000 : BRA $+2
00000259' 0000 : BRK
0000025A' 00500000 : BVC $+2
0000025C' 00700000 : BVS $+2
0000025E' 0018 : CLC
0000025F' 00D8 : CLD
00000260' 0058 : CLI
00000261' 00B8 : CLV
00000262' 00C91234 : CMP #$1234
00000264' 00C51234 : CMP <$1234
00000266' 00D51234 : CMP <$1234,X
00000268' 00CD56781234 : CMP $12345678
0000026B' 00DD56781234 : CMP $12345678,X
0000026E' 00D956781234 : CMP $12345678,Y
00000271' 00C11234 : CMP ($1234,X)
00000273' 00D11234 : CMP ($1234),Y
00000275' 00D21234 : CMP ($1234)
00000277' 00E01234 : CPX #$1234
00000279' 00E41234 : CPX <$1234
0000027B' 00EC56781234 : CPX $12345678
0000027E' 00C01234 : CPY #$1234
00000280' 00C41234 : CPY <$1234
00000282' 00CC56781234 : CPY $12345678
00000285' 00C61234 : DEC <$1234
00000287' 00D61234 : DEC <$1234,X
00000289' 00CE56781234 : DEC $12345678
0000028C' 00DE56781234 : DEC $12345678,X
0000028F' 003A : DEC A
00000290' 00CA : DEX
00000291' 0088 : DEY
00000292' 00491234 : EOR #$1234
00000294' 00451234 : EOR <$1234
00000296' 00551234 : EOR <$1234,X
00000298' 004D56781234 : EOR $12345678
0000029B' 005D56781234 : EOR $12345678,X
0000029E' 005956781234 : EOR $12345678,Y
000002A1' 00411234 : EOR ($1234,X)
000002A3' 00511234 : EOR ($1234),Y
000002A5' 00521234 : EOR ($1234)
000002A7' 00E61234 : INC <$1234
000002A9' 00F61234 : INC <$1234,X
000002AB' 00EE56781234 : INC $12345678
000002AE' 00FE56781234 : INC $12345678,X
000002B1' 001A : INC A
000002B2' 00E8 : INX
000002B3' 00C8 : INY
000002B4' 004C56781234 : JMP $12345678
000002B7' 006C56781234 : JMP ($12345678)
000002BA' 007C56781234 : JMP ($12345678,X)
000002BD' 002056781234 : JSR $12345678
000002C0' 00A91234 : LDA #$1234
Portable 65016 Assembler - V0.1 (2011-06-26)
000002C2' 00A51234 : LDA <$1234
000002C4' 00B51234 : LDA <$1234,X
000002C6' 00AD56781234 : LDA $12345678
000002C9' 00BD56781234 : LDA $12345678,X
000002CC' 00B956781234 : LDA $12345678,Y
000002CF' 00A11234 : LDA ($1234,X)
000002D1' 00B11234 : LDA ($1234),Y
000002D3' 00B21234 : LDA ($1234)
000002D5' 00A21234 : LDX #$1234
000002D7' 00A61234 : LDX <$1234
000002D9' 00B61234 : LDX <$1234,Y
000002DB' 00AE56781234 : LDX $12345678
000002DE' 00BE56781234 : LDX $12345678,Y
000002E1' 00A01234 : LDY #$1234
000002E3' 00A41234 : LDY <$1234
000002E5' 00B41234 : LDY <$1234,X
000002E7' 00AC56781234 : LDY $12345678
000002EA' 00BC56781234 : LDY $12345678,X
000002ED' 004A : LSR A
000002EE' 00461234 : LSR <$1234
000002F0' 00561234 : LSR <$1234,X
000002F2' 004E56781234 : LSR $12345678
000002F5' 005E56781234 : LSR $12345678,X
000002F8' 00EA : NOP
000002F9' 00091234 : ORA #$1234
000002FB' 00051234 : ORA <$1234
000002FD' 00151234 : ORA <$1234,X
000002FF' 000D56781234 : ORA $12345678
00000302' 001D56781234 : ORA $12345678,X
00000305' 001956781234 : ORA $12345678,Y
00000308' 00011234 : ORA ($1234,X)
0000030A' 00111234 : ORA ($1234),Y
0000030C' 00121234 : ORA ($1234)
0000030E' 0048 : PHA
0000030F' 0008 : PHP
00000310' 00DA : PHX
00000311' 005A : PHY
00000312' 0068 : PLA
00000313' 0028 : PLP
00000314' 00FA : PLX
00000315' 007A : PLY
00000316' 002A : ROL A
00000317' 00261234 : ROL <$1234
00000319' 00361234 : ROL <$1234,X
0000031B' 002E56781234 : ROL $12345678
0000031E' 003E56781234 : ROL $12345678,X
00000321' 006A : ROR A
00000322' 00661234 : ROR <$1234
00000324' 00761234 : ROR <$1234,X
00000326' 006E56781234 : ROR $12345678
00000329' 007E56781234 : ROR $12345678,X
0000032C' 0040 : RTI
0000032D' 0060 : RTS
0000032E' 00E91234 : SBC #$1234
Portable 65016 Assembler - V0.1 (2011-06-26)
00000330' 00E51234 : SBC <$1234
00000332' 00F51234 : SBC <$1234,X
00000334' 00ED56781234 : SBC $12345678
00000337' 00FD56781234 : SBC $12345678,X
0000033A' 00F956781234 : SBC $12345678,Y
0000033D' 00E11234 : SBC ($1234,X)
0000033F' 00F11234 : SBC ($1234),Y
00000341' 00F21234 : SBC ($1234)
00000343' 0038 : SEC
00000344' 00F8 : SED
00000345' 0078 : SEI
00000346' 00851234 : STA <$1234
00000348' 00951234 : STA <$1234,X
0000034A' 008D56781234 : STA $12345678
0000034D' 009D56781234 : STA $12345678,X
00000350' 009956781234 : STA $12345678,Y
00000353' 00811234 : STA ($1234,X)
00000355' 00911234 : STA ($1234),Y
00000357' 00921234 : STA ($1234)
00000359' 00DB : STP
0000035A' 00861234 : STX <$1234
0000035C' 00961234 : STX <$1234,Y
0000035E' 008E56781234 : STX $12345678
00000361' 00841234 : STY <$1234
00000363' 00941234 : STY <$1234,X
00000365' 008C56781234 : STY $12345678
00000368' 00641234 : STZ <$1234
0000036A' 00741234 : STZ <$1234,X
0000036C' 009C56781234 : STZ $12345678
0000036F' 009E56781234 : STZ $12345678,X
00000372' 00AA : TAX
00000373' 00A8 : TAY
00000374' 00141234 : TRB $1234
00000376' 001C56781234 : TRB $12345678
00000379' 00041234 : TSB $1234
0000037B' 000C56781234 : TSB $12345678
0000037E' 00BA : TSX
0000037F' 008A : TXA
00000380' 009A : TXS
00000381' 0098 : TYA
00000382' 00CB : WAI
00000383' 0000007E : BRK #$7E ; Test BRK extension
;==============================================================================
; Structured Assembly Code
;------------------------------------------------------------------------------
; A mixture of loops and ifs
00000385' 00A00000 : LDY #0
REPEAT
00000387' 0098 : TYA
00000388' 00A20000 : LDX #0
Portable 65016 Assembler - V0.1 (2011-06-26)
REPEAT
0000038A' 000A : ASL A
0000038B' 0008 : PHP
0000038C' 00900001 : IF CS
0000038E' 00E8 : INX
ENDIF
0000038F' 0028 : PLP
00000390' 00D0FFF8 : UNTIL EQ
00000392' 00C8 : INY
00000393' 00C00080 : CPY #128
00000395' 00D00002 : IF EQ
00000397' 00800002 : BREAK
ENDIF
00000399' 0080FFEC : FOREVER
; Nonsense code to show long branches
.ORG $E000
0000E000 00B00103 : WHILE CC
.REPEAT 16
.BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
.ENDR
0000E002 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E012 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E022 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E032 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E042 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E052 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E062 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E072 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E082 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E092 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E0A2 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E0B2 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E0C2 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E0D2 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E0E2 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E0F2 00EA00EA00EA00EA> + .BYTE $EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA,$EA
0000E102 000A : ASL A
0000E103 0080FEFB : ENDW
;==============================================================================
; Data Related Directives
;------------------------------------------------------------------------------
.DATA
00000000' 000100020003 : .BYTE 1,2,3
00000003' 000B : .BYTE 1+2*3+4
00000004' 004100420043 : .BYTE 'A','B','C'
00000007' 00480065006C006C> : .BYTE "Hello World",13,10
00000014' 00000000 : .BYTE LO ($+2),HI ($+2)
00000016' 0001000000020000> : .WORD 1,2,3
Portable 65016 Assembler - V0.1 (2011-06-26)
0000001C' 00000000 : .WORD $+3
0000001E' 00080000 : .WORD ($+10)-($+2)
00000020' 0001000000010000> : .LONG 1,2,3
; .END
Portable 65016 Assembler - V0.1 (2011-06-26)
Symbol Table
COUNT 00000001
ExtLab 00000000'
FIXED 000004D2
GblLab 0000002D'
L2 00000011'
L5 00000024'
LABA 00000000'
LABB 00000000'
LABC 00000000'
LABD 00000000'
UNKNWN 00000006'
Just the linker to patch up now.
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
Hi Bitwise, that's looking good! Not sure about this bit tho:
Are you on board with the loader discussion?
Cheers
Ed
Code: Select all
00000014' 00000000 : .BYTE LO ($+2),HI ($+2)
Cheers
Ed
teamtempest wrote:
I took a brief look at Archer's loader...
...it'll need a bit of buffering ... to collect both octets of a 16-bit "byte" before storage, for instance. It'll have to understand at least one more record type. If you want it to be able to figure out what to do based on an initial char or record type, that'll take some additional code as well.
On the plus side, it doesn't seem that difficult. Just a bit more work is all :D
...it'll need a bit of buffering ... to collect both octets of a 16-bit "byte" before storage, for instance. It'll have to understand at least one more record type. If you want it to be able to figure out what to do based on an initial char or record type, that'll take some additional code as well.
On the plus side, it doesn't seem that difficult. Just a bit more work is all :D
Cheers
Ed
- BitWise
- In Memoriam
- Posts: 996
- Joined: 02 Mar 2004
- Location: Berkshire, UK
- Contact:
BigEd wrote:
Hi Bitwise, that's looking good! Not sure about this bit tho:
Are you on board with the loader discussion?
Cheers
Ed
Code: Select all
00000014' 00000000 : .BYTE LO ($+2),HI ($+2)
Cheers
Ed
I've been following the loader discussion but have decided what to implement in the linker yet.
Oh and I changed the expression evaluation to 64-bit to allow .LONG to work properly.
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs