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


Groups > comp.lang.c > #161725 > unrolled thread

naked switches

Started byRobert Finch <robfi680@gmail.com>
First post2021-07-07 16:39 -0700
Last post2021-09-30 18:04 +0200
Articles 20 on this page of 59 — 11 participants

Back to article view | Back to comp.lang.c


Contents

  naked switches Robert Finch <robfi680@gmail.com> - 2021-07-07 16:39 -0700
    Re: naked switches Bart <bc@freeuk.com> - 2021-07-08 01:26 +0100
    Re: naked switches Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-08 01:57 +0000
      Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-08 09:16 +0200
    Re: naked switches Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-08 01:00 -0700
      Re: naked switches Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2021-07-08 03:25 -0700
        Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-08 06:58 -0700
          Re: naked switches Bart <bc@freeuk.com> - 2021-07-08 15:52 +0100
          Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-08 17:52 +0200
            Re: naked switches Bart <bc@freeuk.com> - 2021-07-08 17:51 +0100
              Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 10:01 +0200
                Re: naked switches Bart <bc@freeuk.com> - 2021-07-09 11:09 +0100
                  Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 13:14 +0200
                  Re: naked switches Manfred <noname@add.invalid> - 2021-07-09 15:35 +0200
                    Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 16:51 +0200
                      Re: naked switches Manfred <noname@add.invalid> - 2021-07-09 18:23 +0200
                    Re: naked switches Bart <bc@freeuk.com> - 2021-07-09 16:07 +0100
                      Re: naked switches Manfred <noname@add.invalid> - 2021-07-09 18:41 +0200
                        Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-10 11:02 +0200
                      Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 19:20 +0200
                        Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-09 10:46 -0700
                          Re: naked switches Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-09 19:56 +0000
                          Re: naked switches Bart <bc@freeuk.com> - 2021-07-09 22:01 +0100
                            Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-09 15:07 -0700
                              Re: naked switches Bart <bc@freeuk.com> - 2021-07-09 23:30 +0100
                          Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-10 12:17 +0200
            Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-08 10:18 -0700
              Re: naked switches Bart <bc@freeuk.com> - 2021-07-08 18:43 +0100
                Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-08 15:32 -0700
              Re: naked switches Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-08 17:47 +0000
                Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-08 15:45 -0700
                  Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 10:27 +0200
                    Re: naked switches Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-09 11:13 +0100
                      Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 13:30 +0200
                      Re: naked switches Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-11 00:39 -0700
                        Re: naked switches scott@slp53.sl.home (Scott Lurndal) - 2021-07-11 14:06 +0000
                          Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-07-11 08:01 -0700
                          Re: naked switches Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-16 03:53 -0700
                            Re: naked switches scott@slp53.sl.home (Scott Lurndal) - 2021-07-16 14:47 +0000
                              Re: naked switches Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-09-30 06:09 -0700
                                Re: naked switches Robert Finch <robfi680@gmail.com> - 2021-09-30 07:03 -0700
                    Re: naked switches Bart <bc@freeuk.com> - 2021-07-09 13:44 +0100
                      Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-10 13:28 +0200
                        Re: naked switches Bart <bc@freeuk.com> - 2021-07-10 13:04 +0100
                          Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-10 15:39 +0200
                            Re: naked switches Bart <bc@freeuk.com> - 2021-07-10 15:08 +0100
                              Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-10 17:34 +0200
                                Re: naked switches Bart <bc@freeuk.com> - 2021-07-10 17:47 +0100
                Re: naked switches Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-11 00:57 -0700
                  Re: naked switches Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-07-16 03:51 -0700
          Re: naked switches Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-08 11:40 -0700
            Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 10:38 +0200
    Re: naked switches Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-08 17:33 +0000
      Re: naked switches scott@slp53.sl.home (Scott Lurndal) - 2021-07-08 17:47 +0000
        Re: naked switches Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-08 17:58 +0000
          Re: naked switches scott@slp53.sl.home (Scott Lurndal) - 2021-07-08 19:13 +0000
            Re: naked switches Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-09 02:30 +0000
          Re: naked switches David Brown <david.brown@hesbynett.no> - 2021-07-09 10:41 +0200
    Re: naked switches Bonita Montero <Bonita.Montero@gmail.com> - 2021-09-30 18:04 +0200

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


#161796

FromRobert Finch <robfi680@gmail.com>
Date2021-07-09 10:46 -0700
Message-ID<b34f9e99-bfce-4b2d-a01c-ba03037461c5n@googlegroups.com>
In reply to#161795
Is there a syntax for one-hot switches, switches that are based around powers of two? I would like the
compiler to optimize for usage of the BBS branch-on-bit set instruction if possible.

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


#161800

FromKaz Kylheku <563-365-8930@kylheku.com>
Date2021-07-09 19:56 +0000
Message-ID<20210709124909.355@kylheku.com>
In reply to#161796
On 2021-07-09, Robert Finch <robfi680@gmail.com> wrote:
> Is there a syntax for one-hot switches, switches that are based around
> powers of two? I would like the compiler to optimize for usage of the
> BBS branch-on-bit set instruction if possible.

No, there isn't; switching an integer value to cases labeled by constant
integer expressions is all there is.

You are probably looking at

#include <stdlib.h>

const char *sw(int x)
{
  if (x & 1)
    goto L1;
  if (x & 2)
    goto L2;
  if (x & 4)
    goto L4;
  if (x & 8)
    goto L8;
  if (x & 16)
    goto L16;
  if (x & 32)
    goto L32;

  abort();

  L1: return "one";
  L2: return "two";
  L4: return "four";
  L8: return "eight";
  L16: return "sixteen";
  L32: return "thirty-two";
}

That might use "branch if bit set", if such a thing is available in the
target instruction set. There is every opportunity to use it since the
mask is a constant expression testing one bit.


-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

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


#161801

FromBart <bc@freeuk.com>
Date2021-07-09 22:01 +0100
Message-ID<scadfp$4du$1@dont-email.me>
In reply to#161796
On 09/07/2021 18:46, Robert Finch wrote:
> Is there a syntax for one-hot switches, switches that are based around powers of two? I would like the
> compiler to optimize for usage of the BBS branch-on-bit set instruction if possible.
> 

The purpose of a switch statement is to enumerate all the values you're 
interested in. So here, you'd have cases for 1, 2, 4, 8, 16 and so on. 
Then you'd leave to the compiler to implement that as best it can.

If there are too many, use a function (or an inliner based on some 
instruction that tells you the position of first or last '1' bit), and 
use the result as a conventional linear index (0, 1, 2, 3, 4 instead of 
1, 2, 4, 8, 16).


(My own languages specifically use a jumptable for a switch. If it's not 
suitable (table would be too large), it will say so. Then you can change 
to a different statement - like switch, but a different keyword - which 
is implemented as a sequence of tests.

But also, a too-small jumptable might be changed automatically to that 
other statement, if it will be more efficient.)

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


#161804

FromRobert Finch <robfi680@gmail.com>
Date2021-07-09 15:07 -0700
Message-ID<ecc9dfb2-851e-430d-a4aa-fa8c403d1800n@googlegroups.com>
In reply to#161801
On Friday, July 9, 2021 at 5:01:56 PM UTC-4, Bart wrote:
> On 09/07/2021 18:46, Robert Finch wrote: 
> > Is there a syntax for one-hot switches, switches that are based around powers of two? I would like the 
> > compiler to optimize for usage of the BBS branch-on-bit set instruction if possible. 
> >
> The purpose of a switch statement is to enumerate all the values you're 
> interested in. So here, you'd have cases for 1, 2, 4, 8, 16 and so on. 
> Then you'd leave to the compiler to implement that as best it can. 
> 
I figured it out. The compiler now just looks at all the case values to determine if it is possible to use
BBS or BBC. There is no need for a special syntax.

> (My own languages specifically use a jumptable for a switch. If it's not 
> suitable (table would be too large), it will say so. Then you can change 
> to a different statement - like switch, but a different keyword - which 
> is implemented as a sequence of tests. 
> 
> But also, a too-small jumptable might be changed automatically to that 
> other statement, if it will be more efficient.)

I put a maximum limit on the size of a jump table of 1,000,000 entries in case some sort of code
generator is generating the cases. The table must be at least 33% populated, or a series of testing
and branching will be used.
A tabular switch will not be used if there are fewer than 3 cases.

800 LOC for switch processing in the compiler now.

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


#161806

FromBart <bc@freeuk.com>
Date2021-07-09 23:30 +0100
Message-ID<scaimi$gnc$1@dont-email.me>
In reply to#161804
On 09/07/2021 23:07, Robert Finch wrote:
> On Friday, July 9, 2021 at 5:01:56 PM UTC-4, Bart wrote:
>> On 09/07/2021 18:46, Robert Finch wrote:
>>> Is there a syntax for one-hot switches, switches that are based around powers of two? I would like the
>>> compiler to optimize for usage of the BBS branch-on-bit set instruction if possible.
>>>
>> The purpose of a switch statement is to enumerate all the values you're
>> interested in. So here, you'd have cases for 1, 2, 4, 8, 16 and so on.
>> Then you'd leave to the compiler to implement that as best it can.
>>
> I figured it out. The compiler now just looks at all the case values to determine if it is possible to use
> BBS or BBC. There is no need for a special syntax.
> 
>> (My own languages specifically use a jumptable for a switch. If it's not
>> suitable (table would be too large), it will say so. Then you can change
>> to a different statement - like switch, but a different keyword - which
>> is implemented as a sequence of tests.
>>
>> But also, a too-small jumptable might be changed automatically to that
>> other statement, if it will be more efficient.)
> 
> I put a maximum limit on the size of a jump table of 1,000,000 entries in case some sort of code
> generator is generating the cases. The table must be at least 33% populated, or a series of testing
> and branching will be used.

I thought this was for a small device! A switch of 334K to 1000K case 
labels is some switch statement, even if machine-generated. And also 
quite a hefty function body of at least 1 million lines for 1M labels.

I use a limit of 1000 labels for a desktop x64 processor. (Above 1000, 
other solutions might be better, such as tables of function pointers.)

Trying a switch of 500,000 cases, only Tiny C deals with it 
effortlessly. Other compilers either complain, or take forever.

> A tabular switch will not be used if there are fewer than 3 cases.
> 
> 800 LOC for switch processing in the compiler now.
> 

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


#161814

FromDavid Brown <david.brown@hesbynett.no>
Date2021-07-10 12:17 +0200
Message-ID<scbs35$uhm$1@dont-email.me>
In reply to#161796
On 09/07/2021 19:46, Robert Finch wrote:
> Is there a syntax for one-hot switches, switches that are based
> around powers of two? I would like the compiler to optimize for usage
> of the BBS branch-on-bit set instruction if possible.
> 

Not in C, no - there is not really any need.  (You get that kind of
thing in hardware design languages, as it is useful in programmable
logic and chip design).

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


#161756

FromRobert Finch <robfi680@gmail.com>
Date2021-07-08 10:18 -0700
Message-ID<7e094b82-01be-4d7f-9793-4eeda725ca0en@googlegroups.com>
In reply to#161753
>You wrote that you "have been working on a C/C++ like compiler" - do you
>mean you have been /using/ such a compiler, or you have been /writing/
>such a compiler?

I have been using it for simple demos, actually running the compiled code sometime. It has been revamped for several different custom processors, but is still a work in progress.

>As I mentioned earlier, I think a "naked switch" like this is a terrible
>idea.  It is not something I have seen on other compilers, and I've used
>quite a large number over the years for far smaller and slower devices
>than you are describing here.

It is a bad idea in terms of allowing program crashes. But then there are naked functions.

CC64 supports a number of “features” not found in standard C. But I call it a “C” like compiler because it can compile most C code without changes. I used it to compile the standard C library. Stills lots of bugs in the compiler though.

One feature I like is the ability to manipulate bit slices.

int a, b;

a = b[10:1];

Sets a equal to bits 1 to 10 of b. A bit slice can be distinguished from an array index by the colon. Compiles painlessly directly to field manipulation instructions and gets rid of code like:
a = (b >> 1) & 0x3ff;
Where the compiler really has to work to determine the bit operations.
enum allows the stride to be specified. enum(-1) { a,b,c }; will set the values to 0, -1, -2, .etc.
&&& means the same as && except that optimization of both side of the &&& is safe to do. There is also ||| and ?? operators.
In theory (not tried yet) classes with single inheritance and overloaded methods are supported. No templates or operator overloading though. Constructors / destructors not implemented yet.

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


#161758

FromBart <bc@freeuk.com>
Date2021-07-08 18:43 +0100
Message-ID<sc7dft$lre$1@dont-email.me>
In reply to#161756
On 08/07/2021 18:18, Robert Finch wrote:
>> You wrote that you "have been working on a C/C++ like compiler" - do you
>> mean you have been /using/ such a compiler, or you have been /writing/
>> such a compiler?
> 
> I have been using it for simple demos, actually running the compiled code sometime. It has been revamped for several different custom processors, but is still a work in progress.
> 
>> As I mentioned earlier, I think a "naked switch" like this is a terrible
>> idea.  It is not something I have seen on other compilers, and I've used
>> quite a large number over the years for far smaller and slower devices
>> than you are describing here.
> 
> It is a bad idea in terms of allowing program crashes. But then there are naked functions.
> 
> CC64 supports a number of “features” not found in standard C. But I call it a “C” like compiler because it can compile most C code without changes. I used it to compile the standard C library. Stills lots of bugs in the compiler though.
> 
> One feature I like is the ability to manipulate bit slices.
> 
> int a, b;
> 
> a = b[10:1];
> 
> Sets a equal to bits 1 to 10 of b. A bit slice can be distinguished from an array index by the colon. Compiles painlessly directly to field manipulation instructions and gets rid of code like:
> a = (b >> 1) & 0x3ff;
> Where the compiler really has to work to determine the bit operations.

I support such bit operations in my non-C languages, and I'm surprised 
they are not more widely available because they are so handy.

I guess that in C, programmers just have to keep reinventing the same 
macros for such purposes.

For your example, I'd use:

   a = b.[1..10]           # for one language, has to be in this order
   a = b.[1]               # extract a single bit

Without the dot, these would be regular slicing or indexing operations.

> enum allows the stride to be specified. enum(-1) { a,b,c }; will set the values to 0, -1, -2, .etc.

That would be a good idea, if I could think of a use-case! (But the 
reverse ordering of your example could be a problem.)

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


#161765

FromRobert Finch <robfi680@gmail.com>
Date2021-07-08 15:32 -0700
Message-ID<9932c0fa-98ac-4632-bd74-95f8feacafcan@googlegroups.com>
In reply to#161758
> 
> > enum allows the stride to be specified. enum(-1) { a,b,c }; will set the values to 0, -1, -2, .etc.
> That would be a good idea, if I could think of a use-case! (But the 
> reverse ordering of your example could be a problem.)

It was needed to return negative values for error codes from functions. I got tired of having to set all the values manually.
I had another case where the values needed to be spaced out.
Another case may be power of two values. 1,2,4,8,16,32,.... but I do not have a good way to specify this yet.

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


#161759

FromKaz Kylheku <563-365-8930@kylheku.com>
Date2021-07-08 17:47 +0000
Message-ID<20210708103653.702@kylheku.com>
In reply to#161756
On 2021-07-08, Robert Finch <robfi680@gmail.com> wrote:
>>You wrote that you "have been working on a C/C++ like compiler" - do you
>>mean you have been /using/ such a compiler, or you have been /writing/
>>such a compiler?
>
> I have been using it for simple demos, actually running the compiled code sometime. It has been revamped for several different custom processors, but is still a work in progress.
>
>>As I mentioned earlier, I think a "naked switch" like this is a terrible
>>idea.  It is not something I have seen on other compilers, and I've used
>>quite a large number over the years for far smaller and slower devices
>>than you are describing here.
>
> It is a bad idea in terms of allowing program crashes. But then there are naked functions.
>
> CC64 supports a number of “features” not found in standard C. But I call it a “C” like compiler because it can compile most C code without changes. I used it to compile the standard C library. Stills lots of bugs in the compiler though.
>
> One feature I like is the ability to manipulate bit slices.
>
> int a, b;
>
> a = b[10:1];
>
> Sets a equal to bits 1 to 10 of b. A bit slice can be distinguished
> from an array index by the colon. Compiles painlessly directly to
> field manipulation instructions and gets rid of code like: a = (b >>
> 1) & 0x3ff;

A macro can do this:

 a = BIT(b,10,1);

and works everywhere. What you need is a typeof extension to make it
work with different integer types while retaining efficiency, otherwise
you're looking at making it assume 64 bit, or saddling it with a type
name argument.

(typeof is a more valuable, not to mention simpler, extension; it is
useful in all kinds of macros.)

The _Generic mechanism in C11 can also be used to make BIT work
with diferent types.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

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


#161766

FromRobert Finch <robfi680@gmail.com>
Date2021-07-08 15:45 -0700
Message-ID<9a999021-6733-4d00-91fb-9797570a1328n@googlegroups.com>
In reply to#161759
On Thursday, July 8, 2021 at 1:47:12 PM UTC-4, Kaz Kylheku wrote:
> A macro can do this: 
> 
> a = BIT(b,10,1); 
> 
> and works everywhere. What you need is a typeof extension to make it 
> work with different integer types while retaining efficiency, otherwise 
> you're looking at making it assume 64 bit, or saddling it with a type 
> name argument. 

One should not have to write macros for commonly used language elements.

> (typeof is a more valuable, not to mention simpler, extension; it is 
> useful in all kinds of macros.) 

In CC64 there is a typenum() keyword that does almost the same thing. It returns a 16-bit hash-code for the type allowing RTTI. Someday I will get around to modifying it to typeof.
Otherwise with bit-slicing it ignores the type, assuming the bit slice can be done. It works only on the primitive types.

> TXR Programming Language: http://nongnu.org/txr 
> Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

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


#161774

FromDavid Brown <david.brown@hesbynett.no>
Date2021-07-09 10:27 +0200
Message-ID<sc9190$h4g$1@dont-email.me>
In reply to#161766
On 09/07/2021 00:45, Robert Finch wrote:
> On Thursday, July 8, 2021 at 1:47:12 PM UTC-4, Kaz Kylheku wrote:
>> A macro can do this: 
>>
>> a = BIT(b,10,1); 
>>
>> and works everywhere. What you need is a typeof extension to make it 
>> work with different integer types while retaining efficiency, otherwise 
>> you're looking at making it assume 64 bit, or saddling it with a type 
>> name argument. 
> 
> One should not have to write macros for commonly used language elements.

Your extension is not commonly used, because it only exists in your
tool.  People who need to do a lot of bit slicing and don't like masking
and shifting (or struct bit-fields) should not have trouble defining:

#define BIT(x, top, bottom) \
	(((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1))

Yes, the parenthesis you need for macros are ugly, but you only need to
get it right once, and now you can read your bit-fields.

Having said that, it is not at all unreasonable for an embedded compiler
to ship with extra headers, which would be an excellent place to put
macros like this for user convenience.  It would be simpler and clearer
to C programmers who are not used to your extensions.  This is the
technique used by other embedded compilers.

I'm not saying the extension is not useful, or bad in itself - but I
dislike adding extensions when it is perfectly possible to get the same
results without changing the language.  You need very good reasons for
adding non-portable extensions.  And when you do so, you should aim to
do it in a way that is familiar or portable, clear, flexible, and can
provide many benefits instead of needing lots of specialised extensions.


To make a macro (or inline function) that lets you /change/ the
bit-field is more difficult.  As Kaz says, doing that efficiently would
need _Generic (standard C, but not everyone has moved to C11) or a
"typeof" extension.  My recommendation here would be to implement
"typeof" in roughly the same way as gcc, clang, icc, Metroworks, and
other compilers, and roughly as it has been proposed as a new feature
for future C standards.  Then make your macros (or, better, static
inline functions) in a header that you ship with the compiler.


> 
>> (typeof is a more valuable, not to mention simpler, extension; it is 
>> useful in all kinds of macros.) 
> 
> In CC64 there is a typenum() keyword that does almost the same
> thing.  It returns a 16-bit hash-code for the type allowing RTTI. Someday I will
> get around to modifying it to typeof.

Your "typenum" might be useful, but it is not at all the same thing as
"typeof" :  <https://gcc.gnu.org/onlinedocs/gcc/Typeof.html>

> Otherwise with bit-slicing it ignores the type, assuming the bit
> slice can be done. It works only on the primitive types.
> 

(Please get a real newsreader and a real newsserver, rather than google
groups - amongst other benefits it would avoid the need to re-format
your posts due to GG's inability to follow Usenet standards.)

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


#161778

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2021-07-09 11:13 +0100
Message-ID<87czrr3ics.fsf@bsb.me.uk>
In reply to#161774
David Brown <david.brown@hesbynett.no> writes:

> Your extension [for extracting contiguous bits from a word] is not
> commonly used, because it only exists in your tool.  People who need
> to do a lot of bit slicing and don't like masking and shifting (or
> struct bit-fields) should not have trouble defining:
>
> #define BIT(x, top, bottom) \
> 	(((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1))
>
> Yes, the parenthesis you need for macros are ugly, but you only need to
> get it right once, and now you can read your bit-fields.

That's undefined when all the bits are wanted.  (The left shift of 1llu
could be equal to the width.)  Maybe you wrote it for a compiler that
documents an extension.

I usually right shift -1llu by the width minus the number of bits
wanted, but you can also just do two left shifts.

-- 
Ben.

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


#161780

FromDavid Brown <david.brown@hesbynett.no>
Date2021-07-09 13:30 +0200
Message-ID<sc9c05$m4k$1@dont-email.me>
In reply to#161778
On 09/07/2021 12:13, Ben Bacarisse wrote:
> David Brown <david.brown@hesbynett.no> writes:
> 
>> Your extension [for extracting contiguous bits from a word] is not
>> commonly used, because it only exists in your tool.  People who need
>> to do a lot of bit slicing and don't like masking and shifting (or
>> struct bit-fields) should not have trouble defining:
>>
>> #define BIT(x, top, bottom) \
>> 	(((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1))
>>
>> Yes, the parenthesis you need for macros are ugly, but you only need to
>> get it right once, and now you can read your bit-fields.
> 
> That's undefined when all the bits are wanted.  (The left shift of 1llu
> could be equal to the width.)  Maybe you wrote it for a compiler that
> documents an extension.
> 
> I usually right shift -1llu by the width minus the number of bits
> wanted, but you can also just do two left shifts.
> 

Yes, to cover all cases you could use:

	(1llu << ((top) - (bottom)) << 1)

It has always struck me as a little odd that (x << 32) is undefined (for
32-bit integers), even for unsigned x.  It's fine to be undefined for
signed types, but I'd have thought it should at least be
implementation-defined (for efficiency on different targets), rather
than undefined.  But I guess that's the rules, like it or not.

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


#161868

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-07-11 00:39 -0700
Message-ID<865yxh8fkf.fsf@linuxsc.com>
In reply to#161778
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> David Brown <david.brown@hesbynett.no> writes:
>
>> Your extension [for extracting contiguous bits from a word] is not
>> commonly used, because it only exists in your tool.  People who need
>> to do a lot of bit slicing and don't like masking and shifting (or
>> struct bit-fields) should not have trouble defining:
>>
>> #define BIT(x, top, bottom) \
>> 	(((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1))
>>
>> Yes, the parenthesis you need for macros are ugly, but you only need to
>> get it right once, and now you can read your bit-fields.
>
> That's undefined when all the bits are wanted.  (The left shift of 1llu
> could be equal to the width.)  Maybe you wrote it for a compiler that
> documents an extension.
>
> I usually right shift -1llu by the width minus the number of bits
> wanted, but you can also just do two left shifts.

Another way, assuming the mask width desired is greater
than zero, is this

    ((1LLU << width-1) -1) *2 +1

which works great if 'width' is a compile-time constant.

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


#161875

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-07-11 14:06 +0000
Message-ID<3WCGI.8419$rr3.5144@fx34.iad>
In reply to#161868
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> Your extension [for extracting contiguous bits from a word] is not
>>> commonly used, because it only exists in your tool.  People who need
>>> to do a lot of bit slicing and don't like masking and shifting (or
>>> struct bit-fields) should not have trouble defining:
>>>
>>> #define BIT(x, top, bottom) \
>>> 	(((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1))
>>>
>>> Yes, the parenthesis you need for macros are ugly, but you only need to
>>> get it right once, and now you can read your bit-fields.
>>
>> That's undefined when all the bits are wanted.  (The left shift of 1llu
>> could be equal to the width.)  Maybe you wrote it for a compiler that
>> documents an extension.
>>
>> I usually right shift -1llu by the width minus the number of bits
>> wanted, but you can also just do two left shifts.
>
>Another way, assuming the mask width desired is greater
>than zero, is this
>
>    ((1LLU << width-1) -1) *2 +1
>
>which works great if 'width' is a compile-time constant.

In the C++ world, we use this:

namespace bit
{
    template <class T> static inline T maskT(size_t bits)
    {
        if (bits >= sizeof(T)*8)
            return -1;
        else
            return ~(static_cast<T>(-1)<<bits);
    }

    template<class T> static inline T extract(T input, size_t stop_bit, size_t start_bit)
    {
        input >>= start_bit;
        input &= maskT<T>(stop_bit - start_bit + 1);
        return input;
    }

    static inline int64_t extracts(uint64_t input, size_t stop_bit, size_t start_bit)
    {
        int64_t imm = extract(input, stop_bit, start_bit);
        int shift = 63-stop_bit+start_bit;
        imm <<= shift;
        imm >>= shift;
        return imm;
    }

    template<class T> static inline T insert(T original, uint64_t insert, size_t start_bit, size_t width_bits)
    {
        T mask = bit::maskT<T>(width_bits);
        T newdata = mask & insert;
        mask <<= start_bit;
        newdata <<= start_bit;
        original &= ~mask;
        original |= newdata;
        return original;
    }
};

    uint64_t registervalue, field;
     int64_t field1;

    field = bit::extract(registervalue, 15, 0);      /* Extract <15:0> and zero-extend */
    field1 = bit::extracts((int64_t)registervalue, 20, 16);   /* Extract and sign-extend */

    registervalue = bit::insert(registervalue, 0xff, 16, 4); /* Set bits<19:16> == 0xff */

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


#161877

FromRobert Finch <robfi680@gmail.com>
Date2021-07-11 08:01 -0700
Message-ID<93b4fe04-1925-4089-8eb3-ecba3486c939n@googlegroups.com>
In reply to#161875
On Sunday, July 11, 2021 at 10:07:09 AM UTC-4, Scott Lurndal wrote:
> Tim Rentsch <tr.1...@z991.linuxsc.com> writes: 
> >Ben Bacarisse <ben.u...@bsb.me.uk> writes: 
> > 
> >> David Brown <david...@hesbynett.no> writes: 
> >> 
> >>> Your extension [for extracting contiguous bits from a word] is not 
> >>> commonly used, because it only exists in your tool. People who need 
> >>> to do a lot of bit slicing and don't like masking and shifting (or 
> >>> struct bit-fields) should not have trouble defining: 
> >>> 
> >>> #define BIT(x, top, bottom) \ 
> >>> (((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1)) 
> >>> 
> >>> Yes, the parenthesis you need for macros are ugly, but you only need to 
> >>> get it right once, and now you can read your bit-fields. 
> >> 
> >> That's undefined when all the bits are wanted. (The left shift of 1llu 
> >> could be equal to the width.) Maybe you wrote it for a compiler that 
> >> documents an extension. 
> >> 
> >> I usually right shift -1llu by the width minus the number of bits 
> >> wanted, but you can also just do two left shifts. 
> > 
> >Another way, assuming the mask width desired is greater 
> >than zero, is this 
> > 
> > ((1LLU << width-1) -1) *2 +1 
> > 
> >which works great if 'width' is a compile-time constant.
> In the C++ world, we use this: 
> 
> namespace bit 
> { 
> template <class T> static inline T maskT(size_t bits) 
> { 
> if (bits >= sizeof(T)*8) 
> return -1; 
> else 
> return ~(static_cast<T>(-1)<<bits); 
> } 
> 
> template<class T> static inline T extract(T input, size_t stop_bit, size_t start_bit) 
> { 
> input >>= start_bit; 
> input &= maskT<T>(stop_bit - start_bit + 1); 
> return input; 
> } 
> 
> static inline int64_t extracts(uint64_t input, size_t stop_bit, size_t start_bit) 
> { 
> int64_t imm = extract(input, stop_bit, start_bit); 
> int shift = 63-stop_bit+start_bit; 
> imm <<= shift; 
> imm >>= shift; 
> return imm; 
> } 
> 
> template<class T> static inline T insert(T original, uint64_t insert, size_t start_bit, size_t width_bits) 
> { 
> T mask = bit::maskT<T>(width_bits); 
> T newdata = mask & insert; 
> mask <<= start_bit; 
> newdata <<= start_bit; 
> original &= ~mask; 
> original |= newdata; 
> return original; 
> } 
> }; 
> 
> uint64_t registervalue, field; 
> int64_t field1; 
> 
> field = bit::extract(registervalue, 15, 0); /* Extract <15:0> and zero-extend */ 
> field1 = bit::extracts((int64_t)registervalue, 20, 16); /* Extract and sign-extend */ 
> 
> registervalue = bit::insert(registervalue, 0xff, 16, 4); /* Set bits<19:16> == 0xff */

I use the bit-slicing notation in part because the compiler I am using is not very sophisticated.
It cannot determine from a group of shifting and masking operations what bitfield instruction
to use. It does not have very sophisticated pattern matching for instruction sequences. Hence
to get efficient code from the compiler the bit-slicing syntax was added. It is as much to
support the compiler as it is for ease of use by the programmer.
 x = a[15:10]
Compiles directly to an extract instruction something like: ext $t0,$a0,#10,#5 – a single
instruction. If shifting and masking macros were used, the compiler would likely generate all
the operations, turning what should be a single cycle op into a multi-cycle multi-instruction op.

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


#161932

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-07-16 03:53 -0700
Message-ID<864kcu7cnx.fsf@linuxsc.com>
In reply to#161875
scott@slp53.sl.home (Scott Lurndal) writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
>>
>>> David Brown <david.brown@hesbynett.no> writes:
>>>
>>>> Your extension [for extracting contiguous bits from a word] is not
>>>> commonly used, because it only exists in your tool.  People who need
>>>> to do a lot of bit slicing and don't like masking and shifting (or
>>>> struct bit-fields) should not have trouble defining:
>>>>
>>>> #define BIT(x, top, bottom) \
>>>> 	(((x) >> (bottom)) & ((1llu << ((top) - (bottom) + 1)) - 1))
>>>>
>>>> Yes, the parenthesis you need for macros are ugly, but you only need to
>>>> get it right once, and now you can read your bit-fields.
>>>
>>> That's undefined when all the bits are wanted.  (The left shift of 1llu
>>> could be equal to the width.)  Maybe you wrote it for a compiler that
>>> documents an extension.
>>>
>>> I usually right shift -1llu by the width minus the number of bits
>>> wanted, but you can also just do two left shifts.
>>
>> Another way, assuming the mask width desired is greater
>> than zero, is this
>>
>>    ((1LLU << width-1) -1) *2 +1
>>
>> which works great if 'width' is a compile-time constant.
>
> In the C++ world, we use this:
>
> namespace bit
> {
>     template <class T> static inline T maskT(size_t bits)
>     {
>         if (bits >= sizeof(T)*8)
>             return -1;
>         else
>             return ~(static_cast<T>(-1)<<bits);
>     }
>
>     template<class T> static inline T extract(T input, size_t stop_bit, size_t start_bit)
>     {
>         input >>= start_bit;
>         input &= maskT<T>(stop_bit - start_bit + 1);
>         return input;
>     }
>
>     static inline int64_t extracts(uint64_t input, size_t stop_bit, size_t start_bit)
>     {
>         int64_t imm = extract(input, stop_bit, start_bit);
>         int shift = 63-stop_bit+start_bit;
>         imm <<= shift;
>         imm >>= shift;
>         return imm;
>     }
>
>     template<class T> static inline T insert(T original, uint64_t insert, size_t start_bit, size_t width_bits)
>     {
>         T mask = bit::maskT<T>(width_bits);
>         T newdata = mask & insert;
>         mask <<= start_bit;
>         newdata <<= start_bit;
>         original &= ~mask;
>         original |= newdata;
>         return original;
>     }
> };
>
>     uint64_t registervalue, field;
>      int64_t field1;
>
>     field = bit::extract(registervalue, 15, 0);      /* Extract <15:0> and zero-extend */
>     field1 = bit::extracts((int64_t)registervalue, 20, 16);   /* Extract and sign-extend */
>
>     registervalue = bit::insert(registervalue, 0xff, 16, 4); /* Set bits<19:16> == 0xff */

Ahh, rather like using an elephant gun to shoot a field mouse.

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


#161934

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-07-16 14:47 +0000
Message-ID<p_gII.3896$5Y6.3223@fx10.iad>
In reply to#161932
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>scott@slp53.sl.home (Scott Lurndal) writes:
>

>>
>>     uint64_t registervalue, field;
>>      int64_t field1;
>>
>>     field = bit::extract(registervalue, 15, 0);      /* Extract <15:0> and zero-extend */
>>     field1 = bit::extracts((int64_t)registervalue, 20, 16);   /* Extract and sign-extend */
>>
>>     registervalue = bit::insert(registervalue, 0xff, 16, 4); /* Set bits<19:16> == 0xff */
>
>Ahh, rather like using an elephant gun to shoot a field mouse.

The compiler generates optimal code[*].   The source is descriptive
and far more readable (and less subject to error) than manual bit
shifting/masking.

I don't see a problem.

[*] As inline functions, they're translated with the rest of the function.

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


#162877

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-09-30 06:09 -0700
Message-ID<86sfxmtdke.fsf@linuxsc.com>
In reply to#161934
scott@slp53.sl.home (Scott Lurndal) writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> scott@slp53.sl.home (Scott Lurndal) writes:
>>
>
>>>
>>>     uint64_t registervalue, field;
>>>      int64_t field1;
>>>
>>>     field = bit::extract(registervalue, 15, 0);      /* Extract <15:0> and zero-extend */
>>>     field1 = bit::extracts((int64_t)registervalue, 20, 16);   /* Extract and sign-extend */
>>>
>>>     registervalue = bit::insert(registervalue, 0xff, 16, 4); /* Set bits<19:16> == 0xff */
>>
>> Ahh, rather like using an elephant gun to shoot a field mouse.
>
> The compiler generates optimal code[*].

Perhaps some compilers do, but it's more likely that fast code
will result from a purely functional expression that computes
the desired result directly.  Not that code quality had anything to
do with my earlier comments.

> The source is descriptive and far more readable (and less subject
> to error) than manual bit shifting/masking.

That's funny.  Reminds me of things I used to hear 50 years ago when
people would say assembly language is easier to understand than the
high-level languages of the day.

> I don't see a problem.

To me it looks like you're confusing length and verbosity with
comprehensibility.

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


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

Back to top | Article view | comp.lang.c


csiph-web