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.
2 namespace Svc {
3 
4 template <typename T>
6  static_assert(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "size must be 1, 2, 4, 8");
7  FW_ASSERT(this->size >= sizeof(T), static_cast<FwAssertArgType>(this->size),
8  static_cast<FwAssertArgType>(sizeof(T)));
9  // first make a byte array which can definitely store our val
10  U8 valBytes[8] = {0};
11  // now move top of stack into byte array and shrink stack
12  memcpy(valBytes, this->top() - sizeof(T), sizeof(T));
13  this->size -= static_cast<Fpy::StackSizeType>(sizeof(T));
14 
15  // now do appropriate byteswap on byte array
16  if (sizeof(T) == 8) {
17  return static_cast<T>((static_cast<T>(valBytes[7]) << 0) | (static_cast<T>(valBytes[6]) << 8) |
18  (static_cast<T>(valBytes[5]) << 16) | (static_cast<T>(valBytes[4]) << 24) |
19  (static_cast<T>(valBytes[3]) << 32) | (static_cast<T>(valBytes[2]) << 40) |
20  (static_cast<T>(valBytes[1]) << 48) | (static_cast<T>(valBytes[0]) << 56));
21  } else if (sizeof(T) == 4) {
22  return static_cast<T>((static_cast<T>(valBytes[3]) << 0) | (static_cast<T>(valBytes[2]) << 8) |
23  (static_cast<T>(valBytes[1]) << 16) | (static_cast<T>(valBytes[0]) << 24));
24  } else if (sizeof(T) == 2) {
25  return static_cast<T>((static_cast<T>(valBytes[1]) << 0) | (static_cast<T>(valBytes[0]) << 8));
26  } else {
27  return static_cast<T>(valBytes[0]);
28  }
29 }
30 
31 template U8 FpySequencer::Stack::pop();
32 template U16 FpySequencer::Stack::pop();
33 template U32 FpySequencer::Stack::pop();
34 template U64 FpySequencer::Stack::pop();
35 template I8 FpySequencer::Stack::pop();
36 template I16 FpySequencer::Stack::pop();
37 template I32 FpySequencer::Stack::pop();
38 template I64 FpySequencer::Stack::pop();
39 
40 template <>
41 F32 FpySequencer::Stack::pop<F32>() {
42  U32 endianness = this->pop<U32>();
43  F32 val;
44  memcpy(&val, &endianness, sizeof(val));
45  return val;
46 }
47 
48 template <>
49 F64 FpySequencer::Stack::pop<F64>() {
50  U64 endianness = this->pop<U64>();
51  F64 val;
52  memcpy(&val, &endianness, sizeof(val));
53  return val;
54 }
55 
56 template <typename T>
58  static_assert(sizeof(T) == 8 || sizeof(T) == 4 || sizeof(T) == 2 || sizeof(T) == 1, "size must be 1, 2, 4, 8");
59  FW_ASSERT(this->size + sizeof(val) < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->size),
60  static_cast<FwAssertArgType>(sizeof(T)));
61  // first make a byte array which can definitely store our val
62  U8 valBytes[8] = {0};
63  // convert val to unsigned to avoid undefined behavior for bitshifts of signed types
64  using UnsignedT = typename std::make_unsigned<T>::type;
65  UnsignedT valUnsigned = static_cast<UnsignedT>(val);
66  if (sizeof(T) == 8) {
67  valBytes[0] = static_cast<U8>(valUnsigned >> 56);
68  valBytes[1] = static_cast<U8>(valUnsigned >> 48);
69  valBytes[2] = static_cast<U8>(valUnsigned >> 40);
70  valBytes[3] = static_cast<U8>(valUnsigned >> 32);
71  valBytes[4] = static_cast<U8>(valUnsigned >> 24);
72  valBytes[5] = static_cast<U8>(valUnsigned >> 16);
73  valBytes[6] = static_cast<U8>(valUnsigned >> 8);
74  valBytes[7] = static_cast<U8>(valUnsigned >> 0);
75  } else if (sizeof(T) == 4) {
76  valBytes[0] = static_cast<U8>(valUnsigned >> 24);
77  valBytes[1] = static_cast<U8>(valUnsigned >> 16);
78  valBytes[2] = static_cast<U8>(valUnsigned >> 8);
79  valBytes[3] = static_cast<U8>(valUnsigned >> 0);
80  } else if (sizeof(T) == 2) {
81  valBytes[0] = static_cast<U8>(valUnsigned >> 8);
82  valBytes[1] = static_cast<U8>(valUnsigned >> 0);
83  } else {
84  valBytes[0] = static_cast<U8>(valUnsigned);
85  }
86  memcpy(this->top(), valBytes, sizeof(T));
87  this->size += static_cast<Fpy::StackSizeType>(sizeof(T));
88 }
89 
90 template void FpySequencer::Stack::push(U8);
91 template void FpySequencer::Stack::push(U16);
92 template void FpySequencer::Stack::push(U32);
93 template void FpySequencer::Stack::push(U64);
94 template void FpySequencer::Stack::push(I8);
95 template void FpySequencer::Stack::push(I16);
96 template void FpySequencer::Stack::push(I32);
97 template void FpySequencer::Stack::push(I64);
98 
99 template <>
100 void FpySequencer::Stack::push<F32>(F32 val) {
101  U32 endianness;
102  memcpy(&endianness, &val, sizeof(val));
103  this->push(endianness);
104 }
105 
106 template <>
107 void FpySequencer::Stack::push<F64>(F64 val) {
108  U64 endianness;
109  memcpy(&endianness, &val, sizeof(val));
110  this->push(endianness);
111 }
112 
113 // pops a byte array from the top of the stack into the destination array
114 // does not convert endianness
116  FW_ASSERT(this->size >= destSize, static_cast<FwAssertArgType>(this->size), static_cast<FwAssertArgType>(destSize));
117  memcpy(dest, this->top() - destSize, destSize);
118  this->size -= destSize;
119 }
120 
121 // pushes a byte array to the top of the stack from the source array
122 // leaves the source array unmodified
123 // does not convert endianness
125  FW_ASSERT(this->size + srcSize < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->size),
126  static_cast<FwAssertArgType>(srcSize));
127  memcpy(this->top(), src, srcSize);
128  this->size += srcSize;
129 }
130 
131 // pushes zero bytes to the stack
133  FW_ASSERT(this->size + byteCount < Fpy::MAX_STACK_SIZE, static_cast<FwAssertArgType>(this->size),
134  static_cast<FwAssertArgType>(byteCount));
135  memset(this->top(), 0, byteCount);
136  this->size += byteCount;
137 }
138 
140  return &this->bytes[this->size];
141 }
142 
144  return this->bytes + this->lvarOffset();
145 }
146 
148  // at the moment, because we only have one stack frame,
149  // lvars always start at 0
150  return 0;
151 }
152 
153 } // 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