It is currently Tue Oct 24, 2017 12:31 am

All times are UTC - 7 hours



Forum rules


Related:



Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Dec 13, 2016 4:48 am 
Offline
User avatar

Joined: Mon Jun 09, 2014 1:18 pm
Posts: 11
Location: Gothenburg, Sweden
Hi,

does anyone have experience of working with 16-bit pointers on the SPC-700? From what I can tell by reading the manual, there is no such addressing mode. (I'm not referring to absolute addressing.)

I can't get my head around writing even something as simple as a memory clear routine. How would I pass the destination address argument? The only way I can think of, is using self-modifying code together with absolute addressing. It doesn't feel like a clean solution.

Cheers


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 5:13 am 
Offline
User avatar

Joined: Sat Dec 01, 2012 4:10 am
Posts: 65
I have written some custom bootloader for the SMP. Maybe the code will help. The SMP can do indirect 16 Bit addressing, you would need to write something like this:
Code:
ldy ($xx),y

Where $xx is in the page0 memory space (I am not sure it needs to be page0 or page1, but I guess it is like the 6502, where 16 Bit indirect addressing only works in zero-page).
Here is my bootloader (assembled with bass, use it as you want :) ):
Code:
//spc_player_init SPC side
//By el_seyf
//Code is used to copy all RAM and restore Registers of SPC
//Code is located in Stack, just above the last pointer
arch snes.smp//assemble to be a SNES executeable
output   "custom_spc_downloader.spc", create//specifies output name,
                        //will overwrite existing file
//------------------------------------------------------------------//
//Code will check $F4:
//   if "not 0" =>   Byte in $F7 will be written to addr in $F5-F6
//   if "is  0" =>   Routine will copy values from specific
//               Address into Registers A,X,Y,SP,PSW and jump to addr in $F5-F6
//------------------------------------------------------------------//
origin $0000
//turn off DSP:
str $F2=#$6C
str $F3=#$E0
//tell SNES that custom routine is ready to receive data:
lda #$59
sta $F4//store 'Y' in $F4 => SMP is ready to receive Data

ldy #$00
//Wait for $F4 to be "not last value":
check_for_not_last_val:
eor #$FF//not value in A
check_for_not_last_val_loop:
cpy $F4//command=end?
beq end_transfer
cmp $F4//command="not last value"? -> new byte available
bne check_for_not_last_val_loop
tax//temp save "not last val"
//Load Byte from $F7 and store at address in $F5-F6
lda $F7
sta ($F5),y
txa
sta $F4//write received value to command port
bra check_for_not_last_val//saves a byte compared to jmp
//--------------------------------------------------//
end_transfer:
//needs to be redone:
ldx #$00//SP
txs
lda #$00//PSW
pha
lda #$00
ldx #$00
ldy #$00
str $F2=#$6C//DSP_CTRL
str $F3=#$00
str $F2=#$00
str $F3=#$00
str $F1=#$00
plp
jmp $0000
//--------------------------------------------------//
origin $0040

Though my SNES Uploader does not use it, the bootloader supports random writes and I could easily support reading as well.


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 5:28 am 
Offline
User avatar

Joined: Mon Jun 09, 2014 1:18 pm
Posts: 11
Location: Gothenburg, Sweden
elseyf wrote:
I am not sure it needs to be page0 or page1, but I guess it is like the 6502, where 16 Bit indirect addressing only works in zero-page


That's the problem I'm referring to. Only 8-bit indirect addressing is available (for pages 0 and 1). How would I go about to use indirection for any location in RAM?

Suppose I have a number of patterns containing notes to be played. How could I write a routine that plays any of those patterns, without using 16-bit pointers? I've coded Z80 a lot, but I have a hard time getting my head around the SPC700.


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 5:49 am 
Offline
User avatar

Joined: Mon Jun 09, 2014 1:18 pm
Posts: 11
Location: Gothenburg, Sweden
Sorry, I replied too quickly, before completely understanding your answer. So I guess indirection is possible! As long as I store the address in zero page :)


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 6:38 am 
Offline

Joined: Mon Nov 10, 2008 3:09 pm
Posts: 431
Indirect addressing on the SPC700 is the same as on the 6502 or 65816: the pointer has to be in direct page, but the pointed-to address can be anywhere.


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 9:44 am 
Offline

Joined: Thu Aug 28, 2008 1:17 am
Posts: 591
dalton wrote:
Sorry, I replied too quickly, before completely understanding your answer. So I guess indirection is possible! As long as I store the address in zero page :)

You might want to brush up on your 65x. The SMP is a variant of the 65x. Address registers on something like the z80 (ie. HL, BC), are just address vectors. 65x just happens to put those address vectors in ram (with single byte addressing to speed it up) instead of internal to the processor itself.

_________________
__________________________
http://pcedev.wordpress.com


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 10:57 am 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2295
AWJ wrote:
Indirect addressing on the SPC700 is the same as on the 6502 or 65816: the pointer has to be in direct page, but the pointed-to address can be anywhere.


With the 65816, the index registers themselves can be used as pointers.


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 4:30 pm 
Offline

Joined: Thu Feb 07, 2013 1:15 am
Posts: 95
Location: Sweden
Oh, it's on! I heard from Breakin' that you two decided to make some stuff...

As many already mentioned, working with memory is almost identical to how you would do things on 65xx – although I'm in the camp that thinks the SPC700 differs enough from 65xx to not simply think of it as such and use an aliased instruction set and what-not. (Let's not go there this time, but I should do a proper comparison some day!)

Anyway. Any and all indirection use the zeropage, with optional X/Y-indexing either pre- or post-indirection. Passing addresses to a subroutine using only registers is thus not as straight forward as on 65816 or Z80. If you'd really want to, I guess it's most effective to put the address in YA, and then in the subroutine use "movw $dp,ya" to move the argument into a zeropage address. Which is all pretty moot since you're using a fixed zeropage address in the end, anyway...

The common pattern in to reserve different zeropage addresses for specific tasks and just write to those addresses before calling the subroutine. That's how the C64 basic kernal work, and most other 65xx code I've looked at.

Another approach, which I've seen in some SNES games, is to use a fixed zeropage range more like a register file, which is pushed/pulled together with the actual registers when necessary. Not as crazy as it sounds for some designs, I suppose – but for the specific and isolated tasks you usually do on the SPC700 I don't really see an argument for not using the zeropage as a fast (and huge) scratchpad.


Top
 Profile  
 
PostPosted: Tue Dec 13, 2016 6:37 pm 
Offline
Formerly ~J-@D!~
User avatar

Joined: Sun Mar 12, 2006 12:36 am
Posts: 445
Location: Rive nord de Montréal
Just to be clear, you can put the zeropage (or rather, direct page) either in page 0 or 1. There's a bit in the status register for that.


Top
 Profile  
 
PostPosted: Wed Dec 14, 2016 11:52 pm 
Offline

Joined: Thu Aug 28, 2008 1:17 am
Posts: 591
Optiroc wrote:
Passing addresses to a subroutine using only registers is thus not as straight forward as on 65816 or Z80. If you'd really want to, I guess it's most effective to put the address in YA, and then in the subroutine use "movw $dp,ya" to move the argument into a zeropage address. Which is all pretty moot since you're using a fixed zeropage address in the end, anyway...

The common pattern in to reserve different zeropage addresses for specific tasks and just write to those addresses before calling the subroutine. That's how the C64 basic kernal work, and most other 65xx code I've looked at.

Another approach, which I've seen in some SNES games, is to use a fixed zeropage range more like a register file, which is pushed/pulled together with the actual registers when necessary. Not as crazy as it sounds for some designs, I suppose – but for the specific and isolated tasks you usually do on the SPC700 I don't really see an argument for not using the zeropage as a fast (and huge) scratchpad.


I'm of the opinion, that if you're gonna write code - you should probably have a perspective/mentality of a software engineer, not a hardware engineer. From your perspective, if those 256 bytes of zeropage were located on the processor vs ram, it'd be accessed the same way with the same opcodes (you'd still need one extra byte to complete the effective address because that's too many registers to be emdedded into an 8bit opcode). When I'm writing code on the original 68k cpu, I don't give a crap that the ALU is 16bit and the microcoded opcodes use a dual pass on it; I'm writing code for a 32bit processor. And I treat it as such.

ZP are just registers in external memory instead of internal. Voila - up to 128 address registers, or 256 data registers. However you use them. Thus, is becomes straight forward in how to use them. If you're pointing to a string of arguments with HL or BC on the z80, then you're doing the same thing with any ZP pair. It's no different. I even push ZP bytes into the hardware stack, as if I were pushing cpu regs on the stack - because I needed nested routine support using the same "regs".

_________________
__________________________
http://pcedev.wordpress.com


Top
 Profile  
 
PostPosted: Thu Dec 15, 2016 2:09 am 
Offline

Joined: Thu Feb 07, 2013 1:15 am
Posts: 95
Location: Sweden
I agree with all of the above. The not so "straight forward" part of what I said is that for data to end up in the direct page, it almost always has to take the detour through an actual CPU register. Pushing/popping stuff between direct page and the stack quickly eats up cycles.

That said, direct page access is one of the key areas where SPC700 has several great improvements over 6502:
Code:
mov  dp,#imm      ;store immediate value in direct page
mov  dp<d>,dp<s>  ;transfer byte from <s> to <d>
cmp  dp,#imm      ;compare byte in direct page with immediate value *
cmp  dp,dp        ;compare bytes in direct page (absolute) *
cmp  (x),(y)      ;compare bytes in direct page (indirect) *

* also available for the other ALU operations


Top
 Profile  
 
PostPosted: Thu Dec 15, 2016 10:43 am 
Offline

Joined: Thu Aug 28, 2008 1:17 am
Posts: 591
^ I wish emulators hand an option for opcode statistics when a running game; record the occurrence rate of each opcode. Some opcodes look great, but if they're not particular useful or used in most iterations that make up the larger chunks of resource, then they won't have much of an impact regardless of how nice they are to use. In such cases, macros serve the same purpose on lesser processors.

_________________
__________________________
http://pcedev.wordpress.com


Top
 Profile  
 
PostPosted: Thu Dec 15, 2016 4:35 pm 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2295
Something that drives me insane is that you have to clear either x or y in order to use indirect addressing mode on the SPC700.


Top
 Profile  
 
PostPosted: Thu Dec 15, 2016 6:37 pm 
Offline

Joined: Sat Apr 25, 2015 1:47 pm
Posts: 329
Location: FL
That's pretty much a result of it being so heavily modeled after the 6502, which has the same property.


Top
 Profile  
 
PostPosted: Fri Dec 16, 2016 1:27 am 
Offline

Joined: Thu Feb 07, 2013 1:15 am
Posts: 95
Location: Sweden
Yeah, no additions were made to indirect access outside of the zero page. In fact, ldy abs,x and ldx abs,y was curiously removed.

Also removed was the only instruction using absolute indirect addressing, jmp (abs). Or rather, it was replaced by jmp [!abs+x]...

Anyway, I quite enjoy the quirky additions and omissions SPC700 has compared to 65xx and using the "controversial" assembler syntax better gets my mind into SPC700-mode than using a 65xx:esque alias set.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 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:  
Powered by phpBB® Forum Software © phpBB Group