![]() |
![]() |
#1 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 12,230
|
unlk sp
Just something which I came across today, a 68000 re-implementation which fails Toni's cputest with opcode 0x4e5f (unlk SP)
Is that a valid operation? I've only ever used this instruction with address registers upto A6 (which are pointing to the stack frame). Code:
CPUlvl=0, Mask=00ffffff Code=007c0000 SP=007ffbc0 ISP=00800000 Low: 00000000-00008000 High: 00ff8000-01000000 Test: 00780000-00800000 Safe: ffffffff-ffffffff UNLK.L: data/68000/UNLK.L/0000.dat. 0... 8: 4e5f unlk sp A7: expected f01f007c but got e993f600 Registers before: D0: 00000010 D1: 00000000 D2: ffffffff D3: ffffff00 D4: ffff0000 D5: 80008080 D6: 7fff7fff D7: aaaaaaaa A0: 00000000 A1: 00000080 A2: 00008000 A3: 00007fff A4: fffffffe A5: ffffff00 A6: 007bff00 A7:*007ffbc0 SR: 0000 PC: 007c0000 ISP: 007fff80 T1=0 T0=0 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 000 PC: 007c0000 ISP: 007fff80 T1=0 T0=0 S=0 M=0 X=0 N*0 Z!0 V*0 C=0 Registers after: SR:*000e PC: 007c0002 ISP: 007fff80 T1=0 T0=0 S=0 M=0 X=0 N*1 Z!1 V*1 C=0 OK: No exception generated Registers after: SR:*000e PC: 007c0002 ISP: 007fff80 T1=0 T0=0 S=0 M=0 X=0 N*1 Z!1 V*1 C=0 OK: No exception generated Registers after: A4: fffffffe A5: ffffff00 A6: 007bff00 A7:*e993f600 SR: 0000 PC: 007c0002 ISP: 007fff80 T1=0 T0=0 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 OK: No exception generated ``` |
![]() |
![]() |
#2 |
Registered User
![]() Join Date: Jun 2015
Location: Germany
Posts: 658
|
Why should it not be valid? What do you do with the old SP you get in An when you need An for other purposes? You push it on the new stack. Unless I misunderstand the UNLK instruction, you can read back the old SP from the stack on leaving the subroutine where you use LINK/UNLK directly into the SP using "UNLK SP" without needing a scratch address register. To be honest, I would have expected this to be rather common (if we want to consider LINK/UNLK common at all).
EDIT: what 68000 reimplementation is that? Last edited by grond; 12 November 2019 at 13:53. |
![]() |
![]() |
#3 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 281
|
It is a valid instruction, though a bit unusual as it uses A7 both as the (implicit) source and destination. While the 68K family guide is quite clear on what this instruction should perform, I would not be overly surprised if, in reality, it works a little bit different in this specific case, maybe even depending on the member of the family.
|
![]() |
![]() |
#4 |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 46
Posts: 3,620
|
UNLK A7 does not look very useful...
In theory it should just pop A7 out of the stack, something regular MOVE can do. Also it does not look safe to use accross different cpu models, like MOVE.L (A7)+,A7. |
![]() |
![]() |
#5 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 44
Posts: 23,352
|
There is chance this report is bogus. I have seen same error sometimes but also UNLK SP test succeeding. Does it report same error if you only generate UNLK tests?
LINK has undefined behavior between CPU models but UNLK should work identically in all CPU models. |
![]() |
![]() |
#6 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 12,230
|
FX68K a SystemVerilog open source synthesisable cycle accurate 68000 reimplementation. Used originally in FXCast a cycle accurate Atari ST reimplementation for FPGA but now in lots of other reimplementations that require cycle accuracy including Megadrive/Genesis and arcade machines
Last edited by alexh; 13 November 2019 at 00:24. |
![]() |
![]() |
#7 |
Registered User
![]() Join Date: Jun 2015
Location: Germany
Posts: 658
|
What value will end up in A7 in your example? The post-incremented old stack pointer, the post-incremented new stack pointer or the non-incremented new stack pointer? And is that really the same as UNLK A7?
|
![]() |
![]() |
#8 | |
son of 68k
Join Date: Nov 2007
Location: Lyon / France
Age: 46
Posts: 3,620
|
Quote:
IIRC, on 020-030 it would be non-incremented new stack pointer (like on 68000). However, MOVEM would give post-incremented new stack pointer, where on 68000 there is no difference. I didn't test how UNLK A7 behaves but i would bet it is like MOVE. |
|
![]() |
![]() |
#9 |
Per aspera ad astra
![]() Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 49
Posts: 2,238
|
a real example:
a7 = $3FFFC (a7)=($3FFFC)=$50000 unlk a7 microcode: Code:
An -> SP; a7=$3FFFC -> a7 [M(SP)] -> tmp; (a7)=($3FFFC)=$50000 -> tmp SP+4 -> SP; a7+4=$3FFFc+4=$40000 -> a7 tmp -> SP; tmp=$50000 -> a7 movea.l (a7)+,a7or movea.l (a7),a7 for all 68k family processors Last edited by ross; 13 November 2019 at 13:00. Reason: reversed register movement to be more 68k friendly :) |
![]() |
![]() |
#10 |
Registered User
![]() Join Date: Jun 2015
Location: Germany
Posts: 658
|
Interesting! How did you test that?
|
![]() |
![]() |
#11 |
Per aspera ad astra
![]() Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 49
Posts: 2,238
|
|
![]() |
![]() |
#12 |
Thalion Webshrine
Join Date: Jan 2004
Location: Oxford
Posts: 12,230
|
I thought it was an interesting thing because I've never knowingly seen "unlk sp" in any disassembly I've come across (but then I've not seen a lot and I wasn't actively looking).
But potentially given the discussion here, I imagine that higher language compilers (not assemblers) could have produced the same functionality using a different opcode. I fed back to the reporter and they are going to try to re-run with UNLK tests only. |
![]() |
![]() |
#13 | |
Per aspera ad astra
![]() Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 49
Posts: 2,238
|
Quote:
Nor can it be thought of as coupled with a link a7,#nbecause this link doesn't make any sense and also it doesn't behave the same way in the 68k processors family. If you want a movea.l (a7),a7operation (which is perfectly legitimate) you use 2E57opcode that is dedicated and faster ![]() |
|
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
|
|