mirror of
https://github.com/dbalsom/x86_microcode.git
synced 2026-06-16 13:07:07 +03:00
Initial 80386 microcode commit.
This commit is contained in:
@@ -0,0 +1,697 @@
|
||||
#include "alfe/main.h"
|
||||
|
||||
#ifndef INCLUDED_ARRAY_H
|
||||
#define INCLUDED_ARRAY_H
|
||||
|
||||
#include "alfe/bitwise.h"
|
||||
|
||||
// List is not quite a value type, since adding an element to a list will
|
||||
// affect copies of the list.
|
||||
template<class T> class List : private Handle
|
||||
{
|
||||
class Body : public Handle::Body
|
||||
{
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
template<typename... Args> Node(Args&&... args)
|
||||
: _value(std::forward<Args>(args)...), _next(0) { }
|
||||
Node* next() const { return _next; }
|
||||
void setNext(Node* next) { _next = next; }
|
||||
const T& value() const { return _value; }
|
||||
private:
|
||||
T _value;
|
||||
Node* _next;
|
||||
friend class Body;
|
||||
friend class List;
|
||||
};
|
||||
public:
|
||||
template<typename... Args> Body(Args&&... args)
|
||||
: _first(std::forward<Args>(args)...), _last(&_first), _count(1) { }
|
||||
~Body()
|
||||
{
|
||||
Node* n = _first.next();
|
||||
while (n != 0) {
|
||||
Node* nn = n->next();
|
||||
delete n;
|
||||
n = nn;
|
||||
}
|
||||
}
|
||||
template<typename... Args> T* add(Args&&... args)
|
||||
{
|
||||
_last->setNext(new Node(std::forward<Args>(args)...));
|
||||
_last = _last->next();
|
||||
++_count;
|
||||
return &_last->_value;
|
||||
}
|
||||
int count() const { return _count; }
|
||||
const Node* start() const { return &_first; }
|
||||
private:
|
||||
Node _first;
|
||||
Node* _last;
|
||||
int _count;
|
||||
|
||||
friend class List;
|
||||
friend class List::Iterator;
|
||||
};
|
||||
public:
|
||||
List() { }
|
||||
template<typename... Args> T* add(Args&&... args)
|
||||
{
|
||||
if (!valid()) {
|
||||
*this = List(create<Body>(std::forward<Args>(args)...));
|
||||
return &body()->_first._value;
|
||||
}
|
||||
return body()->add(std::forward<Args>(args)...);
|
||||
}
|
||||
int count() const
|
||||
{
|
||||
if (valid())
|
||||
return body()->count();
|
||||
return 0;
|
||||
}
|
||||
bool operator==(List other) const
|
||||
{
|
||||
Iterator l = begin();
|
||||
Iterator r = other.begin();
|
||||
while (l != end() && r != other.end()) {
|
||||
if (*l != *r)
|
||||
return false;
|
||||
++l;
|
||||
++r;
|
||||
}
|
||||
return l == end() && r == other.end();
|
||||
}
|
||||
private:
|
||||
List(const Handle& other) : Handle(other) { }
|
||||
Body* body() { return as<Body>(); }
|
||||
const Body* body() const { return as<Body>(); }
|
||||
public:
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
const T& operator*() const { return _node->value(); }
|
||||
const T* operator->() const { return &_node->value(); }
|
||||
const Iterator& operator++() { _node = _node->next(); return *this; }
|
||||
bool operator==(const Iterator& other) { return _node == other._node; }
|
||||
bool operator!=(const Iterator& other) { return !operator==(other); }
|
||||
bool end() const { return _node == 0; }
|
||||
private:
|
||||
const typename Body::Node* _node;
|
||||
|
||||
Iterator(const typename Body::Node* node) : _node(node) { }
|
||||
|
||||
friend class List;
|
||||
};
|
||||
Iterator begin() const
|
||||
{
|
||||
if (valid())
|
||||
return Iterator(body()->start());
|
||||
return end();
|
||||
}
|
||||
Iterator end() const { return Iterator(0); }
|
||||
};
|
||||
|
||||
template<class T> class Array;
|
||||
|
||||
template<class T, class Base = typename Array<T>::AppendableBaseBody>
|
||||
class AppendableArray;
|
||||
|
||||
// Array is not quite a value type, since changing an element in one array will
|
||||
// affect copies of the same array unless a deep copy is made with copy().
|
||||
template<class T> class Array : private Handle
|
||||
{
|
||||
public:
|
||||
// "allocate" is number of Ts to allocate space for.
|
||||
// "construct" is number of Ts to actually construct.
|
||||
template<class C = Handle, class H = Handle::Body> static
|
||||
C create(int allocate, int construct)
|
||||
{
|
||||
return create<C, H>(allocate, construct, 0);
|
||||
}
|
||||
template<class C = Handle, class H = Handle::Body, typename... Args> static
|
||||
C create(int allocate, int construct, int extraBytes, Args&&... args)
|
||||
{
|
||||
void* buffer = operator new(Body<H>::headSize() + allocate*sizeof(T) +
|
||||
extraBytes);
|
||||
Body<H>* b;
|
||||
try {
|
||||
b = new(buffer) Body<H>(std::forward<Args>(args)...);
|
||||
try {
|
||||
b->constructTail(construct);
|
||||
}
|
||||
catch (...) {
|
||||
b->destruct();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
operator delete(buffer);
|
||||
throw;
|
||||
}
|
||||
return C(b, false);
|
||||
}
|
||||
|
||||
// This class combines an H and an array of Ts in a single memory block.
|
||||
// Also known as the "struct hack". T must be default-constructable.
|
||||
template<class H = Handle::Body> class Body : public H
|
||||
{
|
||||
// HT is never actually used directly - it's just used to figure out
|
||||
// the length and the address of the first T.
|
||||
// class HT : public Body { public: T _t; };
|
||||
public:
|
||||
static int headSize() { return sizeof(HT<H>) - sizeof(T); }
|
||||
|
||||
T* pointer() { return &static_cast<HT<H>*>(this)->_t; }
|
||||
const T* pointer() const
|
||||
{
|
||||
return &static_cast<const HT<H>*>(this)->_t;
|
||||
}
|
||||
T& operator[](int i) { return pointer()[i]; }
|
||||
const T& operator[](int i) const { return pointer()[i]; }
|
||||
|
||||
void destroy() const
|
||||
{
|
||||
this->preDestroy();
|
||||
destruct();
|
||||
operator delete(const_cast<void*>(static_cast<const void*>(this)));
|
||||
}
|
||||
|
||||
int size() const { return _size; }
|
||||
// Be careful to avoid calling setSize() with a size argument greater
|
||||
// than the "allocate" size passed to create().
|
||||
void setSize(int size)
|
||||
{
|
||||
if (size > _size)
|
||||
constructTail(size);
|
||||
else
|
||||
destructTail(size);
|
||||
}
|
||||
|
||||
template<typename... Args> void constructT(Args&&... args)
|
||||
{
|
||||
new(static_cast<void*>(&(*this)[_size]))
|
||||
T(std::forward<Args>(args)...);
|
||||
++_size;
|
||||
}
|
||||
|
||||
class Iterator
|
||||
//: public std::iterator<std::random_access_iterator_tag, T>
|
||||
{
|
||||
public:
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = T;
|
||||
//typename std::iterator<std::random_access_iterator_tag, T>::
|
||||
//difference_type;
|
||||
|
||||
Iterator() : _p(0) { }
|
||||
T& operator[](difference_type n) const { return _p[n]; }
|
||||
T& operator*() const { return *_p; }
|
||||
T* operator->() { return _p; }
|
||||
const Iterator& operator++() { ++_p; return *this; }
|
||||
const Iterator& operator--() { --_p; return *this; }
|
||||
Iterator operator++(int) { Iterator r = *this; ++_p; return r; }
|
||||
Iterator operator--(int) { Iterator r = *this; --_p; return r; }
|
||||
const Iterator& operator+=(difference_type n) { _p += n; return *this; }
|
||||
const Iterator& operator-=(difference_type n) { _p -= n; return *this; }
|
||||
Iterator operator+(difference_type n) const
|
||||
{
|
||||
Iterator r = *this;
|
||||
r += n;
|
||||
return r;
|
||||
}
|
||||
Iterator operator-(difference_type n) const
|
||||
{
|
||||
Iterator r = *this;
|
||||
r -= n;
|
||||
return r;
|
||||
}
|
||||
friend inline Iterator operator+(difference_type n, const Iterator& a)
|
||||
{
|
||||
return a + n;
|
||||
}
|
||||
friend inline Iterator operator-(difference_type n, const Iterator& a)
|
||||
{
|
||||
return a - n;
|
||||
}
|
||||
bool operator==(const Iterator& other) const
|
||||
{
|
||||
return _p == other._p;
|
||||
}
|
||||
bool operator!=(const Iterator& other) const
|
||||
{
|
||||
return _p != other._p;
|
||||
}
|
||||
bool operator<(const Iterator& other) const
|
||||
{
|
||||
return _p < other._p;
|
||||
}
|
||||
bool operator>(const Iterator& other) const
|
||||
{
|
||||
return _p > other._p;
|
||||
}
|
||||
bool operator<=(const Iterator& other) const
|
||||
{
|
||||
return _p <= other._p;
|
||||
}
|
||||
bool operator>=(const Iterator& other) const
|
||||
{
|
||||
return _p >= other._p;
|
||||
}
|
||||
ptrdiff_t operator-(const Iterator& other) const
|
||||
{
|
||||
return _p - other._p;
|
||||
}
|
||||
private:
|
||||
T* _p;
|
||||
Iterator(T* p) : _p(p) { }
|
||||
friend class Body;
|
||||
};
|
||||
|
||||
class ConstIterator
|
||||
//: public std::iterator<std::random_access_iterator_tag, T>
|
||||
{
|
||||
using difference_type = ptrdiff_t;
|
||||
using value_type = T;
|
||||
//typename std::iterator<std::random_access_iterator_tag, T>::
|
||||
//difference_type;
|
||||
public:
|
||||
ConstIterator() : _p(0) { }
|
||||
const T& operator[](difference_type n) const { return _p[n]; }
|
||||
const T& operator*() const { return *_p; }
|
||||
const T* operator->() const { return _p; }
|
||||
const ConstIterator& operator++() { ++_p; return *this; }
|
||||
const ConstIterator& operator--() { --_p; return *this; }
|
||||
ConstIterator operator++(int)
|
||||
{
|
||||
ConstIterator r = *this;
|
||||
++_p;
|
||||
return r;
|
||||
}
|
||||
ConstIterator operator--(int)
|
||||
{
|
||||
ConstIterator r = *this;
|
||||
--_p;
|
||||
return r;
|
||||
}
|
||||
const ConstIterator& operator+=(difference_type n)
|
||||
{
|
||||
_p += n;
|
||||
return *this;
|
||||
}
|
||||
const ConstIterator& operator-=(difference_type n)
|
||||
{
|
||||
_p -= n;
|
||||
return *this;
|
||||
}
|
||||
const ConstIterator& operator+(difference_type n) const
|
||||
{
|
||||
ConstIterator r = *this;
|
||||
r += n;
|
||||
return r;
|
||||
}
|
||||
const ConstIterator& operator-(difference_type n) const
|
||||
{
|
||||
ConstIterator r = *this;
|
||||
r -= n;
|
||||
return r;
|
||||
}
|
||||
friend inline Iterator operator+(difference_type n,
|
||||
const ConstIterator& a)
|
||||
{
|
||||
return a + n;
|
||||
}
|
||||
friend inline Iterator operator-(difference_type n,
|
||||
const ConstIterator& a)
|
||||
{
|
||||
return a - n;
|
||||
}
|
||||
bool operator==(const ConstIterator& other) const
|
||||
{
|
||||
return _p == other._p;
|
||||
}
|
||||
bool operator!=(const ConstIterator& other) const
|
||||
{
|
||||
return _p != other._p;
|
||||
}
|
||||
bool operator<(const ConstIterator& other) const
|
||||
{
|
||||
return _p < other._p;
|
||||
}
|
||||
bool operator>(const ConstIterator& other) const
|
||||
{
|
||||
return _p > other._p;
|
||||
}
|
||||
bool operator<=(const ConstIterator& other) const
|
||||
{
|
||||
return _p <= other._p;
|
||||
}
|
||||
bool operator>=(const ConstIterator& other) const
|
||||
{
|
||||
return _p >= other._p;
|
||||
}
|
||||
ptrdiff_t operator-(const ConstIterator& other) const
|
||||
{
|
||||
return other._p - _p;
|
||||
}
|
||||
private:
|
||||
const T* _p;
|
||||
ConstIterator(const T* p) : _p(p) { }
|
||||
friend class Body;
|
||||
};
|
||||
|
||||
ConstIterator begin() const { return ConstIterator(&((*this)[0])); }
|
||||
ConstIterator end() const { return ConstIterator(&((*this)[size()])); }
|
||||
Iterator begin() { return Iterator(&((*this)[0])); }
|
||||
Iterator end() { return Iterator(&((*this)[size()])); }
|
||||
|
||||
void justSetSize(int size) const { _size = size; }
|
||||
|
||||
private:
|
||||
void constructTail(int size)
|
||||
{
|
||||
int oldSize = _size;
|
||||
try {
|
||||
while (_size < size)
|
||||
constructT();
|
||||
}
|
||||
catch (...) {
|
||||
destructTail(oldSize);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
void destructTail(int size) const
|
||||
{
|
||||
for (; _size > size; --_size)
|
||||
(&(*this)[_size - 1])->~T();
|
||||
}
|
||||
void destruct() const
|
||||
{
|
||||
destructTail(0);
|
||||
this->~Body();
|
||||
}
|
||||
|
||||
mutable int _size; // Needs to be mutable so destroy() can be const.
|
||||
|
||||
// Only constructor is private to prevent inheritance, composition and
|
||||
// stack allocation. All instances are constructed via the placement
|
||||
// new call in create().
|
||||
template<typename... Args> Body(Args&&... args)
|
||||
: H(std::forward<Args>(args)...), _size(0) { }
|
||||
|
||||
// HashTable and Set keep all elements constructed, and use _size to
|
||||
// keep track of the number of actual entries in the table.
|
||||
template<class Key, class Value> friend class HashTable;
|
||||
template<class Key> friend class Set;
|
||||
friend class Array;
|
||||
};
|
||||
|
||||
template<class H> class HT : public Body<H> { public: T _t; };
|
||||
|
||||
class AppendableBaseBody : public Handle::Body
|
||||
{
|
||||
public:
|
||||
int _allocated;
|
||||
};
|
||||
Array() { }
|
||||
Array(const List<T>& list)
|
||||
{
|
||||
int n = list.count();
|
||||
if (n != 0) {
|
||||
*this = Array(create<>(n, 0));
|
||||
for (auto p : list)
|
||||
body()->constructT(p);
|
||||
}
|
||||
}
|
||||
Array(const AppendableArray<T>& a) { *this = Handle(a); }
|
||||
explicit Array(int n)
|
||||
{
|
||||
if (n != 0)
|
||||
*this = Array(create<>(n, n));
|
||||
}
|
||||
void allocate(int n) { *this = Array(n); }
|
||||
void ensure(int n) { if (count() < n) allocate(n); }
|
||||
bool operator==(const Array& other) const
|
||||
{
|
||||
int n = count();
|
||||
if (n != other.count())
|
||||
return false;
|
||||
for (int i = 0; i < n; ++i)
|
||||
if ((*this)[i] != other[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
template<class B> bool operator==(const AppendableArray<T, B>& other) const
|
||||
{
|
||||
int n = count();
|
||||
if (n != other.count())
|
||||
return false;
|
||||
for (int i = 0; i < n; ++i)
|
||||
if ((*this)[i] != other[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool operator!=(const Array& other) const { return !operator==(other); }
|
||||
template<class B> bool operator!=(const AppendableArray<T, B>& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
T& operator[](int i) { return (*body())[i]; }
|
||||
const T& operator[](int i) const { return (*body())[i]; }
|
||||
int count() const { return body() == 0 ? 0 : body()->size(); }
|
||||
Array copy() const
|
||||
{
|
||||
Array r(create<>(count(), 0));
|
||||
for (int i = 0; i < count(); ++i)
|
||||
r.body()->constructT((*this)[i]);
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef typename Body<>::Iterator Iterator;
|
||||
typedef typename Body<>::ConstIterator ConstIterator;
|
||||
ConstIterator begin() const
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->begin();
|
||||
return typename Body<>::ConstIterator();
|
||||
}
|
||||
ConstIterator end() const
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->end();
|
||||
return typename Body<>::ConstIterator();
|
||||
}
|
||||
Iterator begin()
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->begin();
|
||||
return typename Body<>::Iterator();
|
||||
}
|
||||
Iterator end()
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->end();
|
||||
return typename Body<>::Iterator();
|
||||
}
|
||||
|
||||
private:
|
||||
Array(const Handle& other) : Handle(other) { }
|
||||
Body<>* body() { return as<Body<>>(); }
|
||||
const Body<>* body() const { return as<Body<>>(); }
|
||||
template<class U, class B> friend class AppendableArray;
|
||||
};
|
||||
|
||||
// AppendableArray is not quite a value type, since changing an element in one
|
||||
// array will affect copies of the same array unless a deep copy is made with
|
||||
// copy(). Appending to an array may cause it to become a deep copy, if more
|
||||
// storage space was needed.
|
||||
template<class T, class Base> class AppendableArray : private Handle
|
||||
{
|
||||
protected:
|
||||
typedef typename Array<T>::template Body<Base> Body;
|
||||
public:
|
||||
AppendableArray() { }
|
||||
AppendableArray(const Handle& other) : Handle(other) { }
|
||||
AppendableArray(const List<T>& list) : AppendableArray(list.count())
|
||||
{
|
||||
for (auto p : list)
|
||||
body()->constructT(p);
|
||||
}
|
||||
explicit AppendableArray(int n)
|
||||
{
|
||||
// The 8 bytes is the observed malloc overhead on both GCC and VC,
|
||||
// 32-bit and 64-bit (though not VC with debug heap). The idea is that
|
||||
// we allocate actual memory blocks that are powers of 2 bytes to
|
||||
// minimize fragmentation, and allocate as many objects as we can in
|
||||
// that space so as to make the best use of it.
|
||||
int overhead = Body::headSize() + 8;
|
||||
int s = n*sizeof(T) + overhead;
|
||||
s = roundUpToPowerOf2(s) - overhead;
|
||||
int count = s/sizeof(T);
|
||||
int extra = s%sizeof(T);
|
||||
AppendableArray b =
|
||||
Array<T>::template create<Handle, Base>(count, 0, extra);
|
||||
b.body()->_allocated = count;
|
||||
*this = b;
|
||||
}
|
||||
void allocate(int n)
|
||||
{
|
||||
if (allocated() < n) {
|
||||
AppendableArray a(n);
|
||||
if (count() > 0)
|
||||
a.addUnchecked(body()->pointer(), count());
|
||||
*this = a;
|
||||
}
|
||||
}
|
||||
void append(const T& value) { append(&value, 1); }
|
||||
void append(const Array<T>& other)
|
||||
{
|
||||
if (other.count() > 0)
|
||||
append(&other[0], other.count());
|
||||
}
|
||||
template<class B> void append(const AppendableArray<T, B>& other)
|
||||
{
|
||||
if (other.count() > 0)
|
||||
append(&other[0], other.count());
|
||||
}
|
||||
void append(const T* data, int length)
|
||||
{
|
||||
if (allocated() < count() + length) {
|
||||
AppendableArray a(count() + length);
|
||||
if (count() > 0)
|
||||
a.addUnchecked(body()->pointer(), count());
|
||||
a.addUnchecked(data, length);
|
||||
*this = a;
|
||||
}
|
||||
else {
|
||||
int oldCount = count();
|
||||
try {
|
||||
addUnchecked(data, length);
|
||||
}
|
||||
catch (...) {
|
||||
body()->setSize(oldCount);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
void unappend(int elements = 1) { body()->setSize(count() - elements); }
|
||||
// Like append but with default construction instead of copying.
|
||||
void expand(int length)
|
||||
{
|
||||
if (allocated() < count() + length) {
|
||||
AppendableArray a(count() + length);
|
||||
if (count() > 0)
|
||||
a.addUnchecked(body()->pointer(), count());
|
||||
a.expandUnchecked(length);
|
||||
*this = a;
|
||||
}
|
||||
else {
|
||||
int oldCount = count();
|
||||
try {
|
||||
expandUnchecked(length);
|
||||
}
|
||||
catch (...) {
|
||||
body()->setSize(oldCount);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
void ensure(int n)
|
||||
{
|
||||
if (n > count())
|
||||
expand(n - count());
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
if (count() > 0)
|
||||
body()->setSize(0);
|
||||
}
|
||||
|
||||
bool operator==(const Array<T>& other) const
|
||||
{
|
||||
int n = count();
|
||||
if (n != other.count())
|
||||
return false;
|
||||
for (int i = 0; i < n; ++i)
|
||||
if ((*this)[i] != other[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
template<class B> bool operator==(const AppendableArray<T, B>& other) const
|
||||
{
|
||||
int n = count();
|
||||
if (n != other.count())
|
||||
return false;
|
||||
for (int i = 0; i < n; ++i)
|
||||
if ((*this)[i] != other[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const Array<T>& other) const { return !operator==(other); }
|
||||
template<class B> bool operator!=(const AppendableArray<T, B>& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
T& operator[](int i) { return (*body())[i]; }
|
||||
const T& operator[](int i) const { return (*body())[i]; }
|
||||
int count() const { return body() == 0 ? 0 : body()->size(); }
|
||||
int allocated() const { return body() == 0 ? 0 : body()->_allocated; }
|
||||
AppendableArray copy() const
|
||||
{
|
||||
AppendableArray r(count());
|
||||
r.addUnchecked(&(*this)[0], count());
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef typename Body::Iterator Iterator;
|
||||
Iterator begin() const
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->begin();
|
||||
return Body::Iterator();
|
||||
}
|
||||
Iterator end() const
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->end();
|
||||
return Body::Iterator();
|
||||
}
|
||||
Iterator begin()
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->begin();
|
||||
return Body::Iterator();
|
||||
}
|
||||
Iterator end()
|
||||
{
|
||||
if (body() != 0)
|
||||
return body()->end();
|
||||
return Body::Iterator();
|
||||
}
|
||||
|
||||
private:
|
||||
void addUnchecked(const T* start, int c)
|
||||
{
|
||||
for (int i = 0; i < c; ++i) {
|
||||
body()->constructT(*start);
|
||||
++start;
|
||||
}
|
||||
}
|
||||
void expandUnchecked(int c)
|
||||
{
|
||||
for (int i = 0; i < c; ++i)
|
||||
body()->constructT();
|
||||
}
|
||||
Body* body() { return as<Body>(); }
|
||||
const Body* body() const { return as<Body>(); }
|
||||
|
||||
// For access to body().
|
||||
template<class Key, class Value> friend class HashTable;
|
||||
template<class Key> friend class Set;
|
||||
|
||||
// For conversion to Handle
|
||||
template<class U> friend class Array;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_ARRAY_H
|
||||
Reference in New Issue
Block a user