6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed Oct 02, 2024 2:41 am

All times are UTC




Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Jun 22, 2019 5:21 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
This feels like a little bit of a puzzle. Suppose your subroutine is going to run on a 65816 but you don't know whether it's in emulation or native mode, or 8 or 16 bit index or memory mode. How to determine the mode and return the information without messing up the machine?

My first thought of course is PHP then PLA. But I don't know the size of A! Perhaps I can save and restore S using TSX and a later TXS? But I don't know the size of X (or S) ... so it feels like some cleverness is going to be needed.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 5:40 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Only part of the solution, but this byte sequence ought to leave the Z flag cset when Memory/Accumulator is 8-bit, and clear when 16-bit. :)
Code:
db $A9 ;opcode for LDA # (takes an 8- or 16-bit operand)
db $00 ;the 8-bit operand, or half of the 16-bit operand
db $EA ;opcode for NOP, or other half of the 16-bit operand

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Last edited by Dr Jefyll on Sat Jun 22, 2019 5:47 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 5:47 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Ah - how about PHP PHP PLA PHA PLP PLP - then we know the bottom byte of A will contain P. And we put the stack back where we found it.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 7:14 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
I think its easier to work back from what state does the subroutine need the processor to be in to work correctly.

All the additional instructions and modes work emulation mode so you don't usually need to change the E bit unless the fixed stack location or interrupt behaviour is important. If you need to change state then start the function with CLC (or SEC)/XCE/PHP and finish with PLP/XCE before exiting.

8/16 index register size changes are tricky as X/Y get truncated if they get smaller so you need to PHX/PHY and save the current size with a PHP before X is changed.

If the accumulator is in the 8-bit state then it may be necessary to save B as well unless the routine can guarantee not to modify it.

Putting it all together you get
Code:
SomeFunction:
  if mode change needed
   if requires native mode
  CLC
   else
  SEC
   endif
  XCE
  endif
  PHX ; Save X/Y in callers size
  PHY
  PHP ; Save Register sizes
  SEP #$xx ; Set required M/X state
  REP #$xx ; .. omit instruction if #$00
  if 16-bit A
  PHA ; Save A/B
  else
  PHA ; Save A
  XBA
  PHA ; .. and B
  endif

  .. do something

  if 16-bit A
  PLA ; Restore A/B
  else
  PLA ; Restore A
  XBA
  PLA ; .. and B
  endif
  PLP ; Recover callers M/X (and E)
  PLY ; Restore X/Y
  PLX
  if mode change needed
  XCE
  endif
  RTS


You don't always need to save everything of course some registers mat contain results on exit but a universal routine will be restricted to 8-bit values in A/B/X/Y.

_________________
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


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 7:19 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Hmm, I think that's a good answer to a slightly different puzzle: how not to be affected by the initial state. I was thinking of trying to report the machine's state. For example, I give you an unknown 816 machine with an unknown OS and a Basic with an assembler. Somehow you want to figure out what mode Basic is using before (and after) it calls the code you've written.

Asking for a friend.

(Well, not really - some research would answer the case I'm thinking of. But out of this predicament came the puzzle.)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 7:34 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
To report the machines state move to known state (like emulation or native with 8-bit MX) while pushing the old and look at stack.

How about this:
Code:
WhatsMyState:
 CLC ; Go native
 XCE
 PHX ; Save X/Y
 PHY
 PHP ; Push old state
 SEP #$30 ; Go 8-bit MX
 PHA ; Save A
 LDA 2,S ; Fetch old state
 LSR A ; Shift out E
 BCS Emulation ; Was emulation on entry
 LSR A ; Shift down MX
 LSR A
 AND #$06 ; Form index
 TAX
 JMP (Mode,X) ; Jump to native mode
Mode:
 .word M0X0,M0X1,M1X0,M1X1

Emulation:
  ...

M0X0:
 ...
M0X1:
 ...
M1X0:
 ..
M1X1:
 ..

_________________
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


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 8:15 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Nicely done!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 8:37 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
There was a somewhat-related discussion and/or challenge here.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 9:03 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Ooh, good memory - and that challenge is as yet unresolved, I think.

(Andrew, just a thought about your solution: by switching to native mode might you get in trouble if there's an interrupt, if the system expected to be in emulation mode?)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2019 10:07 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
BigEd wrote:
(Andrew, just a thought about your solution: by switching to native mode might you get in trouble if there's an interrupt, if the system expected to be in emulation mode?)

Can't see why. There are separate vectors and all the bank registers are pushed. Its more of an issue the other way round. In emulation mode the interrupt always returns with PBR set to bank zero.

_________________
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


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 23, 2019 12:30 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
They *are* separate vectors, and that could be a problem in itself if only one set of vectors is actually set up. It would be safer to disable interrupts while (possibly) in the "other" mode. And it would also be safest to switch to native mode rather than to emulation mode, because several registers are potentially corrupted by emulation mode.
Code:
CLC
PHP ; save original M/X/I/D state for examination and later return
SEI ; enter critical section
XCE
PHP ; save emulation flag for later examination; M/X bits also saved anew (both set if was emulation mode)
XCE
SEP #$30 ; 8-bit accumulator & indexes, whether emulation mode or not
PLA
AND #31 ; mask off relevant bits
LSR A
PHP ; save emulation bit
ASL A
ASL A
PLP
ROL A ; move M/X to N/V bits and shift in emulation bit to C
PHA
LDA 2,S ; retrieve original M/X/I/D bits
AND #$3C
ORA 1,S
STA 1,S
PLP ; exit critical section
PLA ; restore stack
RTS ; result is in status flags - C=emulation mode, N=accumulator mode, V=index mode, X/Y preserved, A clobbered


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 23, 2019 4:08 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
We shouldn't necessarily be required to save P and switch modes just to detect our state, if we're clever enough to use a few bytes of scratch RAM to detect page wrapping behavior that's specific to the state we're in. Unfortunately, I'm not clever enough at the moment, so I'm just throwing the idea out there ...

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 23, 2019 4:36 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Better idea: emulation mode causes the M/X bits to be stuck on (part of forcing both to 8-bit mode). This can be detected without switching to native mode:
Code:
PHP ; save original state
REP #$30 ; try to switch to 16-bit M/X modes - if this fails, we must be in emulation mode
LDA #$EA00 ; in emulation mode, this becomes LDA #0 : NOP - so Z bit indicates emulation mode
BNE native
PLP ; restore stack
SEP #$C3 ; set all NZCV flags
RTS ; C and Z set = emulation, N=1, V=1 as both 8-bit mode

native:
SEP #$30 ; back to 8-bit mode
PLA
AND #$3C ; mask off M/X/I/D flags
PHA
AND #$30 ; mask off M/X flags
ASL A ; move to N/V flags
ASL A
ORA 1,S ; combine original M/X/I/D flags
STA 1,S
PLP ; transfer modified status reg, restore stack
RTS ; C and Z clear = native, N=M, V=X


Last edited by Chromatix on Mon Jun 24, 2019 12:16 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 23, 2019 4:57 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
28 bytes of code? Very tidy. Nicely done!

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 23, 2019 6:39 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10943
Location: England
Nice! I do like the way Andrew used XCE to preserve the pre-existing machine state at the same time as putting it into a known state, but a solution which doesn't use XCE is even better.


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 17 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: