Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #26645 > unrolled thread

Portable Assembly

Started byrickman <gnuarm@gmail.com>
First post2017-05-27 15:39 -0400
Last post2017-06-07 02:02 -0400
Articles 20 on this page of 95 — 24 participants

Back to article view | Back to comp.arch.embedded


Contents

  Portable Assembly rickman <gnuarm@gmail.com> - 2017-05-27 15:39 -0400
    Re: Portable Assembly Grant Edwards <invalid@invalid.invalid> - 2017-05-27 21:05 +0000
      Re: Portable Assembly Mel Wilson <mwilson@the-wire.com> - 2017-05-27 21:29 +0000
      Re: Portable Assembly upsidedown@downunder.com - 2017-05-28 00:36 +0300
        Re: Portable Assembly Grant Edwards <invalid@invalid.invalid> - 2017-05-27 21:56 +0000
          Re: Portable Assembly Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2017-05-28 14:36 +0200
        Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-05-29 09:53 +0200
    Re: Portable Assembly Les Cargill <lcargill99@comcast.com> - 2017-05-27 16:17 -0500
      Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-28 00:31 +0300
        Re: Portable Assembly Theo Markettos <theom+news@chiark.greenend.org.uk> - 2017-05-27 22:52 +0100
          Re: Portable Assembly Grant Edwards <invalid@invalid.invalid> - 2017-05-27 21:58 +0000
            Re: Portable Assembly upsidedown@downunder.com - 2017-05-28 07:37 +0300
              Re: Portable Assembly rickman <gnuarm@gmail.com> - 2017-05-28 01:28 -0400
              Re: Portable Assembly Tom Gardner <spamjunk@blueyonder.co.uk> - 2017-05-28 07:33 +0100
                Re: Portable Assembly rickman <gnuarm@gmail.com> - 2017-05-28 03:22 -0400
                  Re: Portable Assembly Tom Gardner <spamjunk@blueyonder.co.uk> - 2017-05-28 08:49 +0100
                  Re: Portable Assembly upsidedown@downunder.com - 2017-05-28 15:03 +0300
            Re: Portable Assembly Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2017-05-28 12:26 +0300
          Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-28 01:04 +0300
          Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-05-29 10:43 +0200
            Re: Portable Assembly Anssi Saari <as@sci.fi> - 2017-05-31 10:19 +0300
              Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-31 01:49 -0700
              Re: Portable Assembly Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2017-05-31 15:56 +0300
          Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-29 02:33 -0700
            Re: Portable Assembly upsidedown@downunder.com - 2017-05-29 23:46 +0300
              Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-29 13:54 -0700
        Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-27 15:52 -0700
          Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-28 02:14 +0300
            Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-27 17:14 -0700
              Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-28 03:38 +0300
                Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-27 18:42 -0700
        Re: Portable Assembly Stefan Reuther <stefan.news@arcor.de> - 2017-05-28 18:45 +0200
          Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-28 20:47 +0300
            Re: Portable Assembly Stefan Reuther <stefan.news@arcor.de> - 2017-05-29 18:43 +0200
              Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-29 10:23 -0700
              Re: Portable Assembly "Boudewijn Dijkstra" <sp4mtr4p.boudewijn@indes.com> - 2017-05-30 16:31 +0200
          Re: Portable Assembly Grant Edwards <invalid@invalid.invalid> - 2017-05-29 01:59 +0000
            Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-29 05:21 +0300
        Re: Portable Assembly Les Cargill <lcargill99@comcast.com> - 2017-05-28 22:04 -0500
          Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-29 02:57 -0700
        Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-05-29 11:00 +0200
          Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-29 15:08 +0300
            Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-05-29 15:06 +0200
              Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-29 20:02 +0300
                Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-05-29 23:13 +0200
                  Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-30 16:53 +0300
                    Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-05-31 11:36 +0200
                      Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-06-01 22:43 +0300
                        Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-06-02 13:27 +0200
            Re: Portable Assembly Grant Edwards <invalid@invalid.invalid> - 2017-05-29 13:48 +0000
      Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-05-27 15:46 -0700
      Re: Portable Assembly Tim Wescott <tim@seemywebsite.really> - 2017-05-28 23:59 -0500
    Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-05-28 00:23 +0300
    Re: Portable Assembly jim.brakefield@ieee.org - 2017-05-27 16:54 -0700
    Re: Portable Assembly Walter Banks <walter@bytecraft.com> - 2017-05-29 17:23 -0400
    Re: Portable Assembly "Boudewijn Dijkstra" <sp4mtr4p.boudewijn@indes.com> - 2017-06-02 17:03 +0200
      Re: Portable Assembly Mike Perkins <spam@spam.com> - 2017-06-05 15:39 +0100
        Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-06-05 18:10 +0200
        Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-05 09:10 -0700
          Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-06 00:24 -0400
            Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-06-06 11:05 +0200
            Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-06 07:03 -0700
              Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-06-06 16:58 +0200
                Re: Portable Assembly Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2017-06-06 21:26 +0300
              Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-06 16:42 -0400
                Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-06 23:16 -0700
                  Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-08 06:38 -0400
                    Re: Portable Assembly Dimiter_Popoff <dp@tgi-sci.com> - 2017-06-08 15:58 +0300
                      Re: Portable Assembly upsidedown@downunder.com - 2017-06-08 21:34 +0300
                        Re: Portable Assembly Les Cargill <lcargill99@comcast.com> - 2017-06-10 15:27 -0500
                      Re: Portable Assembly Les Cargill <lcargill99@comcast.com> - 2017-06-10 15:23 -0500
                    Re: Portable Assembly Tom Gardner <spamjunk@blueyonder.co.uk> - 2017-06-08 14:50 +0100
                      Re: Portable Assembly Tauno Voipio <tauno.voipio@notused.fi.invalid> - 2017-06-08 17:38 +0300
                        Re: Portable Assembly Tom Gardner <spamjunk@blueyonder.co.uk> - 2017-06-08 16:37 +0100
                      Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-09 14:14 -0400
                        Re: Portable Assembly Tom Gardner <spamjunk@blueyonder.co.uk> - 2017-06-09 22:25 +0100
                        Re: Portable Assembly Clifford Heath <no.spam@please.net> - 2017-06-10 09:54 +1000
                    Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-09 00:06 -0700
                      Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-09 22:14 -0400
                        Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-09 22:50 -0700
                          Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-10 21:01 -0400
                            Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-11 00:39 -0700
                              Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-12 23:27 -0400
                                Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-12 22:42 -0700
                                  Re: Portable Assembly Ed Prochak <edprochak@gmail.com> - 2017-06-13 14:24 -0700
                                    Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-13 21:57 -0700
                                      Re: Portable Assembly Reinhardt Behm <rbehm@hushmail.com> - 2017-06-14 13:26 +0800
                                        Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-13 23:58 -0700
                                          Re: Portable Assembly Ed Prochak <edprochak@gmail.com> - 2017-06-19 06:48 -0700
                                            Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-19 16:45 -0700
                                              Re: Portable Assembly Ed Prochak <edprochak@gmail.com> - 2017-06-20 15:07 -0700
                                                Re: Portable Assembly Don Y <blockedofcourse@foo.invalid> - 2017-06-21 07:37 -0700
                Re: Portable Assembly David Brown <david.brown@hesbynett.no> - 2017-06-07 09:20 +0200
            Re: Portable Assembly Niklas Holsti <niklas.holsti@tidorum.invalid> - 2017-06-07 00:30 +0300
              Re: Portable Assembly George Neuner <gneuner2@comcast.net> - 2017-06-07 02:02 -0400

Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →


#26679

FromDavid Brown <david.brown@hesbynett.no>
Date2017-05-29 11:00 +0200
Message-ID<oggnog$e4f$1@dont-email.me>
In reply to#26649
On 27/05/17 23:31, Dimiter_Popoff wrote:
> On 28.5.2017 г. 00:17, Les Cargill wrote:
>> rickman wrote:
>>> Someone in another group is thinking of using a portable assembler
>>> to write code for an app that would be ported to a number of
>>> different embedded processors including custom processors in FPGAs.
>>> I'm wondering how useful this will be in writing code that will
>>> require few changes across CPU ISAs and manufacturers.
>>>
>>> I am aware that there are many aspects of porting between CPUs that
>>> is assembly language independent, like writing to Flash memory.  I'm
>>> more interested in the issues involved in trying to use a universal
>>> assembler to write portable code in general.  I'm wondering if it
>>> restricts the instructions you can use or if it works more like a
>>> compiler where a single instruction translates to multiple target
>>> instructions when there is no one instruction suitable.
>>>
>>> Or do I misunderstand how a portable assembler works?  Does it
>>> require a specific assembly language source format for each target
>>> just like using the standard assembler for the target?
>>>
>>
>> That's what C is for.
> 
> Or Basic. Or Fortran etc.

Exactly - you use a programming language appropriate for the job.  For
most low-level work, that is C (or perhaps C++, if you /really/ know
what you are doing).  Some parts of your code will be target-specific C,
some parts will be portable C.  And a few tiny bits will be assembly or
"intrinsic functions" that are assembly made to look like C functions.

Most of the assembly used will actually be written by the toolchain
provider (startup code, library code, etc.) - and if you are using a
half-decent processor, this would almost certainly have been better
written in C than assembly.

C is /not/ a "portable assembly" - it means you don't /need/ a portable
assembly.

> 
> However, they are by far not what a "portable assembler" - existing
> under the name Virtual Processor Assembler in our house is.

No, it is not a "portable assembler".  It is just a translator to
generate PPC assembly from 68K assembly, because you had invested so
much time and code in 68K assembly and wanted to avoid re-writing
everything for the PPC.  That's a reasonable enough business strategy,
and an alternative to writing an emulator for the 68K on the PPC, or
some sort of re-compiler.

But it is not a "portable assembler".  If you can take code written in
your VPA and translate it into PIC, 8051, msp430, ARM, and x86 assembly,
in a way that gives near-optimal efficiency on each target, while
letting you write your VPA code knowing exactly which instructions will
be generated on the target, /then/ you would have a portable assembler.
 But such a language cannot be made, for obvious reasons.

