Is there any way to get a non 8-bit multiple data type?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I understand that this is sort of bizarre question, but I have a few thoughts about and it made me interested.



example:
how can I get 31 bit data type or something?)



right now I think that the answer is a flat out NO, you cannot.
maybe I'm wrong?










share|improve this question




















  • 1





    You can always implement wrapping to whatever width manually. Do you have a specific high-level language in mind? Or assembly language? There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. en.wikipedia.org/wiki/36-bit On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.

    – Peter Cordes
    Nov 16 '18 at 12:29











  • @PeterCordes I have x86 architecture and C in mind, how can I implement this type of wrapping, could you please share some keys for google?

    – stronk_kisik
    Nov 16 '18 at 12:31








  • 1





    Like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive.

    – Peter Cordes
    Nov 16 '18 at 12:33











  • @PeterCordes hmm, no this is not exactly what I was thinking about. could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit. so for transfer from one location to another it will transfer it like 16bit + (16 bit with shift by one bit) or something?

    – stronk_kisik
    Nov 16 '18 at 12:35








  • 1





    No, you can't do that. x86 has byte-addressable memory, not bit-addressable. There are machines with word-addressable memory, but none I've ever heard of with bit-addressable memory where you could just do a 16-bit load or store that wasn't aligned to byte boundaries. C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.

    – Peter Cordes
    Nov 16 '18 at 12:43




















0















I understand that this is sort of bizarre question, but I have a few thoughts about and it made me interested.



example:
how can I get 31 bit data type or something?)



right now I think that the answer is a flat out NO, you cannot.
maybe I'm wrong?










share|improve this question




















  • 1





    You can always implement wrapping to whatever width manually. Do you have a specific high-level language in mind? Or assembly language? There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. en.wikipedia.org/wiki/36-bit On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.

    – Peter Cordes
    Nov 16 '18 at 12:29











  • @PeterCordes I have x86 architecture and C in mind, how can I implement this type of wrapping, could you please share some keys for google?

    – stronk_kisik
    Nov 16 '18 at 12:31








  • 1





    Like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive.

    – Peter Cordes
    Nov 16 '18 at 12:33











  • @PeterCordes hmm, no this is not exactly what I was thinking about. could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit. so for transfer from one location to another it will transfer it like 16bit + (16 bit with shift by one bit) or something?

    – stronk_kisik
    Nov 16 '18 at 12:35








  • 1





    No, you can't do that. x86 has byte-addressable memory, not bit-addressable. There are machines with word-addressable memory, but none I've ever heard of with bit-addressable memory where you could just do a 16-bit load or store that wasn't aligned to byte boundaries. C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.

    – Peter Cordes
    Nov 16 '18 at 12:43
















0












0








0








I understand that this is sort of bizarre question, but I have a few thoughts about and it made me interested.



example:
how can I get 31 bit data type or something?)



right now I think that the answer is a flat out NO, you cannot.
maybe I'm wrong?










share|improve this question
















I understand that this is sort of bizarre question, but I have a few thoughts about and it made me interested.



example:
how can I get 31 bit data type or something?)



right now I think that the answer is a flat out NO, you cannot.
maybe I'm wrong?







assembly memory types cpu-architecture low-level






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 15:01









Peter Cordes

134k18203342




134k18203342










asked Nov 16 '18 at 11:46









stronk_kisikstronk_kisik

296




296








  • 1





    You can always implement wrapping to whatever width manually. Do you have a specific high-level language in mind? Or assembly language? There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. en.wikipedia.org/wiki/36-bit On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.

    – Peter Cordes
    Nov 16 '18 at 12:29











  • @PeterCordes I have x86 architecture and C in mind, how can I implement this type of wrapping, could you please share some keys for google?

    – stronk_kisik
    Nov 16 '18 at 12:31








  • 1





    Like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive.

    – Peter Cordes
    Nov 16 '18 at 12:33











  • @PeterCordes hmm, no this is not exactly what I was thinking about. could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit. so for transfer from one location to another it will transfer it like 16bit + (16 bit with shift by one bit) or something?

    – stronk_kisik
    Nov 16 '18 at 12:35








  • 1





    No, you can't do that. x86 has byte-addressable memory, not bit-addressable. There are machines with word-addressable memory, but none I've ever heard of with bit-addressable memory where you could just do a 16-bit load or store that wasn't aligned to byte boundaries. C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.

    – Peter Cordes
    Nov 16 '18 at 12:43
















  • 1





    You can always implement wrapping to whatever width manually. Do you have a specific high-level language in mind? Or assembly language? There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. en.wikipedia.org/wiki/36-bit On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.

    – Peter Cordes
    Nov 16 '18 at 12:29











  • @PeterCordes I have x86 architecture and C in mind, how can I implement this type of wrapping, could you please share some keys for google?

    – stronk_kisik
    Nov 16 '18 at 12:31








  • 1





    Like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive.

    – Peter Cordes
    Nov 16 '18 at 12:33











  • @PeterCordes hmm, no this is not exactly what I was thinking about. could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit. so for transfer from one location to another it will transfer it like 16bit + (16 bit with shift by one bit) or something?

    – stronk_kisik
    Nov 16 '18 at 12:35








  • 1





    No, you can't do that. x86 has byte-addressable memory, not bit-addressable. There are machines with word-addressable memory, but none I've ever heard of with bit-addressable memory where you could just do a 16-bit load or store that wasn't aligned to byte boundaries. C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.

    – Peter Cordes
    Nov 16 '18 at 12:43










1




1





You can always implement wrapping to whatever width manually. Do you have a specific high-level language in mind? Or assembly language? There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. en.wikipedia.org/wiki/36-bit On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.

– Peter Cordes
Nov 16 '18 at 12:29





You can always implement wrapping to whatever width manually. Do you have a specific high-level language in mind? Or assembly language? There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. en.wikipedia.org/wiki/36-bit On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.

– Peter Cordes
Nov 16 '18 at 12:29













@PeterCordes I have x86 architecture and C in mind, how can I implement this type of wrapping, could you please share some keys for google?

– stronk_kisik
Nov 16 '18 at 12:31







@PeterCordes I have x86 architecture and C in mind, how can I implement this type of wrapping, could you please share some keys for google?

– stronk_kisik
Nov 16 '18 at 12:31






1




1





Like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive.

– Peter Cordes
Nov 16 '18 at 12:33





Like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive.

– Peter Cordes
Nov 16 '18 at 12:33













@PeterCordes hmm, no this is not exactly what I was thinking about. could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit. so for transfer from one location to another it will transfer it like 16bit + (16 bit with shift by one bit) or something?

– stronk_kisik
Nov 16 '18 at 12:35







@PeterCordes hmm, no this is not exactly what I was thinking about. could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit. so for transfer from one location to another it will transfer it like 16bit + (16 bit with shift by one bit) or something?

– stronk_kisik
Nov 16 '18 at 12:35






1




1





No, you can't do that. x86 has byte-addressable memory, not bit-addressable. There are machines with word-addressable memory, but none I've ever heard of with bit-addressable memory where you could just do a 16-bit load or store that wasn't aligned to byte boundaries. C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.

– Peter Cordes
Nov 16 '18 at 12:43







No, you can't do that. x86 has byte-addressable memory, not bit-addressable. There are machines with word-addressable memory, but none I've ever heard of with bit-addressable memory where you could just do a 16-bit load or store that wasn't aligned to byte boundaries. C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.

– Peter Cordes
Nov 16 '18 at 12:43














1 Answer
1






active

oldest

votes


















3














You can always implement wrapping to whatever width manually, like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive, typically left-shift then arithmetic right shift unless the source width is supported specially by the language and/or hardware. (e.g. ARM has a signed-bitfield-extend instruction that can extract and sign-extend an arbitrary bitfield into a full integer register).



There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. https://en.wikipedia.org/wiki/36-bit. On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.




could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit.




No, you can't do that. There are no CPUs I'm aware of with bit-addressable memory. Any load/store has to be aligned to at least byte boundaries. (Byte-addressable memory is nearly universal these days, but some DSPs and some older CPUs like DEC Alpha only have/had word-addressable memory).



C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.



e.g.



struct i31 {
int i:31; // note *signed* int
// 1 bit of padding is implicit on targets with 32-bit int
};

struct i31 inc(struct i31 x) {
x.i++;
return x;
}

int extend_to_int(struct i31 x) {
return x.i;
}


compiles for x86-64 to this (on the Godbolt compiler explorer).



I should probably have used gcc -fwrapv to define the behaviour of signed overflow as 2's complement wraparound. I'm not sure what the C rules are for bitfields, whether assignment of a signed result to a signed bitfield still triggers signed overflow undefined-behaviour in ISO C and C++.



# gcc8.2 -O3
inc(i31):
lea eax, [rdi+1]
and edi, -2147483648 # keep the top bit of the input
and eax, 2147483647 # keep the low 31 bits of i++
or eax, edi # merge.
# IDK why it can't / doesn't just leave the carry-out in the padding
ret
extend_to_int(i31):
lea eax, [rdi+rdi] # left shift by 1 (and copy)
sar eax # shift arithmetic right (by 1)
ret


But ARM is neat and has better bitfield instructions than x86. (Nearly everything has better bitfield instructions than x86).



# ARM gcc7.2 -march=armv8-a -O3
inc(i31):
add r3, r0, #1
bfi r0, r3, #0, #31 # bitfield insert to preserve the high bit of the struct
bx lr
extend_to_int(i31):
sbfx r0, r0, #0, #31 # signed bitfield extract
bx lr





share|improve this answer


























  • Wow, this is awesome answer!

    – stronk_kisik
    Nov 16 '18 at 13:22






  • 1





    there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

    – phuclv
    Nov 16 '18 at 16:22











  • @phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

    – Peter Cordes
    Nov 16 '18 at 16:25






  • 1





    that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

    – phuclv
    Nov 16 '18 at 16:38












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337246%2fis-there-any-way-to-get-a-non-8-bit-multiple-data-type%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














You can always implement wrapping to whatever width manually, like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive, typically left-shift then arithmetic right shift unless the source width is supported specially by the language and/or hardware. (e.g. ARM has a signed-bitfield-extend instruction that can extract and sign-extend an arbitrary bitfield into a full integer register).



There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. https://en.wikipedia.org/wiki/36-bit. On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.




could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit.




No, you can't do that. There are no CPUs I'm aware of with bit-addressable memory. Any load/store has to be aligned to at least byte boundaries. (Byte-addressable memory is nearly universal these days, but some DSPs and some older CPUs like DEC Alpha only have/had word-addressable memory).



C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.



e.g.



struct i31 {
int i:31; // note *signed* int
// 1 bit of padding is implicit on targets with 32-bit int
};

struct i31 inc(struct i31 x) {
x.i++;
return x;
}

int extend_to_int(struct i31 x) {
return x.i;
}


compiles for x86-64 to this (on the Godbolt compiler explorer).



I should probably have used gcc -fwrapv to define the behaviour of signed overflow as 2's complement wraparound. I'm not sure what the C rules are for bitfields, whether assignment of a signed result to a signed bitfield still triggers signed overflow undefined-behaviour in ISO C and C++.



# gcc8.2 -O3
inc(i31):
lea eax, [rdi+1]
and edi, -2147483648 # keep the top bit of the input
and eax, 2147483647 # keep the low 31 bits of i++
or eax, edi # merge.
# IDK why it can't / doesn't just leave the carry-out in the padding
ret
extend_to_int(i31):
lea eax, [rdi+rdi] # left shift by 1 (and copy)
sar eax # shift arithmetic right (by 1)
ret


But ARM is neat and has better bitfield instructions than x86. (Nearly everything has better bitfield instructions than x86).



# ARM gcc7.2 -march=armv8-a -O3
inc(i31):
add r3, r0, #1
bfi r0, r3, #0, #31 # bitfield insert to preserve the high bit of the struct
bx lr
extend_to_int(i31):
sbfx r0, r0, #0, #31 # signed bitfield extract
bx lr





share|improve this answer


























  • Wow, this is awesome answer!

    – stronk_kisik
    Nov 16 '18 at 13:22






  • 1





    there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

    – phuclv
    Nov 16 '18 at 16:22











  • @phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

    – Peter Cordes
    Nov 16 '18 at 16:25






  • 1





    that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

    – phuclv
    Nov 16 '18 at 16:38
















3














You can always implement wrapping to whatever width manually, like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive, typically left-shift then arithmetic right shift unless the source width is supported specially by the language and/or hardware. (e.g. ARM has a signed-bitfield-extend instruction that can extract and sign-extend an arbitrary bitfield into a full integer register).



There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. https://en.wikipedia.org/wiki/36-bit. On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.




could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit.




No, you can't do that. There are no CPUs I'm aware of with bit-addressable memory. Any load/store has to be aligned to at least byte boundaries. (Byte-addressable memory is nearly universal these days, but some DSPs and some older CPUs like DEC Alpha only have/had word-addressable memory).



C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.



e.g.



struct i31 {
int i:31; // note *signed* int
// 1 bit of padding is implicit on targets with 32-bit int
};

struct i31 inc(struct i31 x) {
x.i++;
return x;
}

int extend_to_int(struct i31 x) {
return x.i;
}


compiles for x86-64 to this (on the Godbolt compiler explorer).



I should probably have used gcc -fwrapv to define the behaviour of signed overflow as 2's complement wraparound. I'm not sure what the C rules are for bitfields, whether assignment of a signed result to a signed bitfield still triggers signed overflow undefined-behaviour in ISO C and C++.



# gcc8.2 -O3
inc(i31):
lea eax, [rdi+1]
and edi, -2147483648 # keep the top bit of the input
and eax, 2147483647 # keep the low 31 bits of i++
or eax, edi # merge.
# IDK why it can't / doesn't just leave the carry-out in the padding
ret
extend_to_int(i31):
lea eax, [rdi+rdi] # left shift by 1 (and copy)
sar eax # shift arithmetic right (by 1)
ret


But ARM is neat and has better bitfield instructions than x86. (Nearly everything has better bitfield instructions than x86).



# ARM gcc7.2 -march=armv8-a -O3
inc(i31):
add r3, r0, #1
bfi r0, r3, #0, #31 # bitfield insert to preserve the high bit of the struct
bx lr
extend_to_int(i31):
sbfx r0, r0, #0, #31 # signed bitfield extract
bx lr





share|improve this answer


























  • Wow, this is awesome answer!

    – stronk_kisik
    Nov 16 '18 at 13:22






  • 1





    there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

    – phuclv
    Nov 16 '18 at 16:22











  • @phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

    – Peter Cordes
    Nov 16 '18 at 16:25






  • 1





    that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

    – phuclv
    Nov 16 '18 at 16:38














3












3








3







You can always implement wrapping to whatever width manually, like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive, typically left-shift then arithmetic right shift unless the source width is supported specially by the language and/or hardware. (e.g. ARM has a signed-bitfield-extend instruction that can extract and sign-extend an arbitrary bitfield into a full integer register).



There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. https://en.wikipedia.org/wiki/36-bit. On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.




could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit.




No, you can't do that. There are no CPUs I'm aware of with bit-addressable memory. Any load/store has to be aligned to at least byte boundaries. (Byte-addressable memory is nearly universal these days, but some DSPs and some older CPUs like DEC Alpha only have/had word-addressable memory).



C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.



e.g.



struct i31 {
int i:31; // note *signed* int
// 1 bit of padding is implicit on targets with 32-bit int
};

struct i31 inc(struct i31 x) {
x.i++;
return x;
}

int extend_to_int(struct i31 x) {
return x.i;
}


compiles for x86-64 to this (on the Godbolt compiler explorer).



I should probably have used gcc -fwrapv to define the behaviour of signed overflow as 2's complement wraparound. I'm not sure what the C rules are for bitfields, whether assignment of a signed result to a signed bitfield still triggers signed overflow undefined-behaviour in ISO C and C++.



# gcc8.2 -O3
inc(i31):
lea eax, [rdi+1]
and edi, -2147483648 # keep the top bit of the input
and eax, 2147483647 # keep the low 31 bits of i++
or eax, edi # merge.
# IDK why it can't / doesn't just leave the carry-out in the padding
ret
extend_to_int(i31):
lea eax, [rdi+rdi] # left shift by 1 (and copy)
sar eax # shift arithmetic right (by 1)
ret


But ARM is neat and has better bitfield instructions than x86. (Nearly everything has better bitfield instructions than x86).



# ARM gcc7.2 -march=armv8-a -O3
inc(i31):
add r3, r0, #1
bfi r0, r3, #0, #31 # bitfield insert to preserve the high bit of the struct
bx lr
extend_to_int(i31):
sbfx r0, r0, #0, #31 # signed bitfield extract
bx lr





share|improve this answer















You can always implement wrapping to whatever width manually, like a++; a&=0x7fffffff; to mask the result to 31 bits and implement an unsigned 31-bit type. Redoing sign-extension to a wider type is more expensive, typically left-shift then arithmetic right shift unless the source width is supported specially by the language and/or hardware. (e.g. ARM has a signed-bitfield-extend instruction that can extract and sign-extend an arbitrary bitfield into a full integer register).



There are CPUs with words and/or bytes that aren't multiples of 8 bits, e.g. PDP-10 has 36-bit words. https://en.wikipedia.org/wiki/36-bit. On that system, the natural size is 36 bits, and 32 bits would be a non-standard type that requires extra instructions.




could I have some kind of data structures that will be store in memory like 31 bit -> 31 bit -> 31 bit and can I made CPU work with them as 31 bit.




No, you can't do that. There are no CPUs I'm aware of with bit-addressable memory. Any load/store has to be aligned to at least byte boundaries. (Byte-addressable memory is nearly universal these days, but some DSPs and some older CPUs like DEC Alpha only have/had word-addressable memory).



C with bitfields will emulate narrower types but with padding; you can't avoid having the compiler-generated asm touch the padding.



e.g.



struct i31 {
int i:31; // note *signed* int
// 1 bit of padding is implicit on targets with 32-bit int
};

struct i31 inc(struct i31 x) {
x.i++;
return x;
}

int extend_to_int(struct i31 x) {
return x.i;
}


compiles for x86-64 to this (on the Godbolt compiler explorer).



I should probably have used gcc -fwrapv to define the behaviour of signed overflow as 2's complement wraparound. I'm not sure what the C rules are for bitfields, whether assignment of a signed result to a signed bitfield still triggers signed overflow undefined-behaviour in ISO C and C++.



# gcc8.2 -O3
inc(i31):
lea eax, [rdi+1]
and edi, -2147483648 # keep the top bit of the input
and eax, 2147483647 # keep the low 31 bits of i++
or eax, edi # merge.
# IDK why it can't / doesn't just leave the carry-out in the padding
ret
extend_to_int(i31):
lea eax, [rdi+rdi] # left shift by 1 (and copy)
sar eax # shift arithmetic right (by 1)
ret


But ARM is neat and has better bitfield instructions than x86. (Nearly everything has better bitfield instructions than x86).



# ARM gcc7.2 -march=armv8-a -O3
inc(i31):
add r3, r0, #1
bfi r0, r3, #0, #31 # bitfield insert to preserve the high bit of the struct
bx lr
extend_to_int(i31):
sbfx r0, r0, #0, #31 # signed bitfield extract
bx lr






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 16 '18 at 13:32

























answered Nov 16 '18 at 13:19









Peter CordesPeter Cordes

134k18203342




134k18203342













  • Wow, this is awesome answer!

    – stronk_kisik
    Nov 16 '18 at 13:22






  • 1





    there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

    – phuclv
    Nov 16 '18 at 16:22











  • @phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

    – Peter Cordes
    Nov 16 '18 at 16:25






  • 1





    that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

    – phuclv
    Nov 16 '18 at 16:38



















  • Wow, this is awesome answer!

    – stronk_kisik
    Nov 16 '18 at 13:22






  • 1





    there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

    – phuclv
    Nov 16 '18 at 16:22











  • @phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

    – Peter Cordes
    Nov 16 '18 at 16:25






  • 1





    that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

    – phuclv
    Nov 16 '18 at 16:38

















Wow, this is awesome answer!

– stronk_kisik
Nov 16 '18 at 13:22





Wow, this is awesome answer!

– stronk_kisik
Nov 16 '18 at 13:22




1




1





there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

– phuclv
Nov 16 '18 at 16:22





there are many microcontrollers with bit-addressable memory. For example Intel 8051 has a special 128-bit region that are bit-addressable

– phuclv
Nov 16 '18 at 16:22













@phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

– Peter Cordes
Nov 16 '18 at 16:25





@phuclv: and you can do byte or word loads from it? Not just single-element bitfield stuff?

– Peter Cordes
Nov 16 '18 at 16:25




1




1





that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

– phuclv
Nov 16 '18 at 16:38





that 128-bit region is a subset of the address space, so you can still load a byte from it like normal. 8051 is an 8-bit MCU so it can't load any types wider than that

– phuclv
Nov 16 '18 at 16:38




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337246%2fis-there-any-way-to-get-a-non-8-bit-multiple-data-type%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Lugert, Oklahoma