English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 08 September 2020, 11:08   #1
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,315
shortest way to set z=0 in ccr

Hello, just some small question.

Very often i return ccr's z bit as boolean in my routines. This spares tst instructions.
Of course i could just use moveq but there is not always a data register available.
For setting z=1 no problem : cmp.b d0,d0 does the trick. Changing other ccr bits is no big deal in most cases.
If i didn't care about code size i could use simple andi.b #$fb,ccr but code size is important to me and this instruction is large (and not very readable either).
No assumption can be made about other register contents, as it needs to be a macro used everywhere. So we can't count on D0-D7/A0-A6 being nonzero.

So to set z=0 with single code word the only solution i found is tst.l a7 but this is 020+ and it looks real weird (even if a7 can hardly ever be 0, can it ?).

Any other idea ? Any coding trick i missed ?
meynaf is offline  
Old 08 September 2020, 11:43   #2
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
Quote:
Originally Posted by meynaf View Post
Very often i return ccr's z bit as boolean in my routines.
..
So to set z=0 with single code word
Code:
	clr.w	-(sp)
	rtr
ross is offline  
Old 08 September 2020, 11:52   #3
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 2,890
Fascinating, I completely forgot about RTR
Gotta remember that one - I immediately thought of ways to use it
roondar is offline  
Old 08 September 2020, 12:00   #4
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,315
Could be used in some cases... but too dependent of the situation.

Two problems arise :
- we can have to save/restore registers and there it doesn't work - we could use moveq but this makes it unsuitable for a simple macro
- we need to return with rtr - so that's one extra instruction because we also need rts for the other case (when the routine returns z=1)

Nice try
meynaf is offline  
Old 08 September 2020, 12:05   #5
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
Quote:
Originally Posted by meynaf View Post
Could be used in some cases... but too dependent of the situation.

Two problems arise :
- we can have to save/restore registers and there it doesn't work - we could use moveq but this makes it unsuitable for a simple macro
- we need to return with rtr - so that's one extra instruction because we also need rts for the other case (when the routine returns z=1)

Nice try
Code:
	tst.l	(sp)
(after registers restore )
ross is offline  
Old 08 September 2020, 12:25   #6
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,315
Quote:
Originally Posted by ross View Post
(after registers restore )
Which is unfortunately not doable.
Remember, we may return either z=1 or z=0, and go to same rts if there are registers to restore (as using two movem would destroy code size benefit). Thus we can not insert anything between movem and rts.
meynaf is offline  
Old 08 September 2020, 12:42   #7
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
Quote:
Originally Posted by meynaf View Post
Which is unfortunately not doable.
Remember, we may return either z=1 or z=0, and go to same rts if there are registers to restore (as using two movem would destroy code size benefit). Thus we can not insert anything between movem and rts.
Yes of course it is not doable
But I have not found any way with the required restrictions.
The only one is the ugly
and ccr
..
ross is offline  
Old 08 September 2020, 13:32   #8
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,315
Quote:
Originally Posted by ross View Post
Yes of course it is not doable
But I have not found any way with the required restrictions.
The only one is the ugly
and ccr
..
Same for me. I asked just in case i could have missed something.
Of course i could try with another flag, such as c. But i can only clear it with single code word, not set it, so the situation is the same.
We do not have simple clear/set single flag instructions and yes it's a 68k shortcoming.
I guess i will keep my tst.l a7.
meynaf is offline  
Old 08 September 2020, 14:21   #9
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 1,148
Frankly, I suggest to change the coding style. I know returning conditions in ccr was kind of iconic in the 8-bit ages because there were not so many registers left, and when I moved to 68K, I tried (incorrectly) to adapt this style as well. But this only works with assembler, and no other language, and it does not necessarily make things faster or better. Within a function, it is acceptable, but I would not do that nowadays anymore as part of a function interface.


