Fixed bugs in base.c

In particular, __LITTLE_ENDIAN__ was not a functioning macro.
Instead, I implemented a version by hand (copied from IBM) that
actually figures out if the machine is little endian or not.

Thank you unit testing!
This commit is contained in:
2024-04-28 17:37:18 +05:30
parent cf6aa96539
commit cce3259b56
2 changed files with 30 additions and 31 deletions

View File

@@ -28,61 +28,61 @@ union word_pun
hword_t hword_htobc(hword_t w) hword_t hword_htobc(hword_t w)
{ {
#if __LITTLE_ENDIAN__ if (LITTLE_ENDIAN)
return w; return w;
#else
union hword_pun x = {w}; union hword_pun x = {w};
union hword_pun y = {0}; union hword_pun y = {0};
for (size_t i = 0, j = HWORD_SIZE; i < HWORD_SIZE; ++i, --j) for (size_t i = 0, j = HWORD_SIZE; i < HWORD_SIZE; ++i, --j)
y.bytes[j - 1] = x.bytes[i]; y.bytes[j - 1] = x.bytes[i];
return y.h; return y.h;
#endif
} }
hword_t hword_bctoh(hword_t w) hword_t hword_bctoh(hword_t w)
{ {
#if __LITTLE_ENDIAN__ if (LITTLE_ENDIAN)
return w; return w;
#else
union hword_pun x = {w}; union hword_pun x = {w};
union hword_pun y = {0}; union hword_pun y = {0};
for (size_t i = 0, j = HWORD_SIZE; i < HWORD_SIZE; ++i, --j) for (size_t i = 0, j = HWORD_SIZE; i < HWORD_SIZE; ++i, --j)
y.bytes[j - 1] = x.bytes[i]; y.bytes[j - 1] = x.bytes[i];
return y.h; return y.h;
#endif
} }
word_t word_htobc(word_t w) word_t word_htobc(word_t w)
{ {
#if __LITTLE_ENDIAN__ if (LITTLE_ENDIAN)
return w; return w;
#else
union word_pun x = {w}; union word_pun x = {w};
union word_pun y = {0}; union word_pun y = {0};
for (size_t i = 0, j = WORD_SIZE; i < WORD_SIZE; ++i, --j) for (size_t i = 0, j = WORD_SIZE; i < WORD_SIZE; ++i, --j)
y.bytes[j - 1] = x.bytes[i]; y.bytes[j - 1] = x.bytes[i];
return y.h; return y.h;
#endif
} }
word_t word_bctoh(word_t w) word_t word_bctoh(word_t w)
{ {
#if __LITTLE_ENDIAN__ if (LITTLE_ENDIAN)
return w; return w;
#else
union word_pun x = {w}; union word_pun x = {w};
union word_pun y = {0}; union word_pun y = {0};
for (size_t i = 0, j = WORD_SIZE; i < WORD_SIZE; ++i, --j) for (size_t i = 0, j = WORD_SIZE; i < WORD_SIZE; ++i, --j)
y.bytes[j - 1] = x.bytes[i]; y.bytes[j - 1] = x.bytes[i];
return y.h; return y.h;
#endif
} }
hword_t convert_bytes_to_hword(byte_t *bytes) hword_t convert_bytes_to_hword(byte_t *bytes)
{ {
hword_t be_h = 0; hword_t h = 0;
memcpy(&be_h, bytes, HWORD_SIZE); for (size_t i = 0; i < HWORD_SIZE; ++i)
hword_t h = hword_bctoh(be_h); h |= ((hword_t)(bytes[i]) << (8 * i));
return h;
}
word_t convert_bytes_to_word(byte_t *bytes)
{
word_t h = 0;
for (size_t i = 0; i < WORD_SIZE; ++i)
h |= ((word_t)(bytes[i]) << (8 * i));
return h; return h;
} }
@@ -97,11 +97,3 @@ void convert_word_to_bytes(word_t w, byte_t *bytes)
word_t be_w = word_htobc(w); word_t be_w = word_htobc(w);
memcpy(bytes, &be_w, WORD_SIZE); memcpy(bytes, &be_w, WORD_SIZE);
} }
word_t convert_bytes_to_word(byte_t *bytes)
{
word_t be_w = 0;
memcpy(&be_w, bytes, WORD_SIZE);
word_t w = word_bctoh(be_w);
return w;
}

View File

@@ -97,6 +97,12 @@ typedef enum
#define DHWORD(HWORD) ((data_t){.as_hword = (HWORD)}) #define DHWORD(HWORD) ((data_t){.as_hword = (HWORD)})
#define DWORD(WORD) ((data_t){.as_word = (WORD)}) #define DWORD(WORD) ((data_t){.as_word = (WORD)})
// Macro to determine little endian
#ifndef LITTLE_ENDIAN
static const int __i = 1;
#define LITTLE_ENDIAN ((*((byte_t *)&__i)) == 0)
#endif
/** /**
@brief Safely subtract SUB from W, where both are words (64 bit integers). @brief Safely subtract SUB from W, where both are words (64 bit integers).
@@ -124,8 +130,8 @@ typedef enum
@brief Convert a buffer of bytes to a half word. @brief Convert a buffer of bytes to a half word.
@details We assume the buffer of bytes are in virtual machine byte @details We assume the buffer of bytes are in virtual machine byte
code format (big endian) and that they are at least HWORD_SIZE in code format (little endian) and that they are at least HWORD_SIZE
size. in size.
*/ */
hword_t convert_bytes_to_hword(byte_t *buffer); hword_t convert_bytes_to_hword(byte_t *buffer);
@@ -143,13 +149,14 @@ void convert_hword_to_bytes(hword_t h, byte_t *buffer);
@brief Convert a buffer of bytes to a word. @brief Convert a buffer of bytes to a word.
@details We assume the buffer of bytes are in virtual machine byte @details We assume the buffer of bytes are in virtual machine byte
code format (big endian) and that they are at least WORD_SIZE in code format (little endian) and that they are at least WORD_SIZE in
size. size.
*/ */
word_t convert_bytes_to_word(byte_t *); word_t convert_bytes_to_word(byte_t *);
/** /**
@brief Convert a word into a VM byte code format bytes (big endian) @brief Convert a word into a VM byte code format bytes (little
endian)
@param w: Word to convert @param w: Word to convert