6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 10, 2024 2:52 pm

All times are UTC




Post new topic Reply to topic  [ 28 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Tue Aug 20, 2013 6:22 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
GARTHWILSON wrote:
...get Cross-32 from Data Sync Engineering for $99. It comes with the tables for 50 different processors and the info you need to make up your own for a new processor.

I had downloaded and tried out the Cross-32 demo, and set it aside because it has no apparent support for local labels. Otherwise, it does seem to be an okay assembler, if slightly cumbersome with which to work (e.g., I detest having to type EQU to say LABEL = VALUE—those two extra keystrokes can rapidly add up in a large program). I also find the use of $ as the current program counter symbol completely non-intuitive. Guess I'm just an old stick in the mud...

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 20, 2013 7:05 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8538
Location: Southern California
Using the structure macros for looping, conditionals, etc., most of the local labels will be gone. :D :D

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 20, 2013 8:23 pm 
Offline

Joined: Sun Sep 15, 2002 10:42 pm
Posts: 214
Hardware people see machine instructions in a weird way based on my experience.

From a software person's perspective, PEA is an immediate-mode instruction.

From a hardware person's perspective, PEA pushes an address, so it's not immediate mode.

From what I've seen, hardware and software people tend to view instruction sets differently. For example, the Renesas SH jump-to-an-address-in-a-register is written JMP (Rn). I thought it should be JMP Rn because there's there's no memory reference - it conceptually copies Rn to the PC. The instruction set design argued that since Rn was used as an address, it was JMP (Rn).

Toshi


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 20, 2013 8:34 pm 
Offline

Joined: Mon Mar 02, 2009 7:27 pm
Posts: 3258
Location: NC, USA
TMorita wrote:
Hardware people see machine instructions in a weird way...

:lol: That is an interesting observation Toshi. Maybe it is due to the fact that people are assigned certain hardware or software tasks due to their speciality in the workforce...
God knows either is a trail that can be followed for long periods of time by a lone individual, especially a hobbyist that longs to conquer both ends of the spectrum.

_________________
65Org16:https://github.com/ElEctric-EyE/verilog-6502


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 20, 2013 8:48 pm 
Offline

Joined: Sat Oct 20, 2012 8:41 pm
Posts: 87
Location: San Diego
BigDumbDinosaur wrote:
PHW would make more sense, to me at least, than PEA, since PEA's operand can be anything that will resolve to 16 bits. Of course, there is no PLW to reverse the process... :?

This seems like a nice idea for a couple of new macros. :D


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 20, 2013 9:59 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
TMorita wrote:
Hardware people see machine instructions in a weird way based on my experience.

From a software person's perspective, PEA is an immediate-mode instruction.

From a hardware person's perspective, PEA pushes an address, so it's not immediate mode.

I'm definitely a "hardware person" and a "software person" who started this topic. :lol: PEA's operand can be anything that resolves to 16 bits, not just an address. If you can describe the color of your eyes or the length of your hair via a 16 bit number PEA will push it for you. :wink: Sounds like an immediate mode instruction to me.

Quote:
From what I've seen, hardware and software people tend to view instruction sets differently. For example, the Renesas SH jump-to-an-address-in-a-register is written JMP (Rn). I thought it should be JMP Rn because there's there's no memory reference - it conceptually copies Rn to the PC. The instruction set design argued that since Rn was used as an address, it was JMP (Rn).

Well, how does that account for people like many of this forum's denizens who design and build the hardware, and then write the software needed to make it go?

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 20, 2013 10:00 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
GARTHWILSON wrote:
Using the structure macros for looping, conditionals, etc., most of the local labels will be gone. :D :D

Most, but not all...

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 10, 2013 2:57 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
I'm back on this because I'm in the process of documenting version two of my 65C816 string manipulation library. The new version requires that the calling function set up a stack frame to pass parameters, e.g.:

Code:
         pea #s2_ptr           ;STRING2's pointer
         pea #s1_ptr           ;STRING1's pointer
         jsr strcat            ;catenate STRING2 to STRING1
         bcs error
         ---
error    beq bankovr           ;bank overlap error
         bmi toolong           ;string too long error

As I was preparing this, I was again nagged by the "formal" syntax for PEA (and PEI) and decided to research a bit to see how the syntax described in the Eyes and Lichty manual came about. Summarized, the manual's syntax for PEA and PEI apparently was never an official WDC definition. The 65C816 data sheets over the years (and the one 65C832 data sheet I viewed) have merely described them as stack instructions in the detailed operation segment and make no specific mention of PEA and PEI in the recommended assembly language syntax section.

In fact, there doesn't seem to be any definitive reference to these instructions' addressing modes prior to the introduction of the ORCA/M assembler. It appears that the assembler's developer independently devised this syntax and it ended up being used by default in other assemblers supporting the '816 instruction set. This syntax was probably the result of not fully understanding what PEA and PEI do, which is to push words that can be any kind of data, not just addresses. The '816's data sheet unwittingly added to the misunderstanding, starting with the mnemonics themselves, followed by the instruction descriptions. For example, PEA is described as "Push Absolute Address" (page 31), even though the operand is a word that could be any data, not just an address. Even the mnemonic doesn't make complete sense. If the instruction really does "Push Absolute Address" shouldn't the mnemonic be PAA? A better choice might have been PIW (push immediate word) and PEI might better have been PDW (push direct page word).

My opinion is:

Code:
         pea #<operand>
         pei <operand>

is the correct syntax for these instructions, not the syntax described in the Eyes and Lichty manual.

PEA #<word> loads <word> into the '816's ALU and then pushes it in big-endian order (causing <word> to be stored with its LSB lower on the stack than its MSB), an operation that qualifies PEA as having immediate mode addressing. In fact, I've used PEA #$0000 in some programs to simultaneously create and clear two bytes of workspace on the stack. The fact that PEA affects no flags is irrelevant, as the definition of immediate mode addressing is the operand to the instruction is the instruction's data. Clearly, the syntax PEA $0000 can't be correct, since $0000 is the data.

PEI <byte> loads the word stored at <byte> and <byte>+1 into the ALU and then pushes it, also in big-endian order. In this case, the operand is an address from which the data is to be loaded. As PEI loads the ALU from a direct page address, PEI qualifies as having direct page addressing, same as any other instruction that loads/stores/compares data in a direct page location.

Any comments or should I just be taken to the loony bin and administered my meds? :D

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 10, 2013 4:11 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
BDD,

Your explanation and underlying logic are flawless, IMO. However, unless you feel like starting a petition or
designing your own assembler, I don't see much point in the effort ...

BTW, have you or anyone else used per? The example fragment in the WDC manual has a mysterious
hex operand:
Code:
0000                  ORG  $2200
0000          ACCESS  START
0000
0000 62FD7F           PER  DATA1      push run-time address of DATA1 onto stack
0003 E220             SEP  #$20       set accum to 8-bit mode
0005 A00000           LDY  #0         zero index: DATA1 is cell, not array
0008 B301             LDA  (1,S),Y    load accum from DATA1 in data ban
000A                                  ; (address of DATA1 @ 1,S & 2,S)
000A                  .
000A                  .
000A                  .
000A
000A                  END
0000
0000                  ORG  $2500
0000          DATA0   START
0000 2A2A2A           DC    C’***’
0003 FF       DATA1   DC    H’FF’
0004 F7       DATA2   DC    H’F7’
0005 E3       DATA3   DC    H’E3’
0006
0006 END


Can anyone explain how the '62FD7F' can be derived? Or is it some kind of transcription error?

Mike


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 10, 2013 10:52 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
I think it is a transcription error.

I worked out what I thought the operand of the PER instruction should be, and like you, I determined that it is not $FD7F. I worked it out as $0300 from my understanding of the instruction.

I just read through the description of the instruction in the Eyes & Lichty manual and found confirmation in the paragraph that provides the text for the example code you reference. Eyes & Lichty says that the operand should be $0300 on page 172 in the next to last paragraph. Thus, it should be represented as 620003 instead of 62FD7F as shown in the example code fragment.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 10, 2013 5:31 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
barrym95838 wrote:
Your explanation and underlying logic are flawless, IMO. However, unless you feel like starting a petition or
designing your own assembler, I don't see much point in the effort ...

Effort? I'm not out to change the world, just trying to make some sense of it. :lol:

Quote:
BTW, have you or anyone else used per? The example fragment in the WDC manual has a mysterious
hex operand:
Code:
0000                  ORG  $2200
0000          ACCESS  START
0000
0000 62FD7F           PER  DATA1      push run-time address of DATA1 onto stack
0003 E220             SEP  #$20       set accum to 8-bit mode
0005 A00000           LDY  #0         zero index: DATA1 is cell, not array
0008 B301             LDA  (1,S),Y    load accum from DATA1 in data ban
000A                                  ; (address of DATA1 @ 1,S & 2,S)
000A                  .
000A                  .
000A                  .
000A
000A                  END
0000
0000                  ORG  $2500
0000          DATA0   START
0000 2A2A2A           DC    C’***’
0003 FF       DATA1   DC    H’FF’
0004 F7       DATA2   DC    H’F7’
0005 E3       DATA3   DC    H’E3’
0006
0006 END

Can anyone explain how the '62FD7F' can be derived? Or is it some kind of transcription error?

The 62FD7F thingie is an error, and the way in which the ORCA/M assembler lists the code could use some improvement—it's customary to add space between the assembled bytes for clarity. Anyhow, even though the object code is in error I'll use it for explanation.

What you are seeing is the binary representation of a PER $A200 instruction. I know what your next question will be: How do you get that out of $62 $FD $7F? PER means "Push Effective Relative," where "relative" means a signed 16 bit offset or displacement relative to the program counter (PC). Both the mnemonic and description leave something to be desired in clarity, but so is the case for PEA and PEI. :lol: I suspect Bill Mensch had a hard time coming up with a more descriptive set of mnemonics for these somewhat oddball instructions.

Anyhow, PER's opcode is $62, so that explains the first byte. The others come from how the assembler processes PER and its operand. When PER <addr> is assembled, the <addr> operand is converted to a signed 16 bit offset whose origin (base address) is the address of the next instruction. If I assemble PER $A200 at $2200 (as in the above code fragment), the assembler will calculate a signed 16 bit offset relative to $2203 and assemble those bytes ($FD $7F) as the real operand for the PER instruction. In this respect, the assembler is essentially doing what it does for any instruction that uses relative addressing.

When the PER instruction is executed, the '816 will compute PC+$03+$7FFD and push the resulting 16 bit sum to the stack, most significant byte first, where PC is the address in the program counter. As the PER instruction is at $2200, the value pushed to the stack is $2200+$03+$7FFD or $A200. Note that this works much like the BRL (branch long) instruction, which also takes a signed 16 bit offset. The difference is in what the '816 does with the "effective address" that was computed from the offset.

PER is most useful in writing relocatable code, as the target address of the assembled instruction is always specified as an offset to the program counter, not an absolute value. If the program is relocated in RAM the '816 will generate a new target address at run time that will be exactly $8000 bytes beyond the PER instruction's address and the relationship between instruction and data, as depicted above, will be maintained.

As an example of how PER can be used, consider this macro taken from my '816 macro set for the Kowalski assembler. When assembled, this macro simulates the BSR (branch to subroutine) instruction found in the Motorola 6800 and 68000 MPUs. The first part of the macro calculates the offset required to branch (not jump) to the subroutine and the address that the subroutine must return to, -1 byte. The last two steps actually assemble the code:

Code:
;   BSR: Branch to Subroutine
;   ——————————————————————————————————————————————————————————————————————
;   This macro synthesizes the BSR instruction implemented in the Motorola
;   6800 & 68000 microprocessors.  Programs in which subroutines are call-
;   ed via BSR are fully relocatable,  as the target address is calculated
;   relative to the program counter at run-time.   The target address must
;   be within the range of a long relative branch, +$7FFF or -$8000 bytes.
;   ——————————————————————————————————————————————————————————————————————
;
bsr      .macro .sr            ;BSR <addr>
.mib     =$82                  ;BRL opcode
.mip     =$62                  ;PER opcode
.na      =*+3                  ;next instruction's address
.ra      .set .na+2
.ba      =.ra+1
.ra      .set .ra-.na          ;return address to be pulled by RTS
.ta      .set .sr-.ba          ;subroutine's entry address
         .byte .mip,<.ra,>.ra  ;PER <return address>
         .byte .mib,<.ta,>.ta  ;BRL <subroutine>
         .endm

In the above, symbols that start with a dot (.) are local to the macro. The .SET pseudo-op declares the associated symbol to be a variable, and thus allows its value to change during assembly time.

The macro invocation is BSR <subroutine>, just like JSR <subroutine>. The difference is that the subroutine's address is not actually encoded into the resulting object code, just the offset to it. PER calculates and pushes a return address before the BRL instruction takes the '816 to the subroutine's entrance. When RTS is executed at the end of the subroutine, the address that was pushed by PER will be pulled, incremented and loaded into the program counter, causing the '816 to return to the instruction following the BRL. As PER generated the return address relative to the program counter, moving the program won't cause any problem with addressing.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 11, 2013 12:10 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 410
Location: Minnesota
Quote:
The 62FD7F thingie is an error


Could be. Or maybe this bit should be $A200:

Quote:
0000 ORG $2500


Either way, I like your explanation.

I like the BSR as well, but does it work for forward branches? I ask because this line:

Quote:
.ta .set .sr-.ba ;subroutine's entry address


strikes me as the sort of thing that can't be computed when first encountered if the value of '.sr' isn't known yet. If that expression was the argument of an opcode, I can see there'd be no problem, but assigned to a label?

I can't quickly find documentation on the Kowalski assembler, but I wonder if this might be the equivalent of your macro:

Code:
bsr  .macro .addr
     .byte $62                ; PER opcode
     .word 3-1                ; one less than the size of the next "instruction"
     .byte $82                ; BRL opcode
     .word .addr - * + 2      ; offset to ".addr" from address just after this "instruction"
     .endmacro


I notice that your macro sets ".ra" twice, but the second time always sets its value to 2 (so that's where "3-1" comes from).


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 11, 2013 2:28 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
teamtempest wrote:
I like the BSR as well, but does it work for forward branches?

Yes, as long as it's within $7FFF bytes of the target subroutine.

Quote:
I can't quickly find documentation on the Kowalski assembler...

There really isn't any to be had, at least not in English (Mike Kowalski's native tongue is Polish). A lot of this got worked out by trial and error.

Quote:
...but I wonder if this might be the equivalent of your macro:

Code:
bsr  .macro .addr
     .byte $62                ; PER opcode
     .word 3-1                ; one less than the size of the next "instruction"
     .byte $82                ; BRL opcode
     .word .addr - * + 2      ; offset to ".addr" from address just after this "instruction"
     .endmacro

I notice that your macro sets ".ra" twice, but the second time always sets its value to 2 (so that's where "3-1" comes from).

It's the same in effect. The hoop-jumping in my BSR macro is there to get the assembler to correctly deal with forward references.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 28 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: