fxos/lib/semantics.cpp

94 lines
2.3 KiB
C++

#include <fxos/semantics.h>
namespace FxOS {
DataValue::DataValue():
type(nullptr), determined(false)
{
}
uint32_t DataValue::read(int offset, int size)
{
if(offset < 0 || size < 0 || (type->size && offset+size >= type->size))
throw std::logic_error("Invalid read into simulated data");
if(!size || size & (size - 1))
throw std::logic_error("Simulated read not a power of 2");
if(type->kind==DataType::Integral || type->kind==DataType::BitField)
{
int shift = (4 - size - offset) << 3;
uint32_t u = uinteger >> shift;
return (size == 4) ? u :
(size == 2) ? (uint16_t)u :
(uint8_t)u;
}
else if(type->kind == DataType::Array)
{
int elsize = type->arraytype->size;
int index = offset / elsize;
if(index >= (int)entries.size())
throw std::logic_error("Read out of array bounds");
/* Will throw if reading from two entries simultaneously */
return entries[index].read(offset % elsize, size);
}
else if(type->kind == DataType::Array)
{
int index = 0;
while(offset >= type->attributes[index].size)
{
index++;
offset -= type->attributes[index].size;
}
return entries[index].read(offset, size);
}
throw std::logic_error("Read into unknown DataValue kind");
}
void DataValue::write(int offset, int size, uint32_t contents)
{
if(offset < 0 || size < 0 || (type->size && offset+size >= type->size))
throw std::logic_error("Invalid write into simulated data");
if(!size || size & (size - 1))
throw std::logic_error("Simulated write not a power of 2");
if(type->kind==DataType::Integral || type->kind==DataType::BitField)
{
uint32_t mask = (size == 1) ? 0xff :
(size == 2) ? 0xffff :
0xffffffff;
int shift = (4 - size - offset) << 3;
uinteger = (uinteger & ~(mask << shift)) | (contents << shift);
}
else if(type->kind == DataType::Array)
{
int elsize = type->arraytype->size;
int index = offset / elsize;
if(index >= (int)entries.size())
throw std::logic_error("Write out of array bounds");
entries[index].write(offset % elsize, size, contents);
}
else if(type->kind == DataType::Array)
{
int index = 0;
while(offset >= type->attributes[index].size)
{
index++;
offset -= type->attributes[index].size;
}
entries[index].write(offset, size, contents);
}
throw std::logic_error("Write into unknown DataValue kind");
}
} /* namespace FxOS */