English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 07 October 2023, 23:46   #1501
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,335
Quote:
Originally Posted by meynaf View Post
At the end... they are only human failures.
Which is why higher-level languages exist. Because errare humanum est.

The hardest-to-identify bugs I have encountered at work were when the type system was put out of play. And, luckily, I don’t work in rocketry or surgery.
idrougge is offline  
Old 07 October 2023, 23:48   #1502
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,335
Quote:
Originally Posted by malko View Post
As dramatic as this story is, I don't see the point you want to bring here nor the relation with this thread.
Another OT example : It is possible that in several years we will discover that actual/new (untested on the mid-long term) ARNm SRAS-CoV2 vaccines that have been given to the masses during the pandemic is responsible of the death of a lot of people. Will you then point out as guilty the team behind the conducted computerised simulations and the HLL language they have used to grant the safety of such vaccines ?
We have already ridiculed both the British health services and Microsoft because they used Excel to keep track of Covid-19 cases and because Excel discarded rows after a certain certain number.
idrougge is offline  
Old 08 October 2023, 00:22   #1503
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,335
Quote:
Originally Posted by meynaf View Post
Higher level ? On the Amiga ?
This is a problem. I hope we some day get higher-level languages on the Amiga — so that we may concentrate on the work at hand instead of dealing with low-level details like what function in what library to allocate an object and how to track its lifetime.

Quote:
Then we're just different. MY mistakes are often far from obvious. No compiler in the world would help me for these.
That is what I have been trying to tell you several times already. You are more than proficient in assembly and ThoR is more than proficient in C. Most people are far from your level and will cause crashes, trash memory and leave dangling allocations all over the place. Assembly will lead to crashes sooner and C will lead to memory leaks sooner. Neither are particularly helpful, but at least C offers some safeties which asm doesn’t.

Quote:
What, don't you like doing register allocation ? It is fun.
Not when you’re refactoring.

Quote:
I don't think so, no. Compiler register allocation is static : some are scratch, some are not. In asm this is dynamic.
Register allocation is much more static in assembly; you define register usage up-front. At least in C, the compiler has an opportunity to redefine register allocation when you rewrite a function.

Quote:
The biggest annoyances in programming are not details such as register allocation. It is startup/cleanup code and error handling. C does not protect against these -- but my asm library does.
This is, again, because C is a 1960s programming language. It is, considering the hardware it was developed on and the state of the art in languages when it was created, not even 1970s-era.

That said, if you can implement that in assembly, you could just as well create that in C.

Quote:
There are no vectors in 68k.
There are vectors if you declare them. Wouldn’t it be useful if you could us the + operator to add them just as you can use it to add BCD numbers or floating point numbers or decimal numbers?
idrougge is offline  
Old 08 October 2023, 00:28   #1504
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
@idrougge

There are plenty of HLL for amiga/68k, including variants of C++ from this millenium and even higher level language tools like Hollywood that allow people to just get useful stuff done PDQ.
Karlos is offline  
Old 08 October 2023, 00:41   #1505
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,335
Quote:
Originally Posted by meynaf View Post
Not that kind of vectors. The kind that is parallel computation (SIMD).
Keep in mind that raytracing software was a big niche on the Amiga (Imagine, Real3D, Caligari4D, Lightwave, Cinema4D), despite the lack of vector processing units.

Quote:
What, that C++ derivative without macros ?
Considering the macro implementation in C, perhaps they were better off.

That said, C# is in no way a C++ derivate. It is a Java derivative.

Quote:
If you need to constantly refactor, you've made something wrong to start with.
Who said that I wrote that code? It was most likely written in an Indian TCS sweatshop.

Quote:
You need to create objects for this to work and to use exceptions for error handling. This seems OK and when coding for windows this is exactly what i'm using. But for the Amiga, this has too much overhead for my taste.
Depends on where that code is. 10 000 extra cycles is nothing on a Motorola processor if it is executed only once during the program’s execution unless it is a CLI command in a tight loop.

Quote:
Right, but the point was that sometimes you can't silence compiler warnings by just working on the code (or you have to destroy it).
I have a zero-tolerance for compiler warnings because even if a single warning is inconsequential, it buries serious warnings which might grow more serious over the years.

Quote:
Again, read the thread's title. Recent C++ (C++11) on the Amiga, really ? Java on the Amiga, really ? Recent python on the Amiga, really ?
Well, you can write recent C++ for the Amiga. Not everything must be written on the Amiga.

Quote:
Should I write it in caps so that you finally understand ? I DO NOT DEFEND ASM CODING ON OTHER PLATFORMS !
Is it ok this time ?
Yes, thank you for that clarification. It makes your arguments a lot easier to comprehend, if you didn’t repeatedly refer to non-Amiga compilers.
idrougge is offline  
Old 08 October 2023, 00:47   #1506
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 4,335
Quote:
Originally Posted by meynaf View Post
Typical case is a warning that not all paths return a value, or when some variable is not initialized. Should be useful... except when it's just plain wrong !

Code:
if (val) {
	ret = something;
}
if (val <= 0) {
	ret = something_else;
}
if (val < 0) {
	ret = again_something_else;
}
return ret;
Compiler (MSVC) complains 'ret' may be not initialized, forcing me to perform fake init and generate unneeded code.
This shitty code would be caught in code review immediately.

Why is val written to repeatedly? An assembly programmer would never do this.
Why is val evaluated repeatedly? An assembly programmer would never do this.
Why isn’t the 0 case handled? An assembly programmer would never do this.
idrougge is offline  
Old 08 October 2023, 01:11   #1507
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
Quote:
Originally Posted by idrougge View Post
This shitty code would be caught in code review immediately.

Why is val written to repeatedly? An assembly programmer would never do this.
It isn't. It's tested repeatedly. ret is written two more than once, however. That's probably what you mean?

Quote:
Why is val evaluated repeatedly? An assembly programmer would never do this.
It probably isn't evaluated repeatedly, depending on what the compiler does with condition codes.

Quote:
Why isn’t the 0 case handled? An assembly programmer would never do this.
It is handled as one of the cases tests for <=, then the following check handles strictly less than zero.

I agree the code is bad but some of your interpretation of it is equally bad.
Karlos is offline  
Old 09 October 2023, 10:23   #1508
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
Quote:
Originally Posted by idrougge View Post
Which is why higher-level languages exist. Because errare humanum est.
Higher-level languages exist only because ancient cpus were unable to provide a decent way to code.


Quote:
Originally Posted by idrougge View Post
The hardest-to-identify bugs I have encountered at work were when the type system was put out of play. And, luckily, I don’t work in rocketry or surgery.
Depending what you mean by put out of play, it might show that the so-called type checking shouldn't be trusted too much...



Quote:
Originally Posted by idrougge View Post
This is a problem. I hope we some day get higher-level languages on the Amiga — so that we may concentrate on the work at hand instead of dealing with low-level details like what function in what library to allocate an object and how to track its lifetime.
And then we will discover higher-level means significantly heavier in resources (whatever they are).


Quote:
Originally Posted by idrougge View Post
That is what I have been trying to tell you several times already. You are more than proficient in assembly and ThoR is more than proficient in C. Most people are far from your level and will cause crashes, trash memory and leave dangling allocations all over the place. Assembly will lead to crashes sooner and C will lead to memory leaks sooner. Neither are particularly helpful, but at least C offers some safeties which asm doesn’t.
You may ignore memory leaks, but you can't ignore crashes.


Quote:
Originally Posted by idrougge View Post
Not when you’re refactoring.
This is what the "non existing registers" trick is for. Use d8,d9,a8,a9, and anything you can imagine so you can do your code without having to care that much about registers. Do actual register allocation once you're done.


Quote:
Originally Posted by idrougge View Post
Register allocation is much more static in assembly; you define register usage up-front. At least in C, the compiler has an opportunity to redefine register allocation when you rewrite a function.
No. In C you have D0-D1/A0-A1 that are scratch. Period. In asm they are whatever you define them to be. If you need to redefine, just do search-replace.
In asm you could even do inter-function allocation, to pass same parameters always in same registers and avoid unneeded data moving. For example, a whole bunch of routines could get A2 pointing to some structure, regardless if they actually access it or not. One day, one may call a sub-routine that needs it : nothing to change, it's already there - in C two prototypes would need to be altered.


Quote:
Originally Posted by idrougge View Post
This is, again, because C is a 1960s programming language. It is, considering the hardware it was developed on and the state of the art in languages when it was created, not even 1970s-era.
That does not make it a great tool today.


Quote:
Originally Posted by idrougge View Post
That said, if you can implement that in assembly, you could just as well create that in C.
Theoretically possible, but a magnitude more difficult. The C libraries would come in the way. Startup code might allocate things, etc.


Quote:
Originally Posted by idrougge View Post
There are vectors if you declare them. Wouldn’t it be useful if you could us the + operator to add them just as you can use it to add BCD numbers or floating point numbers or decimal numbers?
I can do this already, by simple macro or routine call.