What you have is a two-target sort-of assembler that gives you
reasonable code on two different targets.  You could also say that you
have your own personal low-level programming language with compiler
backends for two different targets.  Again, that's fair enough - and if
it lets you write the code you want, great.  But it is not a portable
assembly.


> And never will be, like any high level language C is yet another
> phrase book - convenient when you need to do a quick interaction
> when you don't speak the language - and only then.

Spoken like a true fanatic (or salesman).

> 
>>
>> This being said, I've been doing this for
>> 37 years and have only a few times seen an actual need for
>> portability - usually, the new hardware is so radically
>> different that porting makes little sense.
>>
> 
> The need for portability arises when you have megabytes of
> sources which are good and need to be moved to another, better
> platform. For smallish projects - anything which would fit in
> an MCU flash - porting is likely a waste of time, rewriting it
> for the new target will be faster if done by the same person
> who has already done it once.
> 

[toc] | [prev] | [next] | [standalone]


#26682

FromDimiter_Popoff <dp@tgi-sci.com>
Date2017-05-29 15:08 +0300
Message-ID<ogh2om$jio$1@dont-email.me>
In reply to#26679
On 29.5.2017 г. 12:00, David Brown wrote:
> On 27/05/17 23:31, Dimiter_Popoff wrote:
>.....
>>
>> However, they are by far not what a "portable assembler" - existing
>> under the name Virtual Processor Assembler in our house is.
>
> No, it is not a "portable assembler".  It is just a translator to
> generate PPC assembly from 68K assembly,  ....

I might agree with that - if we understand "portable" as "universally
portable".

>
> But it is not a "portable assembler".  If you can take code written in
> your VPA and translate it into PIC, 8051, msp430, ARM, and x86 assembly,

Well who in his right mind would try to port serious 68020 or sort of
code to a PIC or MSP430 etc.
I am talking about what is practical and has worked for me. It would be
a pain to port back from code I have written for power to
something with fewer registers but within reason it is possible and
can even be practical. Yet porting to power has been easier because
it had more registers than the original 68k and many other things,
it is just more powerful and very well thought, whoever did it knew
what he was doing. It even has little endian load and store opcodes...
(I wonder of ARM have big endian load/store opcodes).

Yet I agree it is not an "assembler" I suppose. I myself refer to it
at times as a compiler, then as an assembler... It can generate many
lines per statement - many opcodes, e.g. the 64/32 bit divide the 68020
has is done in a loop, no way around that (17 opcodes, just counted it).
Practically the same what any other compiler would have to do.

> in a way that gives near-optimal efficiency on each target, while
> letting you write your VPA code knowing exactly which instructions will
> be generated on the target, /then/ you would have a portable assembler.

It comes pretty close to that as long as your CPU has 32 registers,
but you need to know exactly what each line does only during debugging,
running step by step through the native code.

>> And never will be, like any high level language C is yet another
>> phrase book - convenient when you need to do a quick interaction
>> when you don't speak the language - and only then.
>
> Spoken like a true fanatic (or salesman).

It may sound so but it is not what I intended.
VPA has made me a lot more efficient than anyone else I have been able
to compare myself with. Since I also am only human it can't be down
to me, not by *that* much. It has to be down to something else; in all
likelihood it is the toolchain I use. My "phrasebook" comment
stays I'm afraid.

Dimiter

------------------------------------------------------
Dimiter Popoff, TGI             http://www.tgi-sci.com
------------------------------------------------------
http://www.flickr.com/photos/didi_tgi/

[toc] | [prev] | [next] | [standalone]


#26683

FromDavid Brown <david.brown@hesbynett.no>
Date2017-05-29 15:06 +0200
Message-ID<ogh669$v3p$1@dont-email.me>
In reply to#26682
On 29/05/17 14:08, Dimiter_Popoff wrote:
> On 29.5.2017 г. 12:00, David Brown wrote:
>> On 27/05/17 23:31, Dimiter_Popoff wrote:
>> .....
>>>
>>> However, they are by far not what a "portable assembler" - existing
>>> under the name Virtual Processor Assembler in our house is.
>>
>> No, it is not a "portable assembler".  It is just a translator to
>> generate PPC assembly from 68K assembly,  ....
> 
> I might agree with that - if we understand "portable" as "universally
> portable".
> 

"Universally portable" is perhaps a bit ambitious :-)  But to be called
a "portable assembly", I would expect a good deal more than two
architectures that are relatively closely related (32-bit, reasonably
orthogonal instruction sets, big endian).  I would imagine that
translating 68K assembly into PPC assembly is mostly straightforward -
unlike translating it into x86, or even ARM.  (The extra registers on
the PPC give you the freedom you need for converting complex addressing
modes on the 68K into reasonable PPC code - while the ARM has fewer
registers available.)

>>
>> But it is not a "portable assembler".  If you can take code written in
>> your VPA and translate it into PIC, 8051, msp430, ARM, and x86 assembly,
> 
> Well who in his right mind would try to port serious 68020 or sort of
> code to a PIC or MSP430 etc.

If the code were /portable/ assembly, then it would be possible.
Standard C code will work fine on the msp430, ARM, x86, 68K and PPC -
though it is unlikely to be efficient on a PIC or 8051.

> I am talking about what is practical and has worked for me. It would be
> a pain to port back from code I have written for power to
> something with fewer registers but within reason it is possible and
> can even be practical. Yet porting to power has been easier because
> it had more registers than the original 68k and many other things,
> it is just more powerful and very well thought, whoever did it knew
> what he was doing. It even has little endian load and store opcodes...
> (I wonder of ARM have big endian load/store opcodes).
> 

(I agree that the PPC is a fine ISA, and have enjoyed using it on a
couple of projects.  ARM Cortex M, the most prevalent cores for
microcontrollers, does not have big endian load or store opcodes.  But
it has byte-reverse instructions for both 16-bit and 32-bit values.  The
traditional ARM instruction set may have them - I am not as familiar
with that.)

If it were /portable/ assembly, then your code that works well for the
PPC would automatically work well for the 68K.

The three key points about assembly, compared to other languages, are
that you know /exactly/ what instructions will be generated, including
the ordering, register choices, etc., that you can access /all/ features
of the target cpu, and that you can write code that is as efficient as
possible for the target.  There is simply no way for this to portable.
Code written for the 68k may use complex addressing modes - they need
multiple instructions in PPC assembly.  If you do this mechanically, you
will know exactly what instructions this generates - but the result will
not be as efficient as code that re-uses registers or re-orders
instructions for better pipelining.  Code written for the PPC may use
more registers than are available on the 68K - /something/ has to give.

Thus your VLA may be a fantastic low-level programming language (having
never used it or seen it, I can't be sure - but I'm sure you would not
have stuck with it if it were not good!).  But it is not a portable
assembly language - it cannot let you write assembly-style code for more
than one target.

> Yet I agree it is not an "assembler" I suppose. I myself refer to it
> at times as a compiler, then as an assembler... It can generate many
> lines per statement - many opcodes, e.g. the 64/32 bit divide the 68020
> has is done in a loop, no way around that (17 opcodes, just counted it).
> Practically the same what any other compiler would have to do.

That's fine - you have a low-level language and a compiler, not a
portable assembler.

Some time it might be fun to look at some example functions, compiled
for either the 68K or the PPC (or, better still, both) and compare both
the source code and the generated object code to modern C and modern C
compilers.  (Noting that the state of C compilers has changed a great
deal since you started making VLA.)

> 
>> in a way that gives near-optimal efficiency on each target, while
>> letting you write your VPA code knowing exactly which instructions will
>> be generated on the target, /then/ you would have a portable assembler.
> 
> It comes pretty close to that as long as your CPU has 32 registers,
> but you need to know exactly what each line does only during debugging,
> running step by step through the native code.
> 
>>> And never will be, like any high level language C is yet another
>>> phrase book - convenient when you need to do a quick interaction
>>> when you don't speak the language - and only then.
>>
>> Spoken like a true fanatic (or salesman).
> 
> It may sound so but it is not what I intended.

Fair enough.

> VPA has made me a lot more efficient than anyone else I have been able
> to compare myself with. Since I also am only human it can't be down
> to me, not by *that* much. It has to be down to something else; in all
> likelihood it is the toolchain I use. My "phrasebook" comment
> stays I'm afraid.
> 

Good comparisons are, of course, extremely difficult - and not least,
extremely expensive.  You would need to do large scale experiments with
at least dozens of programmers working on a serious project before you
could compare efficiency properly.

[toc] | [prev] | [next] | [standalone]


#26686

FromDimiter_Popoff <dp@tgi-sci.com>
Date2017-05-29 20:02 +0300
Message-ID<oghk0h$hhr$1@dont-email.me>
In reply to#26683
On 29.5.2017 г. 16:06, David Brown wrote:
> .... I would imagine that
> translating 68K assembly into PPC assembly is mostly straightforward -
> unlike translating it into x86, or even ARM.  (The extra registers on
> the PPC give you the freedom you need for converting complex addressing
> modes on the 68K into reasonable PPC code - while the ARM has fewer
> registers available.)

Indeed, having more registers is of huge help. But it is not as straight
forward as it might seem at first glance. Then while at it I did a lot
more than just emulate the 68k - on power we have a lot more on offer,
I wanted to take advantage of it, like adding syntax to not touch
the CCR - as the 68k unavoidably does on moves, add and many others,
use the 3 address mode - source1,source2, destination - and have this
available not just as registers but as any addressing mode etc.
If you assemble plain CPU32 code the resulting power object code size is
about 3.5 times the native CPU32 code size. If you write with power
in mind - e.g. you discourage all the unnecessary CCR (CR in power)
updates - code sizes get pretty close. I have designed in a pass
for optimizing that automatically, 1.5 decades later still waiting
to happen... :-). No need for it which would deflect me from more
pressing issues I suppose.

>
> If it were /portable/ assembly, then your code that works well for the
> PPC would automatically work well for the 68K.

This is semantics - but since user level 68k code assembles directly
I think it is fair enough to borrow the word "assembler". Not what
everyone understands under it every time of course but must have
sounded OK to me back then. Then I am a practical person and tend
not to waste much time on names as long as they do not look
outright ugly or misleading (well I might go on purpose for "ugly"
of course but have not done it for vpa).

>
> The three key points about assembly, compared to other languages, are
> that you know /exactly/ what instructions will be generated, including
> the ordering, register choices, etc.,

Well yes, if we accept that we have to accept that VPA (Virtual
Processor Assembler) is not exactly an assembler. But I think the
name is telling enough what to expect.


> that you can access /all/ features
> of the target cpu, and that you can write code that is as efficient as
> possible for the target.

That is completely possible with vpa for power, nothing is stopping you
from using native to power opcodes (I use rwlinm and rlwimi quite often,
realizing there might be no efficient way to emulate them but I do what
I can do best, if I get stuck in a world with x86 processors only
which have just the few original 8086 registers I'll switch occupation
to herding kangaroos or something. Until then I'll change to a new
architecture only if I see why it is better than the one I use now,
for me portability is just a means, not a goal).

> There is simply no way for this to portable.
> Code written for the 68k may use complex addressing modes - they need
> multiple instructions in PPC assembly.

Yes but they run in fewer cycles. Apart from the PC relative - there is
no direct access to the PC on power, takes 2-3 opcodes to get to it
alone - the rest works faster. And say the An,Dn.l*4 mode can take
not just powers of 2... etc., it is pretty powerful.

>  If you do this mechanically, you
> will know exactly what instructions this generates - but the result will
> not be as efficient as code that re-uses registers or re-orders
> instructions for better pipelining.  Code written for the PPC may use
> more registers than are available on the 68K - /something/ has to give.

Oh yes, backward porting would be quite painful. I do use all registers
I have - rarely resorting to r4-r7, they are used for addressing mode
calculations, intermediate operands etc., use one of them and you
have something to work on when porting later. I still do it at times
when I think it is justified... may well bite me one day.

>
> Thus your VLA may be a fantastic low-level programming language (having
> never used it or seen it, I can't be sure - but I'm sure you would not
> have stuck with it if it were not good!).  But it is not a portable
> assembly language - it cannot let you write assembly-style code for more
> than one target.

Hmmm, not for any target - yes. For more than one target with the code
not losing efficiency - it certainly can, if the new target is right
(as was the case 68k -> power).
Basically I have never been after a "universal assembler", I just wanted
to do what you already know I wanted. How we call it is of secondary
interest to me to be fair :-).


> Some time it might be fun to look at some example functions, compiled
> for either the 68K or the PPC (or, better still, both) and compare both
> the source code and the generated object code to modern C and modern C
> compilers.  (Noting that the state of C compilers has changed a great
> deal since you started making VLA.)

Yes, I would also be curious to see that. Not just a function - as it
will likely have been written in assembly by the compiler author - but
some sort of standard thing, say a base64 encoder/decoder or some
vnc server thing etc. (the vnc server under dps is about 8 kilobytes,
just looked at it. Does one type of compression (RRE misused as RLE) and
raw).

Dimiter

======================================================
Dimiter Popoff, TGI             http://www.tgi-sci.com
======================================================
http://www.flickr.com/photos/didi_tgi/

[toc] | [prev] | [next] | [standalone]


#26690

FromDavid Brown <david.brown@hesbynett.no>
Date2017-05-29 23:13 +0200
Message-ID<ogi2mg$6lf$1@dont-email.me>
In reply to#26686
On 29/05/17 19:02, Dimiter_Popoff wrote:
> On 29.5.2017 г. 16:06, David Brown wrote:

<snipped some interesting stuff about VPA>

> 
>> Some time it might be fun to look at some example functions, compiled
>> for either the 68K or the PPC (or, better still, both) and compare both
>> the source code and the generated object code to modern C and modern C
>> compilers.  (Noting that the state of C compilers has changed a great
>> deal since you started making VLA.)
> 
> Yes, I would also be curious to see that. Not just a function - as it
> will likely have been written in assembly by the compiler author - but
> some sort of standard thing, say a base64 encoder/decoder or some
> vnc server thing etc. (the vnc server under dps is about 8 kilobytes,
> just looked at it. Does one type of compression (RRE misused as RLE) and
> raw).
> 

To be practical, it /should/ be a function - or no more than a few 
functions.  (I don't know why you think functions might be written in 
assembly by the compiler author - the compiler author is only going to 
provide compiler-assist functions such as division routines, floating 
point emulation, etc.)  And it should be something that has a clear 
algorithm, so no one can "cheat" by using a better algorithm for the job.

[toc] | [prev] | [next] | [standalone]


#26694

FromDimiter_Popoff <dp@tgi-sci.com>
Date2017-05-30 16:53 +0300
Message-ID<ogjt9d$skn$1@dont-email.me>
In reply to#26690
On 30.5.2017 г. 00:13, David Brown wrote:
> On 29/05/17 19:02, Dimiter_Popoff wrote:
>> On 29.5.2017 г. 16:06, David Brown wrote:
>
> <snipped some interesting stuff about VPA>
>
>>
>>> Some time it might be fun to look at some example functions, compiled
>>> for either the 68K or the PPC (or, better still, both) and compare both
>>> the source code and the generated object code to modern C and modern C
>>> compilers.  (Noting that the state of C compilers has changed a great
>>> deal since you started making VLA.)
>>
>> Yes, I would also be curious to see that. Not just a function - as it
>> will likely have been written in assembly by the compiler author - but
>> some sort of standard thing, say a base64 encoder/decoder or some
>> vnc server thing etc. (the vnc server under dps is about 8 kilobytes,
>> just looked at it. Does one type of compression (RRE misused as RLE) and
>> raw).
>>
>
> To be practical, it /should/ be a function - or no more than a few
> functions.  (I don't know why you think functions might be written in
> assembly by the compiler author - the compiler author is only going to
> provide compiler-assist functions such as division routines, floating
> point emulation, etc.)  And it should be something that has a clear
> algorithm, so no one can "cheat" by using a better algorithm for the job.
>
>

I am pretty sure I have seen - or read about - compiler generated
code where the compiler detects what you want to do and inserts
some assembly prewritten piece of code. Was something about CRC
or about tcp checksum, not sure - and it was someone who said that,
I don't know it from direct experience.

But if the compiler does this it will be obvious enough.

Anyway, a function would do - if complex and long enough to
be close to real life, i.e. a few hundred lines.

But I don't see why not compare written stuff, I just checked
again on that vnc server for dps - not 8k, closer to 11k (the 8k
I saw was a half-baked version, no keyboard tables inside it etc.;
the complete version also includes a screen mask to allow it
to ignore mouse clicks at certain areas, that sort of thing).
Add to it some menu (it is command line option driven only),
a much more complex menu than windows and android RealVNC has
I have and it adds up to 25k.
Compare this to the 350k exe for windows or to the 4M for Android
(and the android does only raw...) and the picture is clear enough
I think.

Dimiter

======================================================
Dimiter Popoff, TGI             http://www.tgi=sci.com
======================================================
http://www.flickr.com/photos/didi_tgi/











Dimiter

[toc] | [prev] | [next] | [standalone]


#26706

FromDavid Brown <david.brown@hesbynett.no>
Date2017-05-31 11:36 +0200
Message-ID<ogm2kl$hqj$1@dont-email.me>
In reply to#26694
On 30/05/17 15:53, Dimiter_Popoff wrote:
> On 30.5.2017 г. 00:13, David Brown wrote:
>> On 29/05/17 19:02, Dimiter_Popoff wrote:
>>> On 29.5.2017 г. 16:06, David Brown wrote:
>>
>> <snipped some interesting stuff about VPA>
>>
>>>
>>>> Some time it might be fun to look at some example functions, compiled
>>>> for either the 68K or the PPC (or, better still, both) and compare both
>>>> the source code and the generated object code to modern C and modern C
>>>> compilers.  (Noting that the state of C compilers has changed a great
>>>> deal since you started making VLA.)
>>>
>>> Yes, I would also be curious to see that. Not just a function - as it
>>> will likely have been written in assembly by the compiler author - but
>>> some sort of standard thing, say a base64 encoder/decoder or some
>>> vnc server thing etc. (the vnc server under dps is about 8 kilobytes,
>>> just looked at it. Does one type of compression (RRE misused as RLE) and
>>> raw).
>>>
>>
>> To be practical, it /should/ be a function - or no more than a few
>> functions.  (I don't know why you think functions might be written in
>> assembly by the compiler author - the compiler author is only going to
>> provide compiler-assist functions such as division routines, floating
>> point emulation, etc.)  And it should be something that has a clear
>> algorithm, so no one can "cheat" by using a better algorithm for the job.
>>
>>
> 
> I am pretty sure I have seen - or read about - compiler generated
> code where the compiler detects what you want to do and inserts
> some assembly prewritten piece of code. Was something about CRC
> or about tcp checksum, not sure - and it was someone who said that,
> I don't know it from direct experience.

A compiler sees the source code you write, and generates object code
that does that job.  It be smart about it, but it will not insert
"pre-written assembly code".  Code generation in compilers is usually
defined with some sort of templates (such a pattern for reading data at
a register plus offset, or a pattern for doing a shift by a fixed size,
etc.).  They are not "pre-written assembly", in that many of the details
are determined at generation time, such as registers, instruction
interleaving, etc.

The nearest you get to pre-written code from the compiler is in the
compiler support libraries.  For example, if the target does not support
division instructions, or floating point, then the compiler will supply
routines as needed.  These /might/ be written in assembly - but often
they are written in C.


A compiler /will/ detect patterns in your C code and use that to
generate object code rather than doing a "direct translation".  The
types of patterns it can detect varies - it is one of the things that
differentiates between compilers.  A classic example for the PPC would be:

#include <stdint.h>

uint32_t reverseLoad(uint32_t * p) {
  uint32_t x = *p;
  return ((x & 0xff000000) >> 24)
       | ((x & 0x00ff0000) >> 8)
       | ((x & 0x0000ff00) << 8)
       | ((x & 0x000000ff) << 24);
}

I am using gcc 4.8 here, since there is a convenient online version as
part of the <https://gcc.godbolt.org/> "compiler explorer".  gcc is at
7.0 these days, and has advanced significantly since then - but that is
the version that is most convenient.

A direct translation (compiling with no optimisation) would be:

reverseLoad:
        stwu 1,-48(1)
        stw 31,44(1)
        mr 31,1
        stw 3,24(31)
        lwz 9,24(31)
        lwz 9,0(9)
        stw 9,8(31)
        lwz 9,8(31)
        srwi 10,9,24
        lwz 9,8(31)
        rlwinm 9,9,0,8,15
        srwi 9,9,8
        or 10,10,9
        lwz 9,8(31)
        rlwinm 9,9,0,16,23
        slwi 9,9,8
        or 10,10,9
        lwz 9,8(31)
        slwi 9,9,24
        or 9,10,9
        mr 3,9
        addi 11,31,48
        lwz 31,-4(11)
        mr 1,11
        blr

Gruesome, isn't it?  Compiling with -O0 puts everything on the stack
rather than holding variables in registers.  Code like that was used in
the old days - perhaps at the time when you decided you needed something
better than C.  But even then, it was mainly only for debugging - since
debugger software was not good enough to handle variables in registers.

Next up, -O1 optimisation.  This is a level where the code becomes
sensible, but not too smart - and it is not uncommon to use it in
debugging because you usually get a one-to-one correspondence between
lines in the source code and blocks of object code.  It makes it easier
to do single stepping.

reverseLoad:
        lwz 9,0(3)
        slwi 3,9,24
        srwi 10,9,24
        or 3,3,10
        rlwinm 10,9,24,16,23
        or 3,3,10
        rlwinm 9,9,8,8,15
        or 3,3,9
        blr

Those that can understand the PPC's bit field instruction "rlwinm" will
see immediately that this is a straightforward translation of the source
code, but with all data held in registers.

But if we ask for smarter optimisation, with -O2, we get:

reverseLoad:
        lwbrx 3,0,3
        blr

This is, of course, optimal.  (Even the function call overhead will be
eliminated if the compiler can do so when the function is used.)


> 
> But if the compiler does this it will be obvious enough.

If you had some examples or references, it would be easier to see what
you mean.

> 
> Anyway, a function would do - if complex and long enough to
> be close to real life, i.e. a few hundred lines.

A function that is a few hundred lines of source code is /not/ real life
- it is broken code.  Surely in VLA you divide your code into functions
of manageable size, rather than single massive functions?

> 
> But I don't see why not compare written stuff, I just checked
> again on that vnc server for dps - not 8k, closer to 11k (the 8k
> I saw was a half-baked version, no keyboard tables inside it etc.;
> the complete version also includes a screen mask to allow it
> to ignore mouse clicks at certain areas, that sort of thing).
> Add to it some menu (it is command line option driven only),
> a much more complex menu than windows and android RealVNC has
> I have and it adds up to 25k.
> Compare this to the 350k exe for windows or to the 4M for Android
> (and the android does only raw...) and the picture is clear enough
> I think.
> 

A VNC server is completely useless for such a test.  It is far too
complex, with far too much variation in implementation and features, too
many external dependencies on an OS or other software (such as for
networking), and far too big for anyone to bother with such a comparison.

You specifically need something /small/.  The algorithm needs to be
simple and clearly expressible.  Total source code lines in C should be
no more than about a 100, with no more than perhaps 3 or 4 functions.
Smaller than that would be better, as it would make it easier for us to
understand the VLA and see its benefits.


Here is a possible example:

// Type for the data - this can easily be changed
typedef float data_t;

static int max(int a, int b) {
  return (a > b) ? a : b;
}

static int min(int a, int b) {
  return (a < b) ? a : b;
}


// Calculate the convolution of two input arrays pointed to by
// pA and pB, placing the results in the output array pC.
void convolute(const data_t * pA, int lenA, const data_t * pB,
    int lenB, data_t * pC, int lenC) {

  // i is the index of the output sample, run from 0 to lenC - 1
  // For each i, we calculate the sum as j goes from -inf to +inf
  // of A(j) * B(i - j)
  // Clearly we can limit j to the range 0 to (lenA - 1)
  // We use k to hold i - j, which will run down as j runs up.
  // k will be limited to (lenB - 1) down to 0.
  // From (i - j) >= 0, we have j <= i
  // From (i - j) < lenB, we have j > (i - lenB)
  // These give us tighter bounds on the run of j

  for (int i = 0; i < lenC; i++) {
    int firstJ = max(0, 1 + i - lenB);
    int endJ = min(lenA, i + 1);
    data_t x = 0;
    for (int j = firstJ; j < endJ; j++) {
      int k = i - j;
      x += (pA[j] * pB[k]);
    }

    pC[i] = x;
  }
}

With gcc 4.8 for the PPC, that's about 55 lines of assembly.  An
interesting point is that the size and instructions are very similar
with -O1 and -O2, but the ordering is significantly different - with
-O2, the pipeline scheduling is considered.  (I don't know which
particular cpu model is used for scheduling by default in gcc.)


To be able to compare with VLA, you'd have to write this algorithm in
VLA.  Then you could compare various points.  It should be easy enough
to look at the size of the code.  For speed comparison, we'd have to
know your target processor and compile specifically for that (to get the
best scheduling, and to handle small differences in the availability of
particular instructions).  Then you would need to run the code - I don't
have any PPC boards conveniently on hand, and of course you are the only
one with VLA tools.

Comparing code clarity and readability is, of course, difficult - but
you could publish your VLA and we can maybe get an idea.  Productivity
is also hard to measure.  For a function like this, the time is spent on
the details of the algorithm and getting the right bounds on the loops -
the actual C code is easy.


You can get a gcc 5.2 cross-compiler for PPC for Windows from here
<http://tranaptic.ca/wordpress/downloads/>, or you can use the online
compiler at <https://gcc.godbolt.org/>.  The PowerPC is not nearly as
popular an architecture as ARM, and it is harder to find free
ready-built tools (though there are plenty of guides to building them
yourself, and you can get supported commercial versions of modern gcc
from Mentor/CodeSourcery).  You can also find tools directly from
Freescale/NXP.

[toc] | [prev] | [next] | [standalone]


#26711

FromDimiter_Popoff <dp@tgi-sci.com>
Date2017-06-01 22:43 +0300
Message-ID<ogpqhh$ahc$1@dont-email.me>
In reply to#26706
On 31.5.2017 г. 12:36, David Brown wrote:
> On 30/05/17 15:53, Dimiter_Popoff wrote:
>> On 30.5.2017 г. 00:13, David Brown wrote:
>>> On 29/05/17 19:02, Dimiter_Popoff wrote:
>>>> On 29.5.2017 г. 16:06, David Brown wrote:
>>>
>>> <snipped some interesting stuff about VPA>
>>>
>>>>
>>>>> Some time it might be fun to look at some example functions, compiled
>>>>> for either the 68K or the PPC (or, better still, both) and compare both
>>>>> the source code and the generated object code to modern C and modern C
>>>>> compilers.  (Noting that the state of C compilers has changed a great
>>>>> deal since you started making VLA.)
>>>>
>>>> Yes, I would also be curious to see that. Not just a function - as it
>>>> will likely have been written in assembly by the compiler author - but
>>>> some sort of standard thing, say a base64 encoder/decoder or some
>>>> vnc server thing etc. (the vnc server under dps is about 8 kilobytes,
>>>> just looked at it. Does one type of compression (RRE misused as RLE) and
>>>> raw).
>>>>
>>>
>>> To be practical, it /should/ be a function - or no more than a few
>>> functions.  (I don't know why you think functions might be written in
>>> assembly by the compiler author - the compiler author is only going to
>>> provide compiler-assist functions such as division routines, floating
>>> point emulation, etc.)  And it should be something that has a clear
>>> algorithm, so no one can "cheat" by using a better algorithm for the job.
>>>
>>>
>>
>> I am pretty sure I have seen - or read about - compiler generated
>> code where the compiler detects what you want to do and inserts
>> some assembly prewritten piece of code. Was something about CRC
>> or about tcp checksum, not sure - and it was someone who said that,
>> I don't know it from direct experience.
>
> A compiler sees the source code you write, and generates object code
> that does that job.  It be smart about it, but it will not insert
> "pre-written assembly code".
   Code generation in compilers is usually
> defined with some sort of templates (such a pattern for reading data at
> a register plus offset, or a pattern for doing a shift by a fixed size,
> etc.).  They are not "pre-written assembly", in that many of the details
> are determined at generation time, such as registers, instruction
> interleaving, etc.
>
> The nearest you get to pre-written code from the compiler is in the
> compiler support libraries.  For example, if the target does not support
> division instructions, or floating point, then the compiler will supply
> routines as needed.  These /might/ be written in assembly - but often
> they are written in C.
>
>
> A compiler /will/ detect patterns in your C code and use that to
> generate object code rather than doing a "direct translation".   The
 > types of patterns it can detect varies - it is one of the things that
 > differentiates between compilers.

We are referring to the same thing under different names - again.
At the end of the day everything the compiler generates is written
in plain assembly, it must be executable by the CPU.
Under "prewritten" I mean some sort of template which gets filled
with addresses etc. thing before committing.
To what lengths the compiler writers go to make common cases look
good know only the writers themselves, my memory is vague but I
do think the guy who said that a few years ago knew what he was
talking about.

>..  A classic example for the PPC would be:
>
> #include <stdint.h>
>
> uint32_t reverseLoad(uint32_t * p) {
>    uint32_t x = *p;
>    return ((x & 0xff000000) >> 24)
>         | ((x & 0x00ff0000) >> 8)
>         | ((x & 0x0000ff00) << 8)
>         | ((x & 0x000000ff) << 24);
> }
>
> I am using gcc 4.8 here, since there is a convenient online version as
> part of the <https://gcc.godbolt.org/> "compiler explorer".  gcc is at
> 7.0 these days, and has advanced significantly since then - but that is
> the version that is most convenient.
>
> A direct translation (compiling with no optimisation) would be:
>
> reverseLoad:
>          stwu 1,-48(1)
>          stw 31,44(1)
>          mr 31,1
>          stw 3,24(31)
>          lwz 9,24(31)
>          lwz 9,0(9)
>          stw 9,8(31)
>          lwz 9,8(31)
>          srwi 10,9,24
>          lwz 9,8(31)
>          rlwinm 9,9,0,8,15
>          srwi 9,9,8
>          or 10,10,9
>          lwz 9,8(31)
>          rlwinm 9,9,0,16,23
>          slwi 9,9,8
>          or 10,10,9
>          lwz 9,8(31)
>          slwi 9,9,24
>          or 9,10,9
>          mr 3,9
>          addi 11,31,48
>          lwz 31,-4(11)
>          mr 1,11
>          blr
>
> Gruesome, isn't it?  Compiling with -O0 puts everything on the stack
> rather than holding variables in registers.  Code like that was used in
> the old days - perhaps at the time when you decided you needed something
> better than C.  But even then, it was mainly only for debugging - since
> debugger software was not good enough to handle variables in registers.
>
> Next up, -O1 optimisation.  This is a level where the code becomes
> sensible, but not too smart - and it is not uncommon to use it in
> debugging because you usually get a one-to-one correspondence between
> lines in the source code and blocks of object code.  It makes it easier
> to do single stepping.
>
> reverseLoad:
>          lwz 9,0(3)
>          slwi 3,9,24
>          srwi 10,9,24
>          or 3,3,10
>          rlwinm 10,9,24,16,23
>          or 3,3,10
>          rlwinm 9,9,8,8,15
>          or 3,3,9
>          blr
>
> Those that can understand the PPC's bit field instruction "rlwinm" will
> see immediately that this is a straightforward translation of the source
> code, but with all data held in registers.
>
> But if we ask for smarter optimisation, with -O2, we get:
>
> reverseLoad:
>          lwbrx 3,0,3
>          blr
>
> This is, of course, optimal.  (Even the function call overhead will be
> eliminated if the compiler can do so when the function is used.)

Above all this is a good example how limiting the high level language
is. Just look at the source and then at the final result.

You will get *exactly* the same result (- the return) with no
optimization in vpa from the line:

  mover.l (source),r3

Logic optimization is more or less a kindergarten exercise. If you need
logic optimization you don't know what you are doing anyway so the
compiler won't be able to help much, no matter how good.

Of course if you stick by a phrase book at source level - as is the case
with *any* high level language - you will need plenty of optimization,
like your example demonstrates. I bet it will will be good only in demo
cases like yours and much less useful in real life, so the only benefit
of writing this in C is the source length, 10+ times the necessary (I 
counted it and I included a return line in the count, 238 vs. 23 bytes).
While 10 times more typing may seem no serious issue to many 10 times
higher chance to insert an error is no laughing matter, and 10 times
more obscurity just because of that is a productivity killer.

>> But if the compiler does this it will be obvious enough.
>
> If you had some examples or references, it would be easier to see what
> you mean.
>
>>
>> Anyway, a function would do - if complex and long enough to
>> be close to real life, i.e. a few hundred lines.
>
> A function that is a few hundred lines of source code is /not/ real life
> - it is broken code.  Surely in VLA you divide your code into functions
> of manageable size, rather than single massive functions?

I meant "function" not the in C subroutine kind of sense, I meant it
more as "functionality", i.e. some code doing some job. How it split
into pieces etc. will depend on many factors, language, programmer
style etc., not relevant to this discussion.

>>
>> But I don't see why not compare written stuff, I just checked
>> again on that vnc server for dps - not 8k, closer to 11k (the 8k
>> I saw was a half-baked version, no keyboard tables inside it etc.;
>> the complete version also includes a screen mask to allow it
>> to ignore mouse clicks at certain areas, that sort of thing).
>> Add to it some menu (it is command line option driven only),
>> a much more complex menu than windows and android RealVNC has
>> I have and it adds up to 25k.
>> Compare this to the 350k exe for windows or to the 4M for Android
>> (and the android does only raw...) and the picture is clear enough
>> I think.
>>
>
> A VNC server is completely useless for such a test.  It is far too
> complex, with far too much variation in implementation and features, too
> many external dependencies on an OS or other software (such as for
> networking), and far too big for anyone to bother with such a comparison.

Actually I think a comparison between two pieces of code doing the same
thing is quite telling when the difference is in the orders of
magnitude, as in this case.
Writing small benchmarking toy sort of stuff is a waste of time, I am
interested in end results.

>
> You specifically need something /small/.

No, something "small" is kind of kindergarten exercise again, it can
only be good enough to fool someone into believing this or that.
It is end results which count.

Dimiter

======================================================
Dimiter Popoff, TGI             http://www.tgi-sci.com
======================================================
http://www.flickr.com/photos/didi_tgi/

[toc] | [prev] | [next] | [standalone]


#26717

FromDavid Brown <david.brown@hesbynett.no>
Date2017-06-02 13:27 +0200
Message-ID<ogrht1$5e7$1@dont-email.me>
In reply to#26711
On 01/06/17 21:43, Dimiter_Popoff wrote:
> On 31.5.2017 г. 12:36, David Brown wrote:
>> On 30/05/17 15:53, Dimiter_Popoff wrote:
>>> On 30.5.2017 г. 00:13, David Brown wrote:
>>>> On 29/05/17 19:02, Dimiter_Popoff wrote:
>>>>> On 29.5.2017 г. 16:06, David Brown wrote:
>>>>
>>>> <snipped some interesting stuff about VPA>
>>>>
>>>>>
>>>>>> Some time it might be fun to look at some example functions, compiled
>>>>>> for either the 68K or the PPC (or, better still, both) and compare
>>>>>> both
>>>>>> the source code and the generated object code to modern C and
>>>>>> modern C
>>>>>> compilers.  (Noting that the state of C compilers has changed a great
>>>>>> deal since you started making VLA.)
>>>>>
>>>>> Yes, I would also be curious to see that. Not just a function - as it
>>>>> will likely have been written in assembly by the compiler author - but
>>>>> some sort of standard thing, say a base64 encoder/decoder or some
>>>>> vnc server thing etc. (the vnc server under dps is about 8 kilobytes,
>>>>> just looked at it. Does one type of compression (RRE misused as
>>>>> RLE) and
>>>>> raw).
>>>>>
>>>>
>>>> To be practical, it /should/ be a function - or no more than a few
>>>> functions.  (I don't know why you think functions might be written in
>>>> assembly by the compiler author - the compiler author is only going to
>>>> provide compiler-assist functions such as division routines, floating
>>>> point emulation, etc.)  And it should be something that has a clear
>>>> algorithm, so no one can "cheat" by using a better algorithm for the
>>>> job.
>>>>
>>>>
>>>
>>> I am pretty sure I have seen - or read about - compiler generated
>>> code where the compiler detects what you want to do and inserts
>>> some assembly prewritten piece of code. Was something about CRC
>>> or about tcp checksum, not sure - and it was someone who said that,
>>> I don't know it from direct experience.
>>
>> A compiler sees the source code you write, and generates object code
>> that does that job.  It be smart about it, but it will not insert
>> "pre-written assembly code".
>   Code generation in compilers is usually
>> defined with some sort of templates (such a pattern for reading data at
>> a register plus offset, or a pattern for doing a shift by a fixed size,
>> etc.).  They are not "pre-written assembly", in that many of the details
>> are determined at generation time, such as registers, instruction
>> interleaving, etc.
>>
>> The nearest you get to pre-written code from the compiler is in the
>> compiler support libraries.  For example, if the target does not support
>> division instructions, or floating point, then the compiler will supply
>> routines as needed.  These /might/ be written in assembly - but often
>> they are written in C.
>>
>>
>> A compiler /will/ detect patterns in your C code and use that to
>> generate object code rather than doing a "direct translation".   The
>> types of patterns it can detect varies - it is one of the things that
>> differentiates between compilers.
> 
> We are referring to the same thing under different names - again.

OK.  I think your naming and description is odd, but I am glad to see we
are getting a better understanding of what the other is saying.

> At the end of the day everything the compiler generates is written
> in plain assembly, it must be executable by the CPU.
> Under "prewritten" I mean some sort of template which gets filled
> with addresses etc. thing before committing.

I think of "prewritten" as referring to larger chunks of assembly code,
with much more concrete choices of values, registers, scheduling, etc.
You described the "prewritten" code as being easily recognisable - in
reality, the majority of the code from modern compilers is generated
from very small templates with great variability.  And on a processor
like the PPC, these will be intertwined with each other according to the
best scheduling for the chip.

As an example, if we have the function:

int foo0(int * p) {
  int a = *p * *p;
  return a;
}

The template for reading "*p" generates

	lmz 3, 0(3)

(Register r3 is used for the first parameter in the PPC eabi.  It is
also used for the return value from a function, which is why it may seem
"over used" in the examples here.  In bigger code, and when the compiler
can inline functions, it will be more flexible about register choices.
I don't know whether you follow the standard PPC eabi in your tools.)

Multiplication is another template:

	mullw 3, 3, 3

As is function exit, in this case just:

	blr

I find it very strange to consider these as "pre-written assembly".

And if the function is more complex, the intertwining causes more
mixups, making it less "pre-written":

int foo1(int * p, int * q) {
  int a = *p * *p;
  int b = *q * *q;
  return a + b;
}

foo1:
	lwz 9,0(3)
	lwz 10,0(4)
	mullw 9,9,9
	mullw 3,10,10
	add 3,9,3
	blr


> To what lengths the compiler writers go to make common cases look
> good know only the writers themselves, my memory is vague but I
> do think the guy who said that a few years ago knew what he was
> talking about.

Well, it is known to the compiler writers and to users who look at the
generated code!  Certainly there is plenty of variation between tools,
with more advanced compilers working harder at this sort of thing.
Command line switches with choices of optimisation levels can also make
a big difference.

How much experience do you have of using C compilers, and studying their
output?

> 
>> ..  A classic example for the PPC would be:
>>
>> #include <stdint.h>
>>
>> uint32_t reverseLoad(uint32_t * p) {
>>    uint32_t x = *p;
>>    return ((x & 0xff000000) >> 24)
>>         | ((x & 0x00ff0000) >> 8)
>>         | ((x & 0x0000ff00) << 8)
>>         | ((x & 0x000000ff) << 24);
>> }
>>

<skipping the details>

>> But if we ask for smarter optimisation, with -O2, we get:
>>
>> reverseLoad:
>>          lwbrx 3,0,3
>>          blr
>>
>> This is, of course, optimal.  (Even the function call overhead will be
>> eliminated if the compiler can do so when the function is used.)
> 
> Above all this is a good example how limiting the high level language
> is. Just look at the source and then at the final result.

No, that is a good example of how smart the compiler is (or can be)
about generating optimal code from the source.

You may in addition view this as a limitation of the C language, which
has no direct way to specify a "bit reversed pointer".  That is fair
enough.  However, it is not really any harder than defining a function
like this, and then using it.  For situations where the compiler can't
generate ideal code, and it is particularly useful to get such optimal
assembly, it is also possible to write a simple little inline assembly
function - it is not really any harder than writing the same thing in
"normal" assembly.

Another option (for newer gcc) is to define the endianness of a struct.
 Then you can access the fields directly, and the loads and stores will
be reversed as needed.

typedef struct __attribute__((scalar_storage_order ("little-endian"))) {
  uint32_t x;
} le32_t;

uint32_t reverseLoad2(le32_t * p) {
  return p->x;
}

reverseLoad2:
        lwbrx 3,0,3
        blr


So the high level language gives you a number of options, with specific
tools giving more options, and the implementation gives you efficient
object code in the end.  You might need to define a function or macro
yourself, but that is a one-time job.

> 
> You will get *exactly* the same result (- the return) with no
> optimization in vpa from the line:
> 
>  mover.l (source),r3

When you say "no optimisation" here, does that mean that VPA supports
some kinds of optimisations?

> 
> Logic optimization is more or less a kindergarten exercise. If you need
> logic optimization you don't know what you are doing anyway so the
> compiler won't be able to help much, no matter how good.

What do you mean by "logic optimisation" ?  It is normal for a good
compiler to do a variety of strength reduction and other re-arrangements
of code to give you something with the same result, but more efficient
execution.  And it is a /good/ thing that the compiler does that - it
means you can write your source code in the clearest and most
maintainable fashion, and let the compiler generate better code.

For example, if you have a simple division by a constant:

uint32_t divX(uint32_t a) {
  return a / 5;
}

The direct translation of this would be:

divX:
	lis 4,5
	divwu 3,3,4
	blr

But a compiler can do better:

divX:			// divide by 5
        lis 9,0xcccc
        ori 9,9,52429
        mulhwu 3,3,9
        srwi 3,3,2
        blr

Such optimisation is certainly not a "kindergarten exercise", and doing
it by hand is hardly a maintainable or flexible solution.  Changing the
denominator to 7 means significant changes:

divX:			// divide by 7
        lis 9,0x2492
        ori 9,9,18725
        mulhwu 9,3,9
        subf 3,9,3
        srwi 3,3,1
        add 3,9,3
        srwi 3,3,2
        blr


> 
> Of course if you stick by a phrase book at source level - as is the case
> with *any* high level language - you will need plenty of optimization,
> like your example demonstrates. 

I still don't know what you mean with "phrase book" here.

> I bet it will will be good only in demo
> cases like yours and much less useful in real life, 

Nonsense.  The benefits of using a higher level language and a compiler
get more noticeable with larger code, as the compiler has no problem
tracking register usage, instruction scheduling, etc., across large
pieces of code - unlike a human.  And it has no problem re-creating code
in different ways when small details change in the source (such as the
divide by 5 and divide by 7 examples).

> so the only benefit
> of writing this in C is the source length, 10+ times the necessary (I
> counted it and I included a return line in the count, 238 vs. 23 bytes).

You have this completely backwards.  If I write a simple example like
this, in a manner that is compilable code, then it is going to take
longer in high-level source code.  But that is the effect of giving that
function definition.  In use, writing "reverseLoad" does not take
significantly more characters than "mover" - and with everything else
around, the C code will be much shorter.  And this was a case picked
specifically to show how some long patterns in C code can be handled by
a compiler to generate optimal short assembly sequences.

The division example shows the opposite - in C, I write "a / 7", while
in assembly you have to write 7 lines (excluding labels and blr).  And
the C code there is nicer in every way.


> While 10 times more typing may seem no serious issue to many 10 times
> higher chance to insert an error is no laughing matter, and 10 times
> more obscurity just because of that is a productivity killer.

In real code, the C source will be 10 times shorter than the assembly.
And if the assembly has enough comments to make it clear, there is
another order of magnitude difference.

> 
>>> But if the compiler does this it will be obvious enough.
>>
>> If you had some examples or references, it would be easier to see what
>> you mean.
>>
>>>
>>> Anyway, a function would do - if complex and long enough to
>>> be close to real life, i.e. a few hundred lines.
>>
>> A function that is a few hundred lines of source code is /not/ real life
>> - it is broken code.  Surely in VLA you divide your code into functions
>> of manageable size, rather than single massive functions?
> 
> I meant "function" not the in C subroutine kind of sense, I meant it
> more as "functionality", i.e. some code doing some job. How it split
> into pieces etc. will depend on many factors, language, programmer
> style etc., not relevant to this discussion.

OK.

But again, it has to be a specific clearly defined and limited
functionality.  "Write a VNC server" is not a specification - that would
take at least many dozens of pages of specifications, not including the
details of the interfacing to the network stack, the types of library
functions available, the API available to client programs that will
"draw" on the server, etc.

> 
>>>
>>> But I don't see why not compare written stuff, I just checked
>>> again on that vnc server for dps - not 8k, closer to 11k (the 8k
>>> I saw was a half-baked version, no keyboard tables inside it etc.;
>>> the complete version also includes a screen mask to allow it
>>> to ignore mouse clicks at certain areas, that sort of thing).
>>> Add to it some menu (it is command line option driven only),
>>> a much more complex menu than windows and android RealVNC has
>>> I have and it adds up to 25k.
>>> Compare this to the 350k exe for windows or to the 4M for Android
>>> (and the android does only raw...) and the picture is clear enough
>>> I think.
>>>
>>
>> A VNC server is completely useless for such a test.  It is far too
>> complex, with far too much variation in implementation and features, too
>> many external dependencies on an OS or other software (such as for
>> networking), and far too big for anyone to bother with such a comparison.
> 
> Actually I think a comparison between two pieces of code doing the same
> thing is quite telling when the difference is in the orders of
> magnitude, as in this case.

No, it is not.  The code is not comparable in any way, and does not do
the same thing except in a very superficial sense.  It's like comparing
a small car with a train - both can transport you around, but they are
very different things, each with their advantages and disadvantages.

If you want to compare your VNC server for DPS written in VPA to a VNC
server written in C, then you would need to give /exact/ specifications
of all the features of your VNC server, and exact details of how it
interfaces with everything else in the DPS system, and have someone
write a VNC server in C for DPS that follows those same specifications.
 That would be no small feat - indeed, it would totally impossible
unless you wanted to do it yourself.

The nearest existing comparison I can think of would be the eCos VNC
server, written in C.  I can't say how it compares in features with your
server, but it has approximately 2100 lines of code, written in a wide
style.  Since I have no idea about how interfacing with DPS compares
with interfacing with eCos (I don't know either system), I have no idea
if that is a useful comparison or not.

> Writing small benchmarking toy sort of stuff is a waste of time, I am
> interested in end results.
> 
>>
>> You specifically need something /small/.
> 
> No, something "small" is kind of kindergarten exercise again, it can
> only be good enough to fool someone into believing this or that.
> It is end results which count.
> 

Then we will all remain in ignorance about whether VPA is useful or not,
in comparison to developing in C.


[toc] | [prev] | [next] | [standalone]


#26684

FromGrant Edwards <invalid@invalid.invalid>
Date2017-05-29 13:48 +0000
Message-ID<ogh8rm$2u5$1@reader1.panix.com>
In reply to#26682
On 2017-05-29, Dimiter_Popoff <dp@tgi-sci.com> wrote:
> On 29.5.2017 г. 12:00, David Brown wrote:
>> On 27/05/17 23:31, Dimiter_Popoff wrote:
>>.....
>>>
>>> However, they are by far not what a "portable assembler" - existing
>>> under the name Virtual Processor Assembler in our house is.
>>
>> No, it is not a "portable assembler".  It is just a translator to
>> generate PPC assembly from 68K assembly,  ....
>
> I might agree with that - if we understand "portable" as "universally
> portable".
>
>>
>> But it is not a "portable assembler".  If you can take code written in
>> your VPA and translate it into PIC, 8051, msp430, ARM, and x86 assembly,
>
> Well who in his right mind would try to port serious 68020 or sort of
> code to a PIC or MSP430 etc.

Nobody.

Yet, that's what a "Universal Assembler" would be able to do.

> I am talking about what is practical and has worked for me.

And it is not anything close to a "Universal Assembler".

-- 
Grant

[toc] | [prev] | [next] | [standalone]


#26656

FromDon Y <blockedofcourse@foo.invalid>
Date2017-05-27 15:46 -0700
Message-ID<ogcvd1$uvi$1@dont-email.me>
In reply to#26647
On 5/27/2017 2:17 PM, Les Cargill wrote:
> That's what C is for.

Arguably, ANY HLL.

> This being said, I've been doing this for
> 37 years and have only a few times seen an actual need for
> portability - usually, the new hardware is so radically
> different that porting makes little sense.

Depends on how you handle your abstractions in the design.
If you tie the design directly to the hardware, then you've
implicitly made it dependent on that hardware -- without
even being aware of the dependencies.

OTOH, you can opt to create abstractions that give you a "slip sheet"
above the bare iron -- at some (small, if done well) cost in efficiency.
(e.g., "Hardware Abstraction Layer" -- though not necessarily as
explicit or limiting therein)

E.g., my current RTOS moves reasonably well between different hardware
platforms (I'm running on ARM and x86, currently) with the same sorts of
services exported to the higher level API's.

OTOH, the API's explicitly include provisions that allow the "application"
layers to tailor themselves to key bots of the hardware made largely
opaque by the API (e.g., MMU page sizes, number and granularity of hardware
timers, etc.)

But, this changes the level of proficiency required of folks working
with those API's.  Arguably, I guess it should (?)

Of course, if you want to shed all "hardware dependencies" and just code
to a POSIX API...  <shrug>

One could make an abstraction that is sufficiently *crude* (the equivalent of
single-transistor logic) and force the coder to use that as an implementation
language; then, recognize patterns of "operations" and map those to templates
that correlate with opcodes of a particular CPU (i.e., many operations -> one
opcode).  Or, the HLL approach of mapping *an* operation into a sequence of
CPU-specific opcodes.  Or, many<->many, in between.

[toc] | [prev] | [next] | [standalone]


#26676

FromTim Wescott <tim@seemywebsite.really>
Date2017-05-28 23:59 -0500
Message-ID<8bGdnSrXW6gAN7bEnZ2dnUU7-QudnZ2d@giganews.com>
In reply to#26647
On Sat, 27 May 2017 16:17:57 -0500, Les Cargill wrote:

> rickman wrote:
>> Someone in another group is thinking of using a portable assembler to
>> write code for an app that would be ported to a number of different
>> embedded processors including custom processors in FPGAs. I'm wondering
>> how useful this will be in writing code that will require few changes
>> across CPU ISAs and manufacturers.
>>
>> I am aware that there are many aspects of porting between CPUs that is
>> assembly language independent, like writing to Flash memory.  I'm more
>> interested in the issues involved in trying to use a universal
>> assembler to write portable code in general.  I'm wondering if it
>> restricts the instructions you can use or if it works more like a
>> compiler where a single instruction translates to multiple target
>> instructions when there is no one instruction suitable.
>>
>> Or do I misunderstand how a portable assembler works?  Does it require
>> a specific assembly language source format for each target just like
>> using the standard assembler for the target?
>>
>>
> That's what C is for.
> 
> This being said, I've been doing this for 37 years and have only a few
> times seen an actual need for portability - usually, the new hardware is
> so radically different that porting makes little sense.

I have used some very good portable C code across three or four different 
architectures (depending on whether you view a 188 and a 286 as different 
architectures).  This all in one company over the span of 9 years or so.

So -- perhaps your scope is limited?

-- 
www.wescottdesign.com

[toc] | [prev] | [next] | [standalone]


#26648

FromDimiter_Popoff <dp@tgi-sci.com>
Date2017-05-28 00:23 +0300
Message-ID<ogcqhm$ees$1@dont-email.me>
In reply to#26645
On 27.5.2017 г. 22:39, rickman wrote:
> Someone in another group is thinking of using a portable assembler to
> write code for an app that would be ported to a number of different
> embedded processors including custom processors in FPGAs.  I'm wondering
> how useful this will be in writing code that will require few changes
> across CPU ISAs and manufacturers.
>
> I am aware that there are many aspects of porting between CPUs that is
> assembly language independent, like writing to Flash memory.  I'm more
> interested in the issues involved in trying to use a universal assembler
> to write portable code in general.  I'm wondering if it restricts the
> instructions you can use or if it works more like a compiler where a
> single instruction translates to multiple target instructions when there
> is no one instruction suitable.
>
> Or do I misunderstand how a portable assembler works?  Does it require a
> specific assembly language source format for each target just like using
> the standard assembler for the target?
>

The only thing of that kind I know of is vpa (virtual processor
assembler) which I have created some 17 years ago.
Takes 68k source and assembles it into power architecture code.
It is a pretty huge thing, all dps (the OS I had originally written
for 68k (CPU32), toolchains, application code for our products etc.
etc. (millions of lines) go through it - and it can do a lot more
than just assemble statements, it does everything I ever wanted
it to do - and when it could not I extended it so it could.

It would be a lot simpler for a smaller processor and less
demanding code of course - as the typical mcu firmware would be.
Basically apart from some exceptions any source working on one
processor can be assembled into code for another one; and the
exceptions are not bulky, though critical - like some handlers within
the supervisor/hypervisor code, task switching, in general dealing
with exceptions is highly processor dependent - though in large part
the code which does the handling is still processor independent, one
has to go through it manually.

Dimiter

------------------------------------------------------
Dimiter Popoff, TGI             http://www.tgi-sci.com
------------------------------------------------------
http://www.flickr.com/photos/didi_tgi/

[toc] | [prev] | [next] | [standalone]


#26659

Fromjim.brakefield@ieee.org
Date2017-05-27 16:54 -0700
Message-ID<2aee4e7a-6bdb-4a11-938b-eb58b9effb09@googlegroups.com>
In reply to#26645
On Saturday, May 27, 2017 at 2:39:41 PM UTC-5, rickman wrote:
> Someone in another group is thinking of using a portable assembler to write 
> code for an app that would be ported to a number of different embedded 
> processors including custom processors in FPGAs.  I'm wondering how useful 
> this will be in writing code that will require few changes across CPU ISAs 
> and manufacturers.
> 
> I am aware that there are many aspects of porting between CPUs that is 
> assembly language independent, like writing to Flash memory.  I'm more 
> interested in the issues involved in trying to use a universal assembler to 
> write portable code in general.  I'm wondering if it restricts the 
> instructions you can use or if it works more like a compiler where a single 
> instruction translates to multiple target instructions when there is no one 
> instruction suitable.
> 
> Or do I misunderstand how a portable assembler works?  Does it require a 
> specific assembly language source format for each target just like using the 
> standard assembler for the target?
> 
> -- 
> 
> Rick C

]>ported to a number of different embedded processors including custom processors in FPGAs

It's possible to do direct threaded code in C.  For small projects, the number of threaded code routines is small and highly application specific.
So all the thread code segments are very portable and the debugging is in the threaded code routines (e.g. one can perfect the application in C on a PC and then migrate to any number of custom ISAs).

That said, am currently creating a system of symbolic constants for all the op-codes and operand values (using VHDL and for each specific ISA).  One can create symbolic constants for various locations in the code (and manually update the constants as code gets inserted or deleted).  Per-opcode functions can be defined that make code generation less troublesome.  The code (either constant expressions or function calls) is laid out as initialization for the instruction memory.  Simulation can be used to debug the code and the ISA.  A quick two step process: edit the code and run the simulator.

One can also write a C or any other language program that generates the binary code file which is then inserted into FPGA RAM during the FPGA compile step.  Typically one writes a separate function for each op-code or label generator (and for each ISA).  Two passes through all the function calls (e.g. the application program) first pass to generate the labels and the second pass to generate the binary file.  For use with FPGA simulation this is a three step process: edit the application program, run the binary file generator and run the FPGA simulator.

The preferred solution is to support label generators in the memory initialization sections of the VHDL or Verilog code.  
Would be very interested if someone has managed to do label generators?

[toc] | [prev] | [next] | [standalone]


#26691

FromWalter Banks <walter@bytecraft.com>
Date2017-05-29 17:23 -0400
Message-ID<ogi3fo$1pv0$1@gioia.aioe.org>
In reply to#26645
On 2017-05-27 3:39 PM, rickman wrote:
> Someone in another group is thinking of using a portable assembler to
>  write code for an app that would be ported to a number of different
>  embedded processors including custom processors in FPGAs.  I'm
> wondering how useful this will be in writing code that will require
> few changes across CPU ISAs and manufacturers.
> 
> I am aware that there are many aspects of porting between CPUs that
> is assembly language independent, like writing to Flash memory.  I'm
> more interested in the issues involved in trying to use a universal
> assembler to write portable code in general.  I'm wondering if it
> restricts the instructions you can use or if it works more like a
> compiler where a single instruction translates to multiple target
> instructions when there is no one instruction suitable.
> 
> Or do I misunderstand how a portable assembler works?  Does it
> require a specific assembly language source format for each target
> just like using the standard assembler for the target?
> 

I have done a few portable assemblers of the general type your
describing. There are two approaches. One is to write macro's for the
instruction set for the target processor and effectively assembler
processor A into processor B with macros. This might work for
architecturally close processors but even then has significant problems.
To give an example 6805 to 6502. The carry following the subtract of 0 -
0 is different.

There is one approach that I have used that does work reasonably well.
Assemble processor A into functionally rich intermediate code and
compile the intermediate code into processor B. The resulting code is
quite portable between the processors and it is capable of supporting a
diverse architectures quite well.

I have done mostly 8 bit processors this way 6808 3 major families to
PIC many varieties 12,14,14x,16 families. In all cases I set up the
translation so I could go either way. I have also targeted some 16,24,
and 32 bit processors. For pure code this has worked quite well with a
low penalty for the translation.

Application code usually has processor specific I/O which can actually
be detected by the translator but generally needs to have some hand
intervention.

w..

[toc] | [prev] | [next] | [standalone]


#26719

From"Boudewijn Dijkstra" <sp4mtr4p.boudewijn@indes.com>
Date2017-06-02 17:03 +0200
Message-ID<op.y07n39ubj0diun@thanatos.lan>
In reply to#26645
Op Sat, 27 May 2017 21:39:36 +0200 schreef rickman <gnuarm@gmail.com>:
> Someone in another group is thinking of using a portable assembler to  
> write code for an app that would be ported to a number of different  
> embedded processors including custom processors in FPGAs.  I'm wondering  
> how useful this will be in writing code that will require few changes  
> across CPU ISAs and manufacturers.
>
> I am aware that there are many aspects of porting between CPUs that is  
> assembly language independent, like writing to Flash memory.  I'm more  
> interested in the issues involved in trying to use a universal assembler  
> to write portable code in general.  I'm wondering if it restricts the  
> instructions you can use or if it works more like a compiler where a  
> single instruction translates to multiple target instructions when there  
> is no one instruction suitable.
>
> Or do I misunderstand how a portable assembler works?  Does it require a  
> specific assembly language source format for each target just like using  
> the standard assembler for the target?

LLVM has a pretty generic intermediate assembler language, though I'm not  
sure if it's meant for actually writing code in.

http://llvm.org/docs/LangRef.html#instruction-reference

Another portable assembly language is Java Bytecode, though it assumes a  
32-bit machine.


-- 
(Remove the obvious prefix to reply privately.)
Gemaakt met Opera's e-mailprogramma: http://www.opera.com/mail/

[toc] | [prev] | [next] | [standalone]


#26720

FromMike Perkins <spam@spam.com>
Date2017-06-05 15:39 +0100
Message-ID<oh3qeq$7lt$1@news2.open-news-network.org>
In reply to#26719
On 02/06/2017 16:03, Boudewijn Dijkstra wrote:
> Op Sat, 27 May 2017 21:39:36 +0200 schreef rickman <gnuarm@gmail.com>:
>> Someone in another group is thinking of using a portable assembler to
>> write code for an app that would be ported to a number of different
>> embedded processors including custom processors in FPGAs.  I'm
>> wondering how useful this will be in writing code that will require
>> few changes across CPU ISAs and manufacturers.
>>
>> I am aware that there are many aspects of porting between CPUs that is
>> assembly language independent, like writing to Flash memory.  I'm more
>> interested in the issues involved in trying to use a universal
>> assembler to write portable code in general.  I'm wondering if it
>> restricts the instructions you can use or if it works more like a
>> compiler where a single instruction translates to multiple target
>> instructions when there is no one instruction suitable.
>>
>> Or do I misunderstand how a portable assembler works?  Does it require
>> a specific assembly language source format for each target just like
>> using the standard assembler for the target?
>
> LLVM has a pretty generic intermediate assembler language, though I'm
> not sure if it's meant for actually writing code in.
>
> http://llvm.org/docs/LangRef.html#instruction-reference

Interesting, but its not obvious who the audience is. Why would anyone 
want to learn another language that is not in common use or aligned to 
any specific CPU?

> Another portable assembly language is Java Bytecode, though it assumes a
> 32-bit machine.

I've been watching this thread for some time. My first impression was 
why not just write in C? So far that impression hasn't changed. Despite 
the odd line of CPU specific assembler code for those occasions that 
require it, C is still perhaps the most portable code you can write?

-- 
Mike Perkins
Video Solutions Ltd
www.videosolutions.ltd.uk

[toc] | [prev] | [next] | [standalone]


#26721

FromDavid Brown <david.brown@hesbynett.no>
Date2017-06-05 18:10 +0200
Message-ID<oh3vim$npl$1@dont-email.me>
In reply to#26720
On 05/06/17 16:39, Mike Perkins wrote:
> On 02/06/2017 16:03, Boudewijn Dijkstra wrote:
>> Op Sat, 27 May 2017 21:39:36 +0200 schreef rickman <gnuarm@gmail.com>:
>>> Someone in another group is thinking of using a portable assembler to
>>> write code for an app that would be ported to a number of different
>>> embedded processors including custom processors in FPGAs.  I'm
>>> wondering how useful this will be in writing code that will require
>>> few changes across CPU ISAs and manufacturers.
>>>
>>> I am aware that there are many aspects of porting between CPUs that is
>>> assembly language independent, like writing to Flash memory.  I'm more
>>> interested in the issues involved in trying to use a universal
>>> assembler to write portable code in general.  I'm wondering if it
>>> restricts the instructions you can use or if it works more like a
>>> compiler where a single instruction translates to multiple target
>>> instructions when there is no one instruction suitable.
>>>
>>> Or do I misunderstand how a portable assembler works?  Does it require
>>> a specific assembly language source format for each target just like
>>> using the standard assembler for the target?
>>
>> LLVM has a pretty generic intermediate assembler language, though I'm
>> not sure if it's meant for actually writing code in.
>>
>> http://llvm.org/docs/LangRef.html#instruction-reference
> 
> Interesting, but its not obvious who the audience is. Why would anyone 
> want to learn another language that is not in common use or aligned to 
> any specific CPU?

The LLVM "assembly" is intended as an intermediary language.  Front-end 
tools like clang (a C, C++ and Objective-C compiler) generate LLVM 
assembly.  Middle-end tools like optimisers and linkers "play" with it. 
and back-end tools translate it into target-specific assembly.  Each 
level can do a wide variety of optimisations.  The aim is that the whole 
LLVM system can be more modular and more easily ported to new 
architectures and new languages than a traditional multi-language 
multi-target compiler (such as gcc).  So LLVM assembly is not an 
assembly language you would learn or code in - it's the glue holding the 
whole system together.

> 
>> Another portable assembly language is Java Bytecode, though it assumes a
>> 32-bit machine.
> 
> I've been watching this thread for some time. My first impression was 
> why not just write in C? So far that impression hasn't changed. Despite 
> the odd line of CPU specific assembler code for those occasions that 
> require it, C is still perhaps the most portable code you can write?
> 

Well, yes - of course C is the sensible option here.  Depending on the 
exact type of code and the targets, Ada, C++, and Forth might also be 
viable options.  But since there is no such thing as "portable 
assembly", it's a poor choice :-)  However, the thread has lead to some 
interesting discussions, IMHO.

[toc] | [prev] | [next] | [standalone]


#26722

FromDon Y <blockedofcourse@foo.invalid>
Date2017-06-05 09:10 -0700
Message-ID<oh3vin$npm$1@dont-email.me>
In reply to#26720
On 6/5/2017 7:39 AM, Mike Perkins wrote:
> On 02/06/2017 16:03, Boudewijn Dijkstra wrote:
>> LLVM has a pretty generic intermediate assembler language, though I'm
>> not sure if it's meant for actually writing code in.
>>
>> http://llvm.org/docs/LangRef.html#instruction-reference
>
> Interesting, but its not obvious who the audience is. Why would anyone want to
> learn another language that is not in common use or aligned to any specific CPU?

Esperanto?  :>

>> Another portable assembly language is Java Bytecode, though it assumes a
>> 32-bit machine.
>
> I've been watching this thread for some time. My first impression was why not
> just write in C? So far that impression hasn't changed. Despite the odd line of
> CPU specific assembler code for those occasions that require it, C is still
> perhaps the most portable code you can write?

The greater the level of abstraction in a language choice, the less
control you have over expressing the minutiae of what you want done.

When I design a new processor (typ. application specific), I code up
sample algorithms using a very low level set of abstractions... virtual
registers, virtual operators, etc.

Once I'm done with a number of these, I "eyeball" the "code" and sort out
what the instructions (opcodes) should be for the processor.  I.e., invent
the "assembly language".

If I'd coded these algorithms in a HIGHER level language, I'd end up
implementing a much more "complex" processor (because it would have
to implement much more capable "primitives")

C's portability problem isn't with the language, per se, as much as it is
with the "practitioners".  It could benefit from much stricter type
checking and a lot fewer "undefined/implementation-defined behaviors"
(cuz it seems folks just get the code working on THEIR target and
never see how it fails to execute properly on any OTHER target!)

[toc] | [prev] | [next] | [standalone]


#26723

FromGeorge Neuner <gneuner2@comcast.net>
Date2017-06-06 00:24 -0400
Message-ID<606cjc9l3kkpjq48efls9ddr8cqe8tc5aa@4ax.com>
In reply to#26722
On Mon, 5 Jun 2017 09:10:10 -0700, Don Y <blockedofcourse@foo.invalid>
wrote:

>C's portability problem isn't with the language, per se, as much as it is
>with the "practitioners".  It could benefit from much stricter type
>checking and a lot fewer "undefined/implementation-defined behaviors"
>(cuz it seems folks just get the code working on THEIR target and
>never see how it fails to execute properly on any OTHER target!)

The argument always has been that if implementation defined behaviors
are locked down, then C would be inefficient on CPUs that don't have
good support for <whatever>.


Look at the (historical) troubles resulting from Java (initially)
requiring IEEE-754 compliance and that FP results be exactly
reproducible *both* on the same platform *and* across platforms.

No FP hardware fully implements any version of IEEE-754: every chip
requires software fixups to achieve compliance, and most fixup suites
are not even complete [e.g., ignoring unpopular rounding modes, etc.].
Java FP code ran slower on chips that needed more fixups, and the
requirements prevented even implementing a compliant Java on some
chips despite their having FP support.

Java ultimately had to entirely back away from its reproducibility
guarantees.  It now requires only best consistency - not exact
reproducibility - on the same platform.  If you want reproducible
results, you have to use software floating point (BigFloat), and
accept much slower code.  And by requiring consistency, it can only
approximate the performance of C code which is likewise compiled. Most
C compilers allow to eshew FP consistency for more speed ... Java does
not.


Of course, FP in general is somewhat less important to this crowd than
to other groups, and C has a lot of implementation defined behavior
unrelated to FP.  But the lesson of trying to lock down hardware
(and/or OS) dependent behavior still is important.


There is no question that C could do much better type/value and
pointer/index checking, but it likely would come at the cost of far
more explicit casting (more verbose code), and likely many more
runtime checks.

A more expressive type system would help [e.g., range integers, etc.],
but that would constitute a significant change to the language.  

Some people point to Ada as an example of a language that can be both
"fast" and "safe", but many people (maybe not in this group, but many
nonetheless) are unaware that quite a lot of Ada's type/value checks
are done at runtime and throw exceptions if they fail.

Obviously, a compiler could provide a way to disable the automated
runtime checking, and even when enabled checks can be elided if the
compiler can statically prove that a given operation will always be
safe.  But even in Ada with its far more expressive types there are
many situations in which the compiler simply can't do that.

More stringent languages like ML won't even compile if they can't
statically type check the code.  In such languages, quite a lot of
programmer effort goes toward clubbing the type checker into
submission.


TANSTAAFL,
George

[toc] | [prev] | [next] | [standalone]


Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →

Back to top | Article view | comp.arch.embedded


csiph-web