andi/ori ccr is the most direct way how to deal with the condition codes, but if that is not readable, I had (back then) a couple of macros defined that set or cleared individual flags. clc/sec (carry bit), clz/sez (zero flag), or ... well, you know how the macro looks like that sets the x bit, right? (-:
Thomas Richter is offline  
Old 08 September 2020, 14:42   #10
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,315
Quote:
Originally Posted by Thomas Richter View Post
Frankly, I suggest to change the coding style. I know returning conditions in ccr was kind of iconic in the 8-bit ages because there were not so many registers left, and when I moved to 68K, I tried (incorrectly) to adapt this style as well. But this only works with assembler, and no other language, and it does not necessarily make things faster or better. Within a function, it is acceptable, but I would not do that nowadays anymore as part of a function interface.
Do i want all these ugly tst after my bsr ? Nah.
Of course this only works with assembler, and ? Do i care about other languages ? In the unlucky case i have to mess with them, i provide a few wrappers, job done.
But change the coding style to look like compiler output, what a joke.
It's not this way to make things faster, even if it's certainly not slower, it's just to avoid putting instructions where not needed. Often the condition is ready without anything special to do and i just have to return. Setting a register would just add extra instructions.


Quote:
Originally Posted by Thomas Richter View Post
andi/ori ccr is the most direct way how to deal with the condition codes, but if that is not readable, I had (back then) a couple of macros defined that set or cleared individual flags. clc/sec (carry bit), clz/sez (zero flag), or ... well, you know how the macro looks like that sets the x bit, right? (-:
It's a loooong time i have these macros. I just wanted shorter ones.
meynaf is offline  
Old 08 September 2020, 15:50   #11
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 53
Posts: 1,327
On Amiga tst.l 4.W can be used, but can be slow and its 4 bytes long.
Don_Adan is offline  
Old 08 September 2020, 15:54   #12
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 1,148
Quote:
Originally Posted by meynaf View Post
Do i want all these ugly tst after my bsr ?
Yes, you better do. The problem is that "secondary return codes" do not scale. As soon as the program and its functions grow larger, it becomes quite easy (I speak from experience) to forget setting the return code, or branching out of a subroutine without setting condition codes correctly. This then means bug-huntig fun for hours.


Take ARexx as a (negative) example: This is all assembly, in one big pile, and is almost impossible to maintain as it contains and lives from such techniques. It means that about 80% of the rexxsyslib.library is not callable from anything but assembler, and undocumented. It also meant that ARexx was never ported to anything, like AmigaOs 4, because it was basically impossible to read or impossible to follow. I know, I tried, and gave up on it.
Thomas Richter is offline  
Old 08 September 2020, 16:34   #13
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
Quote:
Originally Posted by Don_Adan View Post
On Amiga tst.l 4.W can be used, but can be slow and its 4 bytes long.
Yes I had thought about this too, but, apart from the reasons you said, is that you cannot use your function when exec is destroyed
ross is offline  
Old 08 September 2020, 17:06   #14
BastyCDGS
Registered User
 
Join Date: Nov 2015
Location: Freiburg / Germany
Age: 41
Posts: 149
Send a message via ICQ to BastyCDGS
Quote:
Originally Posted by meynaf View Post
Which is unfortunately not doable.
Remember, we may return either z=1 or z=0, and go to same rts if there are registers to restore (as using two movem would destroy code size benefit). Thus we can not insert anything between movem and rts.
No need to do a register restore if you want to use this trick.
tst.l (sp) directly before a rts will always do the job, because (sp) contains the return address in this case, which is always non-zero.

Only in the case you saved the registers, you must restore them before using the trick (but you must do this before rts anyway).

Or am I misunderstanding you?
BastyCDGS is offline  
Old 08 September 2020, 17:17   #15
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 1,148
Quote:
Originally Posted by BastyCDGS View Post
tst.l (sp) directly before a rts will always do the job, because (sp) contains the return address in this case, which is always non-zero.

But does a needless memory read and hence requires a bus cycle to potentially slow memory. Seriously, compare that to a tst.l <return register> (probably in cache), which does not require to read from memory, or an andi #..,ccr, which does not need that either.


All this looks like analyzing the toe of the elephant. There are far more important problems to be solved in software, and there are far more important tricks to be played to create fast software - than this.
Thomas Richter is offline  
Old 08 September 2020, 17:35   #16
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 2,890
If I read the OP correctly, I do believe the goal here wasn't so much speed as it was size. I do kind of agree it seems to be a very small thing, but then again I don't know why meynaf needs this code. It may be that he really does need something that is as small as possible.

One thing I've learned is that assuming a problem is small or unimportant tends to only work for the general case and not the specific. Anyway, enough about this.
roondar is offline  
Old 08 September 2020, 17:49   #17
meynaf
son of 68k
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 48
Posts: 4,315
Quote:
Originally Posted by Don_Adan View Post
On Amiga tst.l 4.W can be used, but can be slow and its 4 bytes long.
Of course, but andi to ccr is also 4 bytes long.


Quote:
Originally Posted by Thomas Richter View Post
Yes, you better do. The problem is that "secondary return codes" do not scale. As soon as the program and its functions grow larger, it becomes quite easy (I speak from experience) to forget setting the return code, or branching out of a subroutine without setting condition codes correctly. This then means bug-huntig fun for hours.
Setting the ccr, or setting d0, are equally easy to forget.


Quote:
Originally Posted by Thomas Richter View Post
Take ARexx as a (negative) example: This is all assembly, in one big pile, and is almost impossible to maintain as it contains and lives from such techniques. It means that about 80% of the rexxsyslib.library is not callable from anything but assembler, and undocumented. It also meant that ARexx was never ported to anything, like AmigaOs 4, because it was basically impossible to read or impossible to follow. I know, I tried, and gave up on it.
I can't tell without seeing the code myself. Perhaps asm is just not your cup of tea, after all. Or the code is really a mess, but this is doable in any language.
Now, is porting ARexx to something else a good idea ? Maybe not.


Quote:
Originally Posted by ross View Post
Yes I had thought about this too, but, apart from the reasons you said, is that you cannot use your function when exec is destroyed
Exec isn't destroyed in my case, but yes, it's not ideal.


Quote:
Originally Posted by BastyCDGS View Post
No need to do a register restore if you want to use this trick.
tst.l (sp) directly before a rts will always do the job, because (sp) contains the return address in this case, which is always non-zero.

Only in the case you saved the registers, you must restore them before using the trick (but you must do this before rts anyway).

Or am I misunderstanding you?
The problem is that of course the routine will not only need to return z=0. In some cases it will also return z=1 (this is the whole purpose of returning a bool, both values are possible).
So if the trick is done after restoring the regs, how can i restore the regs and return the other value ? Restoring them in another place would mean larger code.


Quote:
Originally Posted by Thomas Richter View Post
All this looks like analyzing the toe of the elephant. There are far more important problems to be solved in software, and there are far more important tricks to be played to create fast software - than this.
Then what are you doing here ?
You have more important things to do.


Quote:
Originally Posted by roondar View Post
If I read the OP correctly, I do believe the goal here wasn't so much speed as it was size. I do kind of agree it seems to be a very small thing, but then again I don't know why meynaf needs this code. It may be that he really does need something that is as small as possible.

One thing I've learned is that assuming a problem is small or unimportant tends to only work for the general case and not the specific. Anyway, enough about this.
It is true, it's more about size than speed. As speed critical code would probably inline things rather than calling functions.
And yes, the problem is small. It is more academic than anything else, to let me know if my current solution is the most adequate.
meynaf is offline  
Old 08 September 2020, 20:00   #18
Don_Adan
Registered User
 
Join Date: Jan 2008
Location: Warsaw/Poland
Age: 53
Posts: 1,327
Quote:
Originally Posted by ross View Post
Yes I had thought about this too, but, apart from the reasons you said, is that you cannot use your function when exec is destroyed
When exec is destroyed it will be works too, exec must be cleared for non working. If exec is cleared/destroyed program will be crashed Amiga. Im sure that meynaf mean about OS friendly coding. For non OS friendly coding tst.l A7 is not safe too. If i remember right, i see movem.l clear memory routine called after disabled interrupts, it looks like (if i remember right) :
lea EndBuffy,A0
move.l A7, StackPtr
sub.l A7,A7
moveg #0,d0
...
etc
movem.l D0-D7/A1-A7,-(A0)
movem.l D0-D7/A1-A7,-(A0)
movem.l D0-D7/A1-A7,-(A0)
etc

move.l StackPtr,A7
Don_Adan is offline  
Old 08 September 2020, 20:41   #19
ross
Defendit numerus

ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 51
Posts: 3,283
Quote:
Originally Posted by Don_Adan View Post
When exec is destroyed it will be works too, exec must be cleared for non working. If exec is cleared/destroyed program will be crashed Amiga. Im sure that meynaf mean about OS friendly coding. For non OS friendly coding tst.l A7 is not safe too. If i remember right, i see movem.l clear memory routine called after disabled interrupts, it looks like (if i remember right) :
lea EndBuffy,A0
move.l A7, StackPtr
sub.l A7,A7
moveg #0,d0
...
etc
movem.l D0-D7/A1-A7,-(A0)
movem.l D0-D7/A1-A7,-(A0)
movem.l D0-D7/A1-A7,-(A0)
etc

move.l StackPtr,A7
Yes, I meant by execbase cleared.
And yes, I've also seen a7 set to zero in some "extreme" routines.
ross is offline  
Old 09 September 2020, 09:41   #20
chb
Registered User

 
Join Date: Dec 2014
Location: germany
Posts: 324
Hmm, would a
Code:
btst Dn,#$FF
work? It's supposed to be modulo 8, so for any content of Dn it should clear the Z flag.

It's two words, unfortunately, but that's still a word less than andi to ccr.
chb is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
ccr behaviour of div for v=1 meynaf Coders. Asm / Hardware 9 02 December 2017 22:20
here are my computers set up mcbone Amiga scene 3 17 July 2013 20:00
move.w ccr,d0 on 68030 BlankVector support.WinUAE 11 05 February 2013 16:46
Aminet Set 1 to 10 wizard66 request.Other 2 15 June 2011 15:57
Tosec Set 0.29 Ahamay New to Emulation or Amiga scene 9 15 November 2004 10:03

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 22:07.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Page generated in 0.12769 seconds with 13 queries