Quote:
Originally Posted by idrougge View Post
Keep in mind that raytracing software was a big niche on the Amiga (Imagine, Real3D, Caligari4D, Lightwave, Cinema4D), despite the lack of vector processing units.
What does that change ?


Quote:
Originally Posted by idrougge View Post
Considering the macro implementation in C, perhaps they were better off.
They are inferior in comparison to asm macros, but still way better than nothing.
Now if you know of a language that has great macro implementation, i'd like to see it.


Quote:
Originally Posted by idrougge View Post
That said, C# is in no way a C++ derivate. It is a Java derivative.
And Java is C++ derivative, or maybe C derivative. Otherwise it wouldn't be using curly braces.


Quote:
Originally Posted by idrougge View Post
Who said that I wrote that code? It was most likely written in an Indian TCS sweatshop.
But then you only need to refactor that code once. You seemed to mean you were refactoring the very same code over and over...


Quote:
Originally Posted by idrougge View Post
Depends on where that code is. 10 000 extra cycles is nothing on a Motorola processor if it is executed only once during the program’s execution unless it is a CLI command in a tight loop.
Overhead is not only execution speed.


Quote:
Originally Posted by idrougge View Post
I have a zero-tolerance for compiler warnings because even if a single warning is inconsequential, it buries serious warnings which might grow more serious over the years.
And this is exactly what makes spurious warnings worse than they look.


Quote:
Originally Posted by idrougge View Post
Well, you can write recent C++ for the Amiga. Not everything must be written on the Amiga.
Right, but it is an additionnal constraint and won't make that code execute better.


Quote:
Originally Posted by idrougge View Post
Yes, thank you for that clarification. It makes your arguments a lot easier to comprehend, if you didn’t repeatedly refer to non-Amiga compilers.
I refer to non-Amiga compilers because they are what i'm using the most. I use Amiga compilers not for development but solely for code porting. Remember : on Amiga i do asm.



Quote:
Originally Posted by idrougge View Post
This shitty code would be caught in code review immediately.
It is not shitty code. But as soon as compiler fails, compiler defenders have to find an excuse.


Quote:
Originally Posted by idrougge View Post
Why is val written to repeatedly? An assembly programmer would never do this.
It is *not* written to.
If you meant ret instead of val, it is more efficient this way. Avoiding that write would have meant extra branching.


Quote:
Originally Posted by idrougge View Post
Why is val evaluated repeatedly? An assembly programmer would never do this.
Indeed, an assembler programmer wouldn't do this but rely on the CCR instead. How to do this in C ? Oh yeah, we can't.


Quote:
Originally Posted by idrougge View Post
Why isn’t the 0 case handled? An assembly programmer would never do this.
It is handled. Even Karlos could see this.
meynaf is offline  
Old 09 October 2023, 11:03   #1509
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
Quote:
Originally Posted by meynaf View Post
It is handled. Even Karlos could see this.
Well, I'm off to the burns unit...
Karlos is offline  
Old 09 October 2023, 11:45   #1510
AestheticDebris
Registered User
 
Join Date: May 2023
Location: Norwich
Posts: 378
Quote:
Originally Posted by meynaf View Post
Higher-level languages exist only because ancient cpus were unable to provide a decent way to code.
Honestly, that's the weirdest argument made in this entire thread. And that's really saying something.

Quote:
Originally Posted by meynaf View Post
And then we will discover higher-level means significantly heavier in resources (whatever they are).
The most scarce resource when doing development is cognitive load on the programmer. It is this that higher level language aim to reduce. By contrast memory and CPU time etc are remarkably cheap, even when programming on an Amiga.

Quote:
Originally Posted by meynaf View Post
You may ignore memory leaks, but you can't ignore crashes.
Asm is not immune to memory leaks, just as C is not immune to crashes, even though it may be more prone to crashed. Arguably, from an end user perspective, a crash is a far worse situation though since it almost inevitably means lost data.

Quote:
Originally Posted by meynaf View Post
No. In C you have D0-D1/A0-A1 that are scratch. Period. In asm they are whatever you define them to be. If you need to redefine, just do search-replace.
In asm you could even do inter-function allocation, to pass same parameters always in same registers and avoid unneeded data moving. For example, a whole bunch of routines could get A2 pointing to some structure, regardless if they actually access it or not. One day, one may call a sub-routine that needs it : nothing to change, it's already there - in C two prototypes would need to be altered.
You don't have any of these when coding in C, because C doesn't operate on registers, it operates on variables. The compiler is free to choose how to allocate registers as it sees fit. An updated compiler could use entirely different registers even without changing any code.

Quote:
Originally Posted by meynaf View Post
They are inferior in comparison to asm macros, but still way better than nothing.
Now if you know of a language that has great macro implementation, i'd like to see it.
Macros are a terrible idea, because they're basically just a nasty text replacement over the source code. It also means you have to two syntaxes - the language you're coding in and the language used by the Marco preprocessor.

Modern languages just let you express what you want using the language syntax and then handle things like inlining or specialisation via the compiler.

Quote:
Originally Posted by meynaf View Post
But then you only need to refactor that code once. You seemed to mean you were refactoring the very same code over and over...
In the real world code gets refactored a lot, even during development of a one off product that will never need maintenance. And that applies equally to code on the Amiga. Languages, like asm, that make it hard to do without just plain rewriting the code tend to dissuade people from bothering or ends up introducing bugs because so much has to be rewritten rather than refactored.

Quote:
Originally Posted by meynaf View Post

It is not shitty code. But as soon as compiler fails, compiler defenders have to find an excuse.
No, it's really shitty C. It's writing three dependent if statements, with no else clauses where a switch would have been perfectly suited. It's the kind of thing which gets a crappy grade when a first year student hands it in.

Quote:
Originally Posted by meynaf View Post
It is *not* written to.
If you meant ret instead of val, it is more efficient this way. Avoiding that write would have meant extra branching.
It's clearly not more efficient, otherwise you wouldn't be pointing it out. If you wrote idiomatic C rather than trying to micro-optimise what you imagine the asm will end up being, you'd likely have found the compiler would've spat out what you were expecting rather than get confused by weird code.

Quote:
Originally Posted by meynaf View Post

Indeed, an assembler programmer wouldn't do this but rely on the CCR instead. How to do this in C ? Oh yeah, we can't.

AestheticDebris is online now  
Old 09 October 2023, 12:00   #1511
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
The code as written, absolutely stinks. So, you do what any C programmer would do and refactor it:

From this:
Code:
    if (val) {
	    ret = something;
    }
    if (val <= 0) {
	    ret = something_else; /* overwritten */
    }
    if (val < 0) {
	    ret = again_something_else; /* overwritten again */
    }
To perhaps this:
Code:
    if (val < 0) {
        ret = again_something_else;
    } else if (val == 0) {
        ret = something_else;
    } else {
        ret = something;
    }
Depending on any prior knowledge of the probability of each case you might reorganise.

Putting those into a simple function (Stack parameters, return in d0), you get:

Code:
	lea (4,sp),a0
	move.l (a0)+,d1
	move.l (a0)+,d0
	move.l (a0)+,a1
	move.l (a0),a0
	tst.l d1
	blt .L3
	beq .L4
	rts
.L4:
	move.l a1,d0
	rts
.L3:
	move.l a0,d0
	rts
The compiler has used d1/a0/a1 to hold the parameters and maybe that's unnecessary for such a simple example (it could just move straight from the stack to d0), but the important point is how it used the CCR. It tests val (d1) and uses two conditional branch cases.
Karlos is offline  
Old 09 October 2023, 12:13   #1512
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
Quote:
Originally Posted by AestheticDebris View Post
Honestly, that's the weirdest argument made in this entire thread. And that's really saying something.
It's not weird, it's just how historically this happened.


Quote:
Originally Posted by AestheticDebris View Post
The most scarce resource when doing development is cognitive load on the programmer. It is this that higher level language aim to reduce. By contrast memory and CPU time etc are remarkably cheap, even when programming on an Amiga.
That is the kind of reasoning which led to the bloatwares we have today.
And even though higher level languages aim to reduce cognitive load, they don't actually reach the target.


Quote:
Originally Posted by AestheticDebris View Post
Asm is not immune to memory leaks, just as C is not immune to crashes, even though it may be more prone to crashed. Arguably, from an end user perspective, a crash is a far worse situation though since it almost inevitably means lost data.
The program will hopefully crash at the debug phase, long before it reaches the end user. And as said, a memory leak is more likely to be ignored there.


Quote:
Originally Posted by AestheticDebris View Post
You don't have any of these when coding in C, because C doesn't operate on registers, it operates on variables. The compiler is free to choose how to allocate registers as it sees fit. An updated compiler could use entirely different registers even without changing any code.
No it can't. Otherwise code produced by said compiler wouldn't be able to get linked with objects produced by anything else.


Quote:
Originally Posted by AestheticDebris View Post
Macros are a terrible idea, because they're basically just a nasty text replacement over the source code. It also means you have to two syntaxes - the language you're coding in and the language used by the Marco preprocessor.

Modern languages just let you express what you want using the language syntax and then handle things like inlining or specialisation via the compiler.
While this *might* work with code, it doesn't work with data.
Besides, the "two syntax" does not apply for asm.


Quote:
Originally Posted by AestheticDebris View Post
In the real world code gets refactored a lot, even during development of a one off product that will never need maintenance. And that applies equally to code on the Amiga. Languages, like asm, that make it hard to do without just plain rewriting the code tend to dissuade people from bothering or ends up introducing bugs because so much has to be rewritten rather than refactored.
Yeah sure, the never finished programs fallacy.


Quote:
Originally Posted by AestheticDebris View Post
No, it's really shitty C. It's writing three dependent if statements, with no else clauses where a switch would have been perfectly suited. It's the kind of thing which gets a crappy grade when a first year student hands it in.
If you attempt to rewrite this with a switch you're up to a bad surprise. It simply cannot be done this way, which tells a lot about your understanding of the problem.


Quote:
Originally Posted by AestheticDebris View Post
It's clearly not more efficient, otherwise you wouldn't be pointing it out.
Nonsense. What i have pointed out is a compiler wrongly reporting a situation, no more no less. And then compiler defenders have attacked one of my two examples while carefully ignoring the other.


Quote:
Originally Posted by AestheticDebris View Post
If you wrote idiomatic C rather than trying to micro-optimise what you imagine the asm will end up being, you'd likely have found the compiler would've spat out what you were expecting rather than get confused by weird code.
Idiomatic C leads to poor code. Always have, always will.
One day you will eventually know better than trusting compilers.



Quote:
Originally Posted by Karlos View Post
The code as written, absolutely stinks. So, you do what any C programmer would do and refactor it:

(...)

The compiler has used d1/a0/a1 to hold the parameters and maybe that's unnecessary for such a simple example (it could just move straight from the stack to d0), but the important point is how it used the CCR. It tests val (d1) and uses two conditional branch cases.
And you've just written code that does not work.
Again the code here has been simplified to the minimalistic way of reproducing the behaviour. I have explained this before.
Both if (val) and if (val<=0) also compute something that is used as input in case if (val<0).
meynaf is offline  
Old 09 October 2023, 13:35   #1513
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,233
Quote:
Originally Posted by meynaf View Post
Higher-level languages exist only because ancient cpus were unable to provide a decent way to code.
On the contrary. Decent CPUs exist because they were developed for the needs of compilers. The 6502 is not decent to code at, yet there are limited compilers. The features of this CPU makes it quite hard to create decent compilers for it: Small stack, no "stack indirect" adressing modes, lack of registers. Motorola learned and included in the 68K features that were (at the time) needed for the compilers. Look at movem, link, unlink, stack-indirect addressing, many registers. All these exist to make life for high-level languages suitable.


Quote:
Originally Posted by meynaf View Post
Depending what you mean by put out of play, it might show that the so-called type checking shouldn't be trusted too much...
That is the kind of reasoning that lead to development of software that is suitable for today's use cases. You wouldn't write a browser in assembler, and yet it is an omnipresent tool.




Quote:
Originally Posted by meynaf View Post

This is what the "non existing registers" trick is for. Use d8,d9,a8,a9, and anything you can imagine so you can do your code without having to care that much about registers. Do actual register allocation once you're done.
Which is just a bullshit convention - instead of calling it "d8", give it a decent name. For example "sum", "last_error" or "lifes_left". That is what languages all you to do. "d8" can mean anything, and it is not a particularly good hint for the reader to understand what it might be used for.




Quote:
Originally Posted by meynaf View Post

No. In C you have D0-D1/A0-A1 that are scratch. Period.
No, nonsense. You have scratches whatever the compiler makes scratches. Within a function, any decent compiler will allocate registers dynamically, even changing from line to line or functional block to block. Everything else is a "calling convention" that it follows - simply because its interfaces are also meant to be used from other languages. It is not the compiler that defines this interface, it is the ABI that does. That is, it is the AmigaOs ABI. Other systems used other ABIs. For example MacOs has "a5" as the "pointer to quickdraw globals", same as AmigaOs has "a6" as library basis.




Quote:
Originally Posted by meynaf View Post

In asm they are whatever you define them to be. If you need to redefine, just do search-replace.
Unless you replace one too much or one too little. Search-replace is not a programming principle because, when done by humans, it is error prone. Instead, you assign names to your objects, and let the compiler decide where to put them.


Quote:
Originally Posted by meynaf View Post

In asm you could even do inter-function allocation, to pass same parameters always in same registers and avoid unneeded data moving.
In C, you can even do function inlining and remove the entire function totally... with exactly the same source code. Then, the compiler also allocates registers as it seems fit. This is no magic at all.


If a function has external linkage, it cannot do of course because it must assume that the function is to be called from some other places without having this "register allocation" available. Thus, "if it matters, make your function static" and let the compiler do the magic for you.


Quote:
Originally Posted by meynaf View Post

It is not shitty code. But as soon as compiler fails, compiler defenders have to find an excuse.
It is shitty code, thrust me. If I had to review this code here at our lab, I would ask you to rewrite it. The problem is that it is not transparent - some branches are executed more than once, and the program flow is not obvious. The issue is: You do not write the code for yourself. You write it for somebody else to read. Even if this somebody else is your future you in two years from now. If you intend a trivial refactoring of code to add a feature, and fail to grasp the program flow by following each "if"-clause carefully, you'll run into a mistake. The code is not structured well.


Quote:
Originally Posted by meynaf View Post


If you meant ret instead of val, it is more efficient this way. Avoiding that write would have meant extra branching.
It does not really matter how "efficient" that code is - that is the matter of the compiler to figure out. It is "inefficient to update and refactor", and that is what matters in reality. Code that is easy to break is expensive to maintain, and that is costing more nerves than a slight inefficiency.





Quote:
Originally Posted by meynaf View Post


Indeed, an assembler programmer wouldn't do this but rely on the CCR instead. How to do this in C ? Oh yeah, we can't.
Because we won't need to. "Wartime story"? Look at the mathffp.library. That is originally Motorola code for fast floating point, hand optimized assembler. CBM just took this code (well, avoiding the term "licensed" because I don't know...) and put that into a library with minimal efford. Due to "speed reasons", the code accesses the sr in certain places to get hands on the condition code. Guess what happened? Motorola made "move from sr" priviliedged from the 68010 onwards, so CBM made the "minimal efford" approach of porting this to 68010 to have GetCC() from exec.library called. End result: It is slower than it needs to be because now the code has to load execbase and call through a function just to do what it had to do earlier.


Morale of the story: Premature optimization is the root of all evil. It was a bullshit optimization from Motorola in first place, it was unnecessary, and if they had followed good programming practise *not* to use the ccr to store side-information, the thing would have been portable to begin with.
Thomas Richter is offline  
Old 09 October 2023, 13:48   #1514
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
Quote:
Originally Posted by meynaf View Post
And you've just written code that does not work.
In what sense?
Code:
#include <stdio.h>

int testA(int val, int something, int something_else, int again_something_else) {
    int ret;
    if (val) {
	    ret = something;
    }
    if (val <= 0) {
	    ret = something_else;
    }
    if (val < 0) {
	    ret = again_something_else;
    }
    return ret;
}

int testB(int val, int something, int something_else, int again_something_else) {
    int ret;

    if (val < 0) {
        ret = again_something_else;
    } else if (val == 0) {
        ret = something_else;
    } else {
	    ret = something;
    }
    return ret;
}

int main(void) {
    for (int i = -1; i<2; ++i) {
        if (testA(i, 2, 3, 5) != testB(i, 2, 3, 5)) {
            printf("Failed for %d\n", i);
        } else {
            printf("Passed for %d\n", i);
        }
    }
    return 0;
}
Code:
Passed for -1
Passed for 0
Passed for 1
I appreciate I only tested the range -1 to +1, but is there some case that I missed here?
Karlos is offline  
Old 09 October 2023, 14:26   #1515
robinsonb5
Registered User
 
Join Date: Mar 2012
Location: Norfolk, UK
Posts: 1,153
Quote:
Originally Posted by Karlos View Post
In what sense?
I think meynaf just means that the example was stripped to the bone from a more complex original program, and that the original code wouldn't work if refactored in that way. (The final case depends on side effects of the first two cases.)
robinsonb5 is offline  
Old 09 October 2023, 14:50   #1516
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
Quote:
Originally Posted by Karlos View Post
In what sense?
See robinsonb5's reply.
meynaf is offline  
Old 09 October 2023, 15:19   #1517
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
Quote:
Originally Posted by Thomas Richter View Post
On the contrary. Decent CPUs exist because they were developed for the needs of compilers. The 6502 is not decent to code at, yet there are limited compilers. The features of this CPU makes it quite hard to create decent compilers for it: Small stack, no "stack indirect" adressing modes, lack of registers. Motorola learned and included in the 68K features that were (at the time) needed for the compilers. Look at movem, link, unlink, stack-indirect addressing, many registers. All these exist to make life for high-level languages suitable.
One doesn't preclude the other. Originally HLLs were developed because ML was too unwieldy. Then cpus got extra features to help with HLLs (and you could have noted that movem, stack-indirect addressing, many registers, actually everything except link/unlk, are all features that are useful for asm too).


Quote:
Originally Posted by Thomas Richter View Post
That is the kind of reasoning that lead to development of software that is suitable for today's use cases. You wouldn't write a browser in assembler, and yet it is an omnipresent tool.
Being omnipresent is perfectly compatible with being a bloatware.


Quote:
Originally Posted by Thomas Richter View Post
Which is just a bullshit convention - instead of calling it "d8", give it a decent name. For example "sum", "last_error" or "lifes_left". That is what languages all you to do. "d8" can mean anything, and it is not a particularly good hint for the reader to understand what it might be used for.
No, because names are then confused with memory.
By using that convention, the intent (use a register if possible) is clear.


Quote:
Originally Posted by Thomas Richter View Post
No, nonsense. You have scratches whatever the compiler makes scratches. Within a function, any decent compiler will allocate registers dynamically, even changing from line to line or functional block to block. Everything else is a "calling convention" that it follows - simply because its interfaces are also meant to be used from other languages. It is not the compiler that defines this interface, it is the ABI that does. That is, it is the AmigaOs ABI. Other systems used other ABIs. For example MacOs has "a5" as the "pointer to quickdraw globals", same as AmigaOs has "a6" as library basis.
That it comes from the ABI and not from the compiler is actually the point : the Amiga ABI says d0-d1/a0-a1 and compilers have to follow it.
Asm programmers can use whatever they want, on the contrary.


Quote:
Originally Posted by Thomas Richter View Post
Unless you replace one too much or one too little. Search-replace is not a programming principle because, when done by humans, it is error prone. Instead, you assign names to your objects, and let the compiler decide where to put them.
If the replacement is badly done, the code will not work at all and this is easy to find out.
Giving names to objects is done by humans and error prone too.


Quote:
Originally Posted by Thomas Richter View Post
In C, you can even do function inlining and remove the entire function totally... with exactly the same source code. Then, the compiler also allocates registers as it seems fit. This is no magic at all.
What ? Repeat the whole pack of functions for every call ? This is crazy.
I haven't said these functions were small enough to be candidates for inlining. Usually they are not.
Oh, and in asm too you can choose between inlining or not, by using macros and/or conditional assembly. No magic either.
... with the small exception that the assembler is required to respect what you want to assemble, where the compiler is perfectly allowed to not inline the code even if you asked for it (it's just a hint, not a requirement).


Quote:
Originally Posted by Thomas Richter View Post
If a function has external linkage, it cannot do of course because it must assume that the function is to be called from some other places without having this "register allocation" available. Thus, "if it matters, make your function static" and let the compiler do the magic for you.
As if compilers were able to do this magic.


Quote:
Originally Posted by Thomas Richter View Post
It is shitty code, thrust me. If I had to review this code here at our lab, I would ask you to rewrite it. The problem is that it is not transparent - some branches are executed more than once, and the program flow is not obvious. The issue is: You do not write the code for yourself. You write it for somebody else to read. Even if this somebody else is your future you in two years from now. If you intend a trivial refactoring of code to add a feature, and fail to grasp the program flow by following each "if"-clause carefully, you'll run into a mistake. The code is not structured well.
Oh i'd like to thrust you, be sure, but to trust you is another story.
I already said it, doing this otherwise would have led to code duplication.


Quote:
Originally Posted by Thomas Richter View Post
It does not really matter how "efficient" that code is - that is the matter of the compiler to figure out. It is "inefficient to update and refactor", and that is what matters in reality. Code that is easy to break is expensive to maintain, and that is costing more nerves than a slight inefficiency.
Frankly this is a storm in a glass of water. If the reader thinks this code is bad, he can just attempt to rewrite it (and then understand why it was written this way).


Quote:
Originally Posted by Thomas Richter View Post
Because we won't need to. "Wartime story"? Look at the mathffp.library. That is originally Motorola code for fast floating point, hand optimized assembler. CBM just took this code (well, avoiding the term "licensed" because I don't know...) and put that into a library with minimal efford. Due to "speed reasons", the code accesses the sr in certain places to get hands on the condition code. Guess what happened? Motorola made "move from sr" priviliedged from the 68010 onwards, so CBM made the "minimal efford" approach of porting this to 68010 to have GetCC() from exec.library called. End result: It is slower than it needs to be because now the code has to load execbase and call through a function just to do what it had to do earlier.

Morale of the story: Premature optimization is the root of all evil. It was a bullshit optimization from Motorola in first place, it was unnecessary, and if they had followed good programming practise *not* to use the ccr to store side-information, the thing would have been portable to begin with.
I'm not really asking for an ability to use the CCR directly in C, just a way to avoid evaluating same things several times. As even though a compiler *might* be able to avoid this, it is nevertheless error prone.
meynaf is offline  
Old 09 October 2023, 16:18   #1518
AestheticDebris
Registered User
 
Join Date: May 2023
Location: Norwich
Posts: 378
Quote:
Originally Posted by robinsonb5 View Post
I think meynaf just means that the example was stripped to the bone from a more complex original program, and that the original code wouldn't work if refactored in that way. (The final case depends on side effects of the first two cases.)
The problem with that argument is that if no-one can see an example of that, then they're obviously going to judge that the code is nonsensical. And nobody can verify that the compiler isn't correct.

Quote:
Originally Posted by meynaf View Post
That it comes from the ABI and not from the compiler is actually the point : the Amiga ABI says d0-d1/a0-a1 and compilers have to follow it.
Asm programmers can use whatever they want, on the contrary.
Um, ASM code is supposed to follow the platform ABI too, otherwise if the OS has to get involved at some point (e.g. stack unwinding) you have no guarantees that things will work correctly. It's not a C thing, it's an AmigaOS thing. If a C program wanted to shove the OS entirely out of the way, it could happily use whatever conventions it likes.
AestheticDebris is online now  
Old 09 October 2023, 16:47   #1519
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
Quote:
Originally Posted by AestheticDebris View Post
The problem with that argument is that if no-one can see an example of that, then they're obviously going to judge that the code is nonsensical. And nobody can verify that the compiler isn't correct.
The code doesn't need to be readable, well designed, or even correct, to see that in this example the compiler was incorrect.
The compiler didn't warn that the code looked strange, it said that some variables weren't initialized in all code paths - which is just plain wrong. To see this, use VS2022.


Quote:
Originally Posted by AestheticDebris View Post
Um, ASM code is supposed to follow the platform ABI too, otherwise if the OS has to get involved at some point (e.g. stack unwinding) you have no guarantees that things will work correctly. It's not a C thing, it's an AmigaOS thing.
No, ASM code isn't required to follow the platform ABI. It only has to know that most OS calls are expected to trash D0-D1/A0-A1. Everywhere the OS isn't called (which is most of the code), the coder is free to do whatever he sees fit.
To port code from a 68k platform to another, everything platform specific (HW, OS calls) has to be replaced. The platform ABI is of absolutely no relevance ; if new code trashes more registers, just save them around the call.
And, stack unwinding made by the OS ? Serious ?


Quote:
Originally Posted by AestheticDebris View Post
If a C program wanted to shove the OS entirely out of the way, it could happily use whatever conventions it likes.
This has absolutely nothing to do with the OS.
I've seen compiled code using D0-D3/A0-A1 as scratch on an OS itself using D0-D2/A0-A2.
meynaf is offline  
Old 09 October 2023, 17:16   #1520
Karlos
Alien Bleed
 
Karlos's Avatar
 
Join Date: Aug 2022
Location: UK
Posts: 4,165
Quote:
Originally Posted by robinsonb5 View Post
I think meynaf just means that the example was stripped to the bone from a more complex original program, and that the original code wouldn't work if refactored in that way. (The final case depends on side effects of the first two cases.)
so something more like this then:

Code:
    if (val) {
	    ret = something;
            val = side_effect1(val);
    }
    if (val <= 0) {
	    ret = something_else;
            val = side_effect2(val);
    }
    if (val < 0) {
	    ret = again_something_else;
    }
When your code ends up like this you may need to rethink what you are doing.
Karlos 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
Chat GPT Amiga Assembly rcman Coders. Asm / Hardware 3 26 March 2023 20:24
An Amiga coder was banned without a reason - is it ok? litwr project.EAB 1 18 June 2021 20:38
Beginning Amiga Assembly Tutorial(s) Curbie Coders. Asm / Hardware 15 29 May 2020 00:21
Beginning Amiga Assembly Programming Hewitson Coders. Tutorials 32 09 October 2012 18:25
Amiga Assembly sources - Please help! W4r3DeV1L Amiga scene 21 16 July 2008 08:13

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 23:49.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.20709 seconds with 16 queries