F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
FpySequencerStack.cpp
Go to the documentation of this file.
1 #include <cstring>
3 namespace Svc {
4 
5 template <typename T>
7  static_assert(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "size must be 1, 2, 4, 8");
8  FW_ASSERT(this->size >= sizeof(T), static_cast<FwAssertArgType>(this->size),
9  static_cast<FwAssertArgType>(sizeof(T)));
10  // first make a byte array which can definitely store our val
11  U8 valBytes[8] = {0};
12  // now move top of stack into byte array and shrink stack
13  memcpy(valBytes, this->top() - sizeof(T), sizeof(T));
14  this->size -= static_cast<Fpy::StackSizeType>(sizeof(T));
15 
16  // now do appropriate byteswap on byte array
17  if (sizeof(T) == 8) {
18  return static_cast<T>((static_cast<T>(valBytes[7]) << 0) | (static_cast<T>(valBytes[6]) << 8) |
19  (static_cast<T>(valBytes[5]) << 16) | (static_cast<T>(valBytes[4]) << 24) |
20  (static_cast<T>(valBytes[3]) << 32) | (static_cast<T>(valBytes[2]) << 40) |
21  (static_cast<T>(valBytes[1]) << 48) | (static_cast<T>(valBytes[0]) << 56));
22  } else if (sizeof(T) == 4) {
23  return static_cast<T>((static_cast<T>(valBytes[3]) << 0) | (static_cast<T>(valBytes[2]) << 8) |
24  (static_cast<T>(valBytes[1]) << 16) | (static_cast<T>(valBytes[0]) << 24));
25  } else if (sizeof(T) == 2) {
26  return static_cast<T>((static_cast<T>(valBytes[1]) << 0) | (static_cast<T>(valBytes[0]) << 8));
27  } else {
28  return static_cast<T>(valBytes[0]);
29  }
30 }
31 
32 template U8 FpySequencer::Stack::pop();
33 template U16 FpySequencer::Stack::pop();
34 template U32 FpySequencer::Stack::pop();
35 template U64 FpySequencer::Stack::pop();
36 template I8 FpySequencer::Stack::pop();
37 template I16 FpySequencer::Stack::pop();
38 template I32 FpySequencer::Stack::pop();
39 template I64 FpySequencer::Stack::pop();
40 
41 template <>
42 F32 FpySequencer::Stack::pop<F32>() {
43  U32 endianness = this->pop<U32>();
44  F32 val;
45  memcpy(&val, &endianness, sizeof(val));
46  return val;
47 }
48 
49 template <>
50 F64 FpySequencer::Stack::pop<F64>() {
51  U64 endianness = this->pop<U64>();
52  F64 val;
53  memcpy(&val, &endianness, sizeof(val));
54  return val;
55 }
56 
57 template <typename T>
59  static_assert(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "size must be 1, 2, 4, 8");
60  FW_ASSERT(this->size + sizeof(val) < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->size),
61  static_cast<FwAssertArgType>(sizeof(T)));
62  // first make a byte array which can definitely store our val
63  U8 valBytes[8] = {0};
64  // convert val to unsigned to avoid undefined behavior for bitshifts of signed types
65  using UnsignedT = typename std::make_unsigned<T>::type;
66  UnsignedT valUnsigned = static_cast<UnsignedT>(val);
67  if (sizeof(T) == 8) {
68  valBytes[0] = static_cast<U8>(valUnsigned >> 56);
69  valBytes[1] = static_cast<U8>(valUnsigned >> 48);
70  valBytes[2] = static_cast<U8>(valUnsigned >> 40);
71  valBytes[3] = static_cast<U8>(valUnsigned >> 32);
72  valBytes[4] = static_cast<U8>(valUnsigned >> 24);
73  valBytes[5] = static_cast<U8>(valUnsigned >> 16);
74  valBytes[6] = static_cast<U8>(valUnsigned >> 8);
75  valBytes[7] = static_cast<U8>(valUnsigned >> 0);
76  } else if (sizeof(T) == 4) {
77  valBytes[0] = static_cast<U8>(valUnsigned >> 24);
78  valBytes[1] = static_cast<U8>(valUnsigned >> 16);
79  valBytes[2] = static_cast<U8>(valUnsigned >> 8);
80  valBytes[3] = static_cast<U8>(valUnsigned >> 0);
81  } else if (sizeof(T) == 2) {
82  valBytes[0] = static_cast<U8>(valUnsigned >> 8);
83  valBytes[1] = static_cast<U8>(valUnsigned >> 0);
84  } else {
85  valBytes[0] = static_cast<U8>(valUnsigned);
86  }
87  memcpy(this->top(), valBytes, sizeof(T));
88  this->size += static_cast<Fpy::StackSizeType>(sizeof(T));
89 }
90 
91 template void FpySequencer::Stack::push(U8);
92 template void FpySequencer::Stack::push(U16);
93 template void FpySequencer::Stack::push(U32);
94 template void FpySequencer::Stack::push(U64);
95 template void FpySequencer::Stack::push(I8);
96 template void FpySequencer::Stack::push(I16);
97 template void FpySequencer::Stack::push(I32);
98 template void FpySequencer::Stack::push(I64);
99 
100 template <>
101 void FpySequencer::Stack::push<F32>(F32 val) {
102  U32 endianness;
103  memcpy(&endianness, &val, sizeof(val));
104  this->push(endianness);
105 }
106 
107 template <>
108 void FpySequencer::Stack::push<F64>(F64 val) {
109  U64 endianness;
110  memcpy(&endianness, &val, sizeof(val));
111  this->push(endianness);
112 }
113 
114 // pops a byte array from the top of the stack into the destination array
115 // does not convert endianness
117  FW_ASSERT(this->size >= destSize, static_cast<FwAssertArgType>(this->size), static_cast<FwAssertArgType>(destSize));
118  memcpy(dest, this->top() - destSize, destSize);
119  this->size -= destSize;
120 }
121 
122 // pushes a byte array to the top of the stack from the source array
123 // leaves the source array unmodified
124 // does not convert endianness
126  FW_ASSERT(this->size + srcSize < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->size),
127  static_cast<FwAssertArgType>(srcSize));
128  memcpy(this->top(), src, srcSize);
129  this->size += srcSize;
130 }
131 
132 // pushes zero bytes to the stack
134  FW_ASSERT(this->size + byteCount < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->size),
135  static_cast<FwAssertArgType>(byteCount));
136  memset(this->top(), 0, byteCount);
137  this->size += byteCount;
138 }
139 
141  return &this->bytes[this->size];
142 }
143 
145  return this->bytes + this->lvarOffset();
146 }
147 
149  // at the moment, because we only have one stack frame,
150  // lvars always start at 0
151  return 0;
152 }
153 
154 } // namespace Svc
Fpy::StackSizeType lvarOffset()
int8_t I8
8-bit signed integer
Definition: BasicTypes.h:50
float F32
32-bit floating point
Definition: BasicTypes.h:83
void pushZeroes(Fpy::StackSizeType byteCount)
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
Fpy::StackSizeType size
double F64
64-bit floating point (double). Required for compiler-supplied double promotion.
Definition: BasicTypes.h:85
RateGroupDivider component implementation.
#define FW_ASSERT(...)
Definition: Assert.hpp:14
U32 StackSizeType
the type which everything referencing a size or offset on the stack is represented in ...
#define U64(C)
Definition: sha.h:181