65Org16 Assembler (16-bit bytes, 32-bit address space)

Programming the 6502 microprocessor and its relatives in assembly and other languages.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

Bitwise, is it possible to add data tables in your 65Org16 assembler?. In MK's assembler it looks like this:

Code: Select all

coltable	.DB $00,$00,$00,$00,$FF,$FF,$FF,$00,$68,$37,$2B,$00,$70,$A4,$B2,$00	;4-bit C-64
TIA
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Post by BigEd »

Hi EE
I think the .byte directive does what you want:
Quote:
The .BYTE directive deposits a series of 8-bit values into the object code for the current module. The values can be defined as the result of an expression (this includes simple numeric values) or as strings delimited by quotes.

Code: Select all

        .BYTE "Hello World",$0D,$0A,0
With some help from the two authors, I've been able to get Bill's TinyBasic reconstructed source (of Tom Pittman's binary) into a form which assembles with both assemblers, with the only variation being a swapping between two include headers:

Code: Select all

   .include "header-dev65.asm"
;  .include "header-hxa.asm"
I've found that HXA sometimes gives clearer diagnostics, but dev65 is an easier route to binaries for ROM images. Anyhow, it's good to have portable sources.

Those headers are simple enough:

Code: Select all

==> header-dev65.asm <==
;; assembly header for Dev65 assembler
;;    http://www.obelisk.demon.co.uk/dev65/as65.html

mesg .macro sometext 
     .byte  sometext
     .endm

Code: Select all

==> header-hxa.asm <==
;; assembly header for HXA assembler
;;    http://home.earthlink.net/~hxa/docs/hxa.htm#l7e

        .hexfile
        .listfile
        .errfile

        .cpu T_32_M16
        .assume BIT32=1032, BIT32R=3210
        .include "i6502.a"

macro mesg, ?sometext
        .str ?sometext
.endm
The other useful thing I have is a sign-extension macro, where I have a table of 8-bit bytes which are going to be treated as signed (so BPL, BMI, BIT are likely to be used)

Code: Select all

;; sign extension - will set Z and N, but disturbs C and V
signextend .macro dummy
      eor #$80
      sec
      sbc #$80
      .endm
I could preserve C and V if I use a temporary: this is untested, and suggestions for improvement are welcome:

Code: Select all

;; untested! sign extension - will set Z and N, preserve C and V
signextend .macro dummy
      php
      eor #$80
      sec
      sbc #$80
      sta atemp
      plp
      lda atemp
      .endm
(Probably this macro syntax is only good for dev65)

Both of those macros also work on 6502, but just waste some cycles.

(I've also been aiming to assemble the same source for both 6502 and 65Org16 - so far that's been possible, but I haven't yet got TinyBasic working.)

Cheers
Ed
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

Forgive another stupid question, but I am getting "Illegal addressing mode" when trying to use ASL, LSR, ROL, ROR...

Ah, never mind, Must enter as ASL A, etc... Sorry
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Post by BigDumbDinosaur »

ElEctric_EyE wrote:
Forgive another stupid question, but I am getting "Illegal addressing mode" when trying to use ASL, LSR, ROL, ROR...

Ah, never mind, Must enter as ASL A, etc... Sorry
ASL A, etc., is correct MOS Technology syntax. It's based on the notion that instructions that are able to address memory and accumulator should have an operand.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
teamtempest
Posts: 443
Joined: 08 Nov 2009
Location: Minnesota
Contact:

Post by teamtempest »

Quote:
ASL A, etc., is correct MOS Technology syntax. It's based on the notion that instructions that are able to address memory and accumulator should have an operand.
Mebbe so, but there's also the notion that it's unnecessary clutter. Since no instruction on any 65xx- variant that allows implied addressing also allows accumulator addressing, and vice versa, it's no problem for an assembler to determine the proper code to emit even in the absence of an 'A' in the operand field.

Of course you already know that. Never mind :oops:

Turning to an earlier post:
Quote:
Code:
;; untested! sign extension - will set Z and N, preserve C and V
signextend .macro dummy
php
eor #$80
sec
sbc #$80
sta atemp
plp
lda atemp
.endm



(Probably this macro syntax is only good for dev65)
If you're referring to putting the macro name before the ".macro" pseudo op and any formal arguments after it, that is a very common style, so HXA supports that. I sometimes have a long name that throws off list formatting if I put it before the pseudo op, so I tend to put both name and arguments after, but whatever works.

The formal argument 'dummy' would have to be written '?dummy' to be what HXA likes to see, but that fact that it isn't used wouldn't be a problem. Simpler just to leave it out altogether, though.
Quote:
I've found that HXA sometimes gives clearer diagnostics, but dev65 is an easier route to binaries for ROM images.
I like the first part :D ; that's one of my areas of emphasis. Not so much the second :cry: I'd have to know more details before I could comment much beyond saying that the two assemblers have very different ideas regarding how to go about linking (dev65 seems much more traditional). Possibly too different to easily reconcile in a single source.
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Post by BitWise »

I have updated both the 6501/6502/65C02/65816 and 65Org16 assemblers so that:

- They allow implied mode with ASL/ROL etc. as well as ASL A

- They allow reserved words as labels (e.g. BREAK)

- Don't crash when the file name is invalid (- it crashed trying to report the error)

- Allow an optional condition code on BREAK and CONTINUE commands for use in structured assembly. For example

Code: Select all

LDX #0
REPEAT
 CPX #10
 BREAK EQ
 INX
FOREVER
- Misc other small bugs and fixes

The revised 65Org16 assembler and example using NMAKE are here:
http://www.obelisk.demon.co.uk/files/65016.zip

The revised 6502 assembler and example using batch files are here:
http://www.obelisk.demon.co.uk/6502/6502.zip

The same JAR is in both but the assemblers and linkers need different class names to invoke them.
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
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Post by BigEd »

Great - thanks!
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

Excellent, thanks for that update Bitwise! although I've not tried it yet, does it address the following:

I am having a problem with LDA $XXXXXXXX,x. More detail here.
Currently this operation is showing up as a $00B5 in the .bin which translates to a LDA $XXXX,x when it should be opcode $00BD?
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Post by BitWise »

ElEctric_EyE wrote:
Excellent, thanks for that update Bitwise! although I've not tried it yet, does it address the following:

I am having a problem with LDA $XXXXXXXX,x. More detail here.
Currently this operation is showing up as a $00B5 in the .bin which translates to a LDA $XXXX,x when it should be opcode $00BD?
Looks like there is a bug in the direct page detection. Meanwhile use one of the override characters to get the right instruction.

Code: Select all

FFFFF000  00B5E000          :                 LDA     $FFFFE000,X
FFFFF002  00BDE000FFFF      :                 LDA     |$FFFFE000,X
FFFFF005  00BDE000FFFF      :                 LDA     !$FFFFE000,X
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
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Post by BitWise »

Found the bug in a routine that determines if a unsigned value will fit in a byte by testing if the high byte is all ones or all zeroes. Addresses are unsigned so this returns the wrong result for $ffff0000-$ffffffff.

The fixed assembler outputs:

Code: Select all

FFFFF000  00BD8000FFFF      :                 LDA $FFFF8000,X
FFFFF003  00BD8000FFFF      :                 LDA !$FFFF8000,X
FFFFF006  00BD8000FFFF      :                 LDA |$FFFF8000,X
I've updated the 65Org16 assembler zip at
http://www.obelisk.demon.co.uk/files/65016.zip
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
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

Awesome, I'll be able to put the new update to use in a couple of days...
teamtempest
Posts: 443
Joined: 08 Nov 2009
Location: Minnesota
Contact:

Post by teamtempest »

Quote:
(I couldn't get strings to come out quite right in HXA, so I'm currently working around it with .byte directives and hex values. It's likely that I haven't got the .assume/.cpu directives quite right.)
I'm going to try to expand a little on the HXA 0.180 documention under the assumption that what's there isn't clear enough yet. Maybe writing it out in a longer fashion will even help me understand it better :)

To begin with, HXA deals 32-bit signed and unsigned integers. If we consider those as consisting of four 8-bit octets, I think of them as being laid out this way, from most to least significant:

3 - 2 - 1 - 0

It takes a right shift to move bits to a less significant position, so I visualize the most significant bits as being on the left, regardless of what the actual internal arrangement might be.

When the time comes to produce output, an array of these 32-bit values is a primary source of raw material. However we usually do not want all four octets, and even if we do, we might not want them in that 3-2-1-0 order. So HXA provides options to specify exactly what we do want.

For example, 6502 processors normally want their octets in least significant first order. An 8-bit quantity is just 0, 16-bits is 01, 24-bits is 012, and 32-bits should come out 0123. The 6502 has a 16-bit address bus, and the way to describe all this to HXA is:

Code: Select all

.cpu T_16_L
"T" originally meant "Test", but "16" means "16-bit address bus" and "L" means "Least significant byte first" (as an aside, I've decided this is a useful enough notation that the native 65xx version of HXA, HXA65, actually uses it behind the scenes).

Anyway, what do we want for the 65Org16? This is an "LSB" processor with a 32-bit address space and a 16-bit "byte". The straightforward way to describe that is:

Code: Select all

.cpu T_32_L16
where "L16" means "least significant byte first, 16-bit bytes" (if no number is present after the "L", eight-bit bytes are defaulted).

So what does this get us? Well, the pseudo ops "BYTE" and "WORD" become aliases for "BIT16" and "BIT32" (instead of "BIT08" and "BIT16", respectively) and the "LONG" pseudo op isn't available. This is the trick that lets the same macro instruction set work for both a normal 6502 and the 65Org16, as all the macros are defined in terms of these alias families.

Now

Code: Select all

.byte $ABCD    ; one byte
.word $ABCD    ; two bytes, native order
.revword $ABCD ; two bytes, reverse native order
produces

Code: Select all

DC    ; wrong - should be CD
DC BA ; wrong - should be CD AB
AB CD ; correct
What's happened is that the "L" in "T_32_L16" causes HXA to by default extract 16-bit values in the octet order 01, 32-bits in the order 0123 and reversed 32-bits in the order 3210.

To deal with this HXA extends its "ASSUME" pseudo op to describe custom octet extraction orders. To make the sequence correct for the 65Org16:

Code: Select all

.cpu T_32_L16
.assume BIT16=10, BIT32=1032

.byte $ABCD
.word $ABCD
.revword $ABCD
produces:

Code: Select all

CD
CD AB
AB CD
which is what we want.

Because custom extraction orders are possible the 65Org16 can also be described as a most-significant-byte first processor. In this case the default octet extraction orders run 16-bits 10, 32-bits 3210 and reversed 32-bits 0123. The 16-bit ("byte") order is naturally what we want, but the other two must be accounted for:

Code: Select all

.cpu T_32_M16
.assume BIT32=1032, BIT32R=3210
Given that either way works fine for "byte" and "word" values, is there any reason to prefer one to the other? It turns out there is, and that is because of "string" values.

Character values in HXA range from zero to 255, eight bits or one octet, regardless of the "byte" size. This means that when a "byte" is larger than one octet, characters in strings must be padded to fit. Because the numeric value of a character is always smaller than 256, HXA pads in such a way that the "character octet" is always in the least significant position:

Code: Select all

.cpu T_16_L08
.str "123" ; -> 31 32 33

.cpu T_16_M08
.str "123" ; -> 31 32 33

.cpu T_32_L16
.str "123" ; -> 31 00 32 00 33 00

.cpu T_32_M16
.str "123" ; -> 00 31 00 32 00 33

.cpu T_32_L32
.str "123" ; -> 31 00 00 00 32 00 00 00 33 00 00 00

.cpu T_32_M32
.str "123" ; -> 00 00 00 31 00 00 00 32 00 00 00 33
Um, this is just for illustration, as HXA does not actually permit cpu re-definition during a single assembly.

It is an arguable point that because "character" values are always "bytes", any custom extraction order that is applied to "BIT16" for 16-bit "bytes" (or "BIT32" for 32-bit "bytes") should also apply to character "bytes". For the time being HXA does not do that, however.

Because the 65Org16 wants to see character octets in "00 char" rather than "char 00" order, the better definition to use is after all:

Code: Select all

.cpu T_32_M16
.assume BIT32=1032, BIT32R=3210
I should note that this works only for the HXA_T variant at present, although eventually, once either an instruction set is finalized or I happen to feel like it, something very much like this will happen "behind the scenes" when HXA65 is extended to support the 65Org16.

Hope this helps anyone who's confused about this!
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

Hi Bitwise,
I think I may have have witnessed another bug involving DEC/INC $xxxxxxxx (opcodes $CE/$EE respectively). It is being translated to DEC/INC $xxxx (opcode $C6/$E6).
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Post by BitWise »

ElEctric_EyE wrote:
Hi Bitwise,
I think I may have have witnessed another bug involving DEC/INC $xxxxxxxx (opcodes $CE/$EE respectively). It is being translated to DEC/INC $xxxx (opcode $C6/$E6).
Found and fixed over the weekend. I'll build an updated ZIP tonight.
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
User avatar
BitWise
In Memoriam
Posts: 996
Joined: 02 Mar 2004
Location: Berkshire, UK
Contact:

Post by BitWise »

BitWise wrote:
ElEctric_EyE wrote:
Hi Bitwise,
I think I may have have witnessed another bug involving DEC/INC $xxxxxxxx (opcodes $CE/$EE respectively). It is being translated to DEC/INC $xxxx (opcode $C6/$E6).
Found and fixed over the weekend. I'll build an updated ZIP tonight.
Ok. Now generates this

Code: Select all

FFFFF000  00BD8000FFFF      :                 LDA $FFFF8000,X
FFFFF003  00BD8000FFFF      :                 LDA !$FFFF8000,X
FFFFF006  00BD8000FFFF      :                 LDA |$FFFF8000,X
                              
FFFFF009  00B58000          :                 LDA $00008000,X
FFFFF00B  00BD80000000      :                 LDA !$00008000,X
FFFFF00E  00BD80000000      :                 LDA |$00008000,X
                              
FFFFF011  00EE8000FFFF      :                 INC $FFFF8000
FFFFF014  00EE8000FFFF      :                 INC !$FFFF8000
FFFFF017  00EE8000FFFF      :                 INC |$FFFF8000
                                                              
FFFFF01A  00E68000          :                 INC $00008000
FFFFF01C  00EE80000000      :                 INC !$00008000
FFFFF01F  00EE80000000      :                 INC |$00008000
New ZIP at http://www.obelisk.demon.co.uk/files/65016.zip
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
Post Reply