mirror of
https://github.com/rehlds/rehlds.git
synced 2025-01-01 01:25:38 +03:00
Merge pull request #22 from theAsmodai/master
Finished work with JIT in DELTA_CheckDelta and DELTA_WriteDelta
This commit is contained in:
commit
4821823407
@ -349,41 +349,63 @@ int DELTA_FindFieldIndex(struct delta_s *pFields, const char *fieldname)
|
||||
}
|
||||
|
||||
Con_Printf(__FUNCTION__ ": Warning, couldn't find %s\n", fieldname);
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* <24032> ../engine/delta.c:393 */
|
||||
void DELTA_SetField(struct delta_s *pFields, const char *fieldname)
|
||||
{
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
int index = DELTA_FindFieldIndex(pFields, fieldname);
|
||||
|
||||
if (index != -1)
|
||||
DELTA_SetFieldByIndex(pFields, index);
|
||||
#else
|
||||
delta_description_t *pTest = DELTA_FindField(pFields, fieldname);
|
||||
|
||||
|
||||
if (pTest)
|
||||
{
|
||||
pTest->flags |= FDT_MARK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* <240b2> ../engine/delta.c:411 */
|
||||
void DELTA_UnsetField(struct delta_s *pFields, const char *fieldname)
|
||||
{
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
int index = DELTA_FindFieldIndex(pFields, fieldname);
|
||||
|
||||
if (index != -1)
|
||||
DELTA_UnsetFieldByIndex(pFields, index);
|
||||
#else
|
||||
delta_description_t *pTest = DELTA_FindField(pFields, fieldname);
|
||||
|
||||
|
||||
if (pTest)
|
||||
{
|
||||
pTest->flags &= ~FDT_MARK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* <24132> ../engine/delta.c:429 */
|
||||
void DELTA_SetFieldByIndex(struct delta_s *pFields, int fieldNumber)
|
||||
{
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
DELTAJit_SetFieldByIndex(pFields, fieldNumber);
|
||||
#else
|
||||
pFields->pdd[fieldNumber].flags |= FDT_MARK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* <2416a> ../engine/delta.c:441 */
|
||||
void DELTA_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber)
|
||||
{
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
DELTAJit_UnsetFieldByIndex(pFields, fieldNumber);
|
||||
#else
|
||||
pFields->pdd[fieldNumber].flags &= ~FDT_MARK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* <23cc4> ../engine/delta.c:453 */
|
||||
@ -428,17 +450,28 @@ int DELTA_TestDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
|
||||
case DT_ANGLE:
|
||||
different = *(uint32 *)&from[pTest->fieldOffset] != *(uint32 *)&to[pTest->fieldOffset];
|
||||
break;
|
||||
#ifdef REHLDS_FIXES
|
||||
// don't use multiplier when checking, to increase performance
|
||||
case DT_TIMEWINDOW_8:
|
||||
case DT_TIMEWINDOW_BIG:
|
||||
different = (int32)(*(float *)&from[pTest->fieldOffset]) != (int32)(*(float *)&to[pTest->fieldOffset]);
|
||||
break;
|
||||
#else
|
||||
case DT_TIMEWINDOW_8:
|
||||
different = (int32)(*(float *)&from[pTest->fieldOffset] * 100.0) != (int32)(*(float *)&to[pTest->fieldOffset] * 100.0);
|
||||
break;
|
||||
case DT_TIMEWINDOW_BIG:
|
||||
different = (int32)(*(float *)&from[pTest->fieldOffset] * 1000.0) != (int32)(*(float *)&to[pTest->fieldOffset] * 1000.0);
|
||||
break;
|
||||
#endif
|
||||
case DT_STRING:
|
||||
st1 = (char*)&from[pTest->fieldOffset];
|
||||
st2 = (char*)&to[pTest->fieldOffset];
|
||||
if (!(!*st1 && !*st2 || *st1 && *st2 && !Q_stricmp(st1, st2))) // Not sure why it is case insensitive, but it looks so
|
||||
{
|
||||
#ifdef REHLDS_FIXES
|
||||
different = TRUE;
|
||||
#endif // REHLDS_FIXES
|
||||
length = Q_strlen(st2);
|
||||
}
|
||||
break;
|
||||
@ -546,26 +579,40 @@ void DELTA_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount)
|
||||
delta_description_t *pTest;
|
||||
int i;
|
||||
int lastbit = -1;
|
||||
int bitnumber;
|
||||
int fieldCount = pFields->fieldCount;
|
||||
|
||||
Q_memset(bits, 0, 8);
|
||||
|
||||
lastbit = -1;
|
||||
bitnumber = -1;
|
||||
for (i = fieldCount - 1, pTest = &pFields->pdd[i]; i >= 0; i--, pTest--)
|
||||
{
|
||||
if (pTest->flags & FDT_MARK)
|
||||
{
|
||||
if (lastbit == -1)
|
||||
bitnumber = i;
|
||||
lastbit = i;
|
||||
bits[i > 31 ? 1 : 0] |= 1 << (i & 0x1F);
|
||||
lastbit = bitnumber;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REHLDS_FIXES
|
||||
// fix for bad bytecount when no fields are marked
|
||||
if (lastbit == -1) {
|
||||
*bytecount = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
*bytecount = (lastbit >> 3) + 1;
|
||||
}
|
||||
|
||||
qboolean DELTA_IsFieldMarked(delta_t* pFields, int fieldNumber)
|
||||
{
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
return DELTAJit_IsFieldMarked(pFields, fieldNumber);
|
||||
#else
|
||||
return pFields->pdd[fieldNumber].flags & FDT_MARK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* <2456d> ../engine/delta.c:782 */
|
||||
void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pFields)
|
||||
{
|
||||
@ -579,8 +626,13 @@ void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pF
|
||||
|
||||
for (i = 0, pTest = pFields->pdd; i < fieldCount; i++, pTest++)
|
||||
{
|
||||
#if defined (REHLDS_OPT_PEDANTIC) || defined (REHLDS_FIXES)
|
||||
if (!DELTA_IsFieldMarked(pFields, i))
|
||||
continue;
|
||||
#else
|
||||
if (!(pTest->flags & FDT_MARK))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
fieldSign = pTest->fieldType & DT_SIGNED;
|
||||
fieldType = pTest->fieldType & ~DT_SIGNED;
|
||||
@ -678,49 +730,52 @@ void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pF
|
||||
}
|
||||
|
||||
/* <2467e> ../engine/delta.c:924 */
|
||||
int DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
|
||||
qboolean DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
|
||||
{
|
||||
int sendfields;
|
||||
qboolean sendfields;
|
||||
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
sendfields = DELTAJit_Feilds_Clear_Mark_Check(from, to, pFields);
|
||||
sendfields = DELTAJit_Fields_Clear_Mark_Check(from, to, pFields);
|
||||
#else
|
||||
DELTA_ClearFlags(pFields);
|
||||
DELTA_MarkSendFields(from, to, pFields);
|
||||
#endif
|
||||
sendfields = DELTA_CountSendFields(pFields);
|
||||
#endif
|
||||
|
||||
return sendfields;
|
||||
}
|
||||
|
||||
/* <247f5> ../engine/delta.c:949 */
|
||||
NOINLINE int DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void))
|
||||
NOINLINE qboolean DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void))
|
||||
{
|
||||
int sendfields;
|
||||
qboolean sendfields;
|
||||
int bytecount;
|
||||
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
sendfields = DELTAJit_Feilds_Clear_Mark_Check(from, to, pFields);
|
||||
#else
|
||||
sendfields = DELTAJit_Fields_Clear_Mark_Check(from, to, pFields);
|
||||
#else // REHLDS_OPT_PEDANTIC || REHLDS_FIXES
|
||||
DELTA_ClearFlags(pFields);
|
||||
DELTA_MarkSendFields(from, to, pFields);
|
||||
sendfields = DELTA_CountSendFields(pFields);
|
||||
#endif
|
||||
#endif // REHLDS_OPT_PEDANTIC || REHLDS_FIXES
|
||||
|
||||
//sendfields = DELTA_CountSendFields(pFields);
|
||||
_DELTA_WriteDelta(from, to, force, pFields, callback, sendfields);
|
||||
return sendfields;
|
||||
}
|
||||
|
||||
/* <24760> ../engine/delta.c:963 */
|
||||
int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), int sendfields)
|
||||
qboolean _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)( void ), qboolean sendfields)
|
||||
{
|
||||
int i;
|
||||
int bytecount;
|
||||
int bits[2]; // this is a limit with 64 fields max in delta
|
||||
int bits[2];
|
||||
|
||||
if (sendfields || force)
|
||||
{
|
||||
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
|
||||
DELTAJit_SetSendFlagBits(pFields, bits, &bytecount);
|
||||
#else
|
||||
DELTA_SetSendFlagBits(pFields, bits, &bytecount);
|
||||
#endif
|
||||
|
||||
if (callback)
|
||||
callback();
|
||||
@ -728,7 +783,7 @@ int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, de
|
||||
MSG_WriteBits(bytecount, 3);
|
||||
for (i = 0; i < bytecount; i++)
|
||||
{
|
||||
MSG_WriteBits(((byte*)bits)[i], 8);
|
||||
MSG_WriteBits(( (byte*)bits )[i], 8);
|
||||
}
|
||||
|
||||
DELTA_WriteMarkedFields(from, to, pFields);
|
||||
@ -737,6 +792,7 @@ int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, de
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* <24aa0> ../engine/delta.c:1010 */
|
||||
int DELTA_ParseDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
|
||||
{
|
||||
@ -1038,6 +1094,12 @@ delta_t *DELTA_BuildFromLinks(delta_link_t **pplinks)
|
||||
DELTA_ReverseLinks(pplinks);
|
||||
|
||||
count = DELTA_CountLinks(*pplinks);
|
||||
|
||||
#ifdef REHLDS_FIXES
|
||||
if (count > DELTA_MAX_FIELDS)
|
||||
Sys_Error(__FUNCTION__ ": Too many fields in delta description %i (MAX %i)\n", count, DELTA_MAX_FIELDS);
|
||||
#endif
|
||||
|
||||
pdesc = (delta_description_t *)Mem_ZeroMalloc(sizeof(delta_description_t) * count);
|
||||
|
||||
for (p = *pplinks, pcur = pdesc; p != NULL; p = p->next, pcur++)
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
#include "maintypes.h"
|
||||
|
||||
#define DELTA_MAX_FIELDS 56 // 7*8
|
||||
|
||||
#define DT_BYTE BIT(0) // A byte
|
||||
#define DT_SHORT BIT(1) // 2 byte field
|
||||
#define DT_FLOAT BIT(2) // A floating point field
|
||||
@ -134,10 +136,11 @@ int DELTA_TestDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
int DELTA_CountSendFields(delta_t *pFields);
|
||||
void DELTA_MarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
void DELTA_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount);
|
||||
qboolean DELTA_IsFieldMarked(delta_t* pFields, int fieldNumber);
|
||||
void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
int DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
int DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void));
|
||||
int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), int sendfields);
|
||||
qboolean DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
qboolean DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void));
|
||||
qboolean _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), qboolean sendfields);
|
||||
int DELTA_ParseDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
void DELTA_AddEncoder(char *name, void(*conditionalencode)(struct delta_s *, const unsigned char *, const unsigned char *));
|
||||
void DELTA_ClearEncoders(void);
|
||||
|
@ -3,6 +3,20 @@
|
||||
|
||||
CDeltaJitRegistry g_DeltaJitRegistry;
|
||||
|
||||
bool deltajit_memblock::isEmpty() const
|
||||
{
|
||||
if (numFields == 0)
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < numFields; i++)
|
||||
{
|
||||
if (fields[i].mask != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 DELTAJIT_CreateMask(int startBit, int endBit) {
|
||||
if (startBit < 0) startBit = 0;
|
||||
if (endBit < 0) endBit = 0;
|
||||
@ -107,36 +121,57 @@ void DELTAJIT_CreateDescription(delta_t* delta, deltajitdata_t &jitdesc) {
|
||||
|
||||
}
|
||||
|
||||
class CDeltaClearMarkFieldsJIT;
|
||||
|
||||
class CDeltaJit {
|
||||
public:
|
||||
CDeltaClearMarkFieldsJIT* cleanMarkCheckFunc;
|
||||
delta_t* delta;
|
||||
|
||||
int markedFieldsMaskSize;
|
||||
|
||||
int marked_fields_mask[2];
|
||||
int sse_highbits[2]; //High 64 bits for manipulating marked_fields_mask via SSE registers
|
||||
|
||||
CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc);
|
||||
|
||||
virtual ~CDeltaJit();
|
||||
};
|
||||
|
||||
class CDeltaClearMarkFieldsJIT : public jitasm::function<int, CDeltaClearMarkFieldsJIT, void*, void*, void*> {
|
||||
public:
|
||||
deltajitdata_t *jitdesc;
|
||||
deltajit_marked_count_type_t countType;
|
||||
|
||||
XmmReg marked_fields_mask = xmm5;
|
||||
|
||||
|
||||
CDeltaClearMarkFieldsJIT(deltajitdata_t *_jitdesc, deltajit_marked_count_type_t _countType)
|
||||
: jitdesc(_jitdesc), countType(_countType) {
|
||||
}
|
||||
|
||||
void checkFieldMask(jitasm::Frontend::Reg32& mask, deltajit_memblock_field* jitField);
|
||||
Result main(Addr src, Addr dst, Addr delta);
|
||||
void processStrings(Addr src, Addr dst, Addr delta);
|
||||
void callConditionalEncoder(Addr src, Addr dst, Addr delta);
|
||||
void countMarkedFields();
|
||||
Result main(Addr src, Addr dst, Addr deltaJit);
|
||||
void processStrings(Addr src, Addr dst);
|
||||
void callConditionalEncoder(Addr src, Addr dst, Addr deltaJit);
|
||||
void calculateBytecount();
|
||||
};
|
||||
|
||||
void CDeltaClearMarkFieldsJIT::checkFieldMask(jitasm::Frontend::Reg32& mask, deltajit_memblock_field* jitField) {
|
||||
test(mask, (uint16)jitField->mask);
|
||||
setnz(al);
|
||||
movzx(dx, al);
|
||||
movzx(edx, al);
|
||||
}
|
||||
|
||||
void CDeltaClearMarkFieldsJIT::callConditionalEncoder(Addr src, Addr dst, Addr delta) {
|
||||
void CDeltaClearMarkFieldsJIT::callConditionalEncoder(Addr src, Addr dst, Addr deltaJit) {
|
||||
//This generator expects that following registers are already initialized:
|
||||
// esi = src
|
||||
// edi = dst
|
||||
|
||||
int deltaOffset = (offsetof(CDeltaJit, delta));
|
||||
int condEncoderOffset = (offsetof(delta_t, conditionalencode));
|
||||
mov(eax, ptr[delta]);
|
||||
mov(eax, ptr[deltaJit]);
|
||||
mov(eax, ptr[eax + deltaOffset]);
|
||||
mov(ecx, dword_ptr[eax + condEncoderOffset]);
|
||||
If(ecx != 0);
|
||||
push(edi);
|
||||
@ -148,78 +183,119 @@ void CDeltaClearMarkFieldsJIT::callConditionalEncoder(Addr src, Addr dst, Addr d
|
||||
EndIf();
|
||||
}
|
||||
|
||||
void CDeltaClearMarkFieldsJIT::countMarkedFields() {
|
||||
void CDeltaClearMarkFieldsJIT::calculateBytecount() {
|
||||
//This generator expects that following registers are already initialized:
|
||||
// ebx = delta->pdd
|
||||
//
|
||||
//Returns value: 'changed flag' or count in eax
|
||||
//ebx = delta
|
||||
|
||||
xor_(eax, eax);
|
||||
size_t delta_markbits_offset = offsetof(CDeltaJit, marked_fields_mask);
|
||||
mov(eax, dword_ptr[ebx + delta_markbits_offset]);
|
||||
xor_(edx, edx);
|
||||
|
||||
if (countType == DJ_M_DONT_COUNT) {
|
||||
return;
|
||||
// 0-7
|
||||
mov(ecx, 1);
|
||||
test(eax, 0xFF);
|
||||
cmovnz(edx, ecx);
|
||||
|
||||
// 8-15
|
||||
if (jitdesc->numFields > 7)
|
||||
{
|
||||
mov(esi, 2);
|
||||
test(eax, 0xFF00);
|
||||
cmovnz(edx, esi);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < jitdesc->numFields; i++) {
|
||||
int fieldId = jitdesc->fields[i].id;
|
||||
int flagsOffset = (fieldId * sizeof(delta_description_t) + offsetof(delta_description_t, flags));
|
||||
|
||||
if (i & 1) { //rotate between cx and dx to decrease instruction result dependencies
|
||||
mov(cx, word_ptr[ebx + flagsOffset]);
|
||||
and_(cx, 1);
|
||||
or_(ax, cx);
|
||||
} else {
|
||||
mov(dx, word_ptr[ebx + flagsOffset]);
|
||||
and_(dx, 1);
|
||||
or_(ax, dx);
|
||||
}
|
||||
|
||||
//insert 'is changed' check every 8 fields
|
||||
if ((i & 7) == 0) {
|
||||
jnz("countMarkedFields_finish");
|
||||
}
|
||||
// 16-23
|
||||
if (jitdesc->numFields > 15)
|
||||
{
|
||||
mov(ecx, 3);
|
||||
test(eax, 0xFF0000);
|
||||
cmovnz(edx, ecx);
|
||||
}
|
||||
|
||||
L("countMarkedFields_finish");
|
||||
// 24-31
|
||||
if (jitdesc->numFields > 23)
|
||||
{
|
||||
mov(esi, 4);
|
||||
test(eax, 0xFF000000);
|
||||
cmovnz(edx, esi);
|
||||
}
|
||||
|
||||
if (jitdesc->numFields > 31)
|
||||
{
|
||||
mov(eax, dword_ptr[ebx + delta_markbits_offset + 4]);
|
||||
|
||||
// 32-39
|
||||
mov(ecx, 5);
|
||||
test(eax, 0xFF);
|
||||
cmovnz(edx, ecx);
|
||||
|
||||
// 40-47
|
||||
if (jitdesc->numFields > 39)
|
||||
{
|
||||
mov(esi, 6);
|
||||
test(eax, 0xFF00);
|
||||
cmovnz(edx, esi);
|
||||
}
|
||||
|
||||
// 48-55
|
||||
if (jitdesc->numFields > 47)
|
||||
{
|
||||
mov(ecx, 7);
|
||||
test(eax, 0xFF0000);
|
||||
cmovnz(edx, ecx);
|
||||
}
|
||||
|
||||
// maxfields is 56
|
||||
}
|
||||
|
||||
size_t delta_masksize_offset = offsetof(CDeltaJit, markedFieldsMaskSize);
|
||||
mov(dword_ptr[ebx + delta_masksize_offset], edx);
|
||||
}
|
||||
|
||||
CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr dst, Addr delta)
|
||||
CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr dst, Addr deltaJit)
|
||||
{
|
||||
|
||||
#ifndef REHLDS_FIXES
|
||||
sub(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking
|
||||
#endif
|
||||
|
||||
mov(esi, ptr[src]);
|
||||
mov(edi, ptr[dst]);
|
||||
mov(ebx, ptr[delta]);
|
||||
int fieldsOffset = (offsetof(delta_t, pdd));
|
||||
mov(ebx, dword_ptr[ebx + fieldsOffset]);
|
||||
movdqu(xmm3, xmmword_ptr[esi]);
|
||||
movdqu(xmm4, xmmword_ptr[edi]);
|
||||
|
||||
auto zero_xmm = xmm2;
|
||||
pxor(zero_xmm, zero_xmm);
|
||||
for (unsigned int i = 0; i < jitdesc->numblocks; i++) {
|
||||
if (!jitdesc->blocks[i].isEmpty()) {
|
||||
movdqu(xmm3, xmmword_ptr[esi + (i * 16)]);
|
||||
movdqu(xmm4, xmmword_ptr[edi + (i * 16)]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto mask = ecx;
|
||||
xor_(mask, mask);
|
||||
|
||||
pxor(marked_fields_mask, marked_fields_mask);
|
||||
|
||||
for (unsigned int i = 0; i < jitdesc->numblocks; i++) {
|
||||
auto block = &jitdesc->blocks[i];
|
||||
|
||||
if (block->isEmpty())
|
||||
continue;
|
||||
|
||||
movdqa(xmm0, xmm3);
|
||||
movdqa(xmm1, xmm4);
|
||||
|
||||
//prefetch next blocks
|
||||
if (i < jitdesc->numblocks) {
|
||||
movdqu(xmm3, xmmword_ptr[esi + ((i + 1) * 16)]);
|
||||
movdqu(xmm4, xmmword_ptr[edi + ((i + 1) * 16)]);
|
||||
for (unsigned int j = i + 1; j < jitdesc->numblocks; j++) {
|
||||
if (!jitdesc->blocks[j].isEmpty()) {
|
||||
movdqu(xmm3, xmmword_ptr[esi + (j * 16)]);
|
||||
movdqu(xmm4, xmmword_ptr[edi + (j * 16)]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pxor(xmm0, xmm1);
|
||||
pcmpeqb(xmm0, xmm2);
|
||||
pcmpeqb(xmm0, xmm1);
|
||||
pmovmskb(mask, xmm0);
|
||||
not_(mask);
|
||||
|
||||
|
||||
auto block = &jitdesc->blocks[i];
|
||||
for (unsigned int j = 0; j < block->numFields; j++) {
|
||||
auto jitField = &block->fields[j];
|
||||
|
||||
@ -245,7 +321,7 @@ CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr d
|
||||
|
||||
cmp(eax, edx);
|
||||
setne(al);
|
||||
movzx(dx, al);
|
||||
movzx(edx, al);
|
||||
|
||||
} else {
|
||||
continue;
|
||||
@ -257,34 +333,52 @@ CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr d
|
||||
checkFieldMask(mask, jitField);
|
||||
#endif
|
||||
|
||||
int flagsOffset = (jitField->field->id * sizeof(delta_description_t) + offsetof(delta_description_t, flags));
|
||||
if (jitField->first) {
|
||||
mov(word_ptr[ebx + flagsOffset], dx);
|
||||
}
|
||||
else {
|
||||
or_(word_ptr[ebx + flagsOffset], dx);
|
||||
}
|
||||
// set bit in send mask
|
||||
movd(xmm0, edx);
|
||||
psllq(xmm0, jitField->field->id);
|
||||
por(marked_fields_mask, xmm0);
|
||||
}
|
||||
}
|
||||
|
||||
processStrings(src, dst, delta);
|
||||
size_t delta_markbits_offset = offsetof(CDeltaJit, marked_fields_mask);
|
||||
|
||||
callConditionalEncoder(src, dst, delta);
|
||||
//Before calling the condition encoder we have to save 'marked fields' mask
|
||||
//from SSE register into the CDeltaJit::marked_fields_mask, because conditional encoder can modify the mask
|
||||
mov(ebx, ptr[deltaJit]);
|
||||
movdqu(xmmword_ptr[ebx + delta_markbits_offset], marked_fields_mask);
|
||||
|
||||
countMarkedFields();
|
||||
processStrings(src, dst);
|
||||
|
||||
//emit conditional encoder call
|
||||
callConditionalEncoder(src, dst, deltaJit);
|
||||
|
||||
// check if mask is empty
|
||||
mov(edi, dword_ptr[ebx + delta_markbits_offset]);
|
||||
or_(edi, dword_ptr[ebx + delta_markbits_offset + 4]);
|
||||
|
||||
If(edi != 0);
|
||||
calculateBytecount();
|
||||
Else();
|
||||
//set maskSize to 0 if there are no marked fields
|
||||
size_t delta_masksize_offset = offsetof(CDeltaJit, markedFieldsMaskSize);
|
||||
xor_(edx, edx);
|
||||
mov(dword_ptr[ebx + delta_masksize_offset], edx);
|
||||
EndIf();
|
||||
|
||||
#ifndef REHLDS_FIXES
|
||||
add(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking
|
||||
#endif
|
||||
#endif // REHLDS_FIXES
|
||||
|
||||
return eax;
|
||||
return edx;
|
||||
}
|
||||
|
||||
void CDeltaClearMarkFieldsJIT::processStrings(Addr src, Addr dst, Addr delta) {
|
||||
void CDeltaClearMarkFieldsJIT::processStrings(Addr src, Addr dst) {
|
||||
//This generator expects that following registers are already initialized:
|
||||
// ebx = delta->pdd
|
||||
// esi = src
|
||||
// edi = dst
|
||||
// ebx = deltaJit
|
||||
|
||||
size_t delta_markbits_offset = offsetof(CDeltaJit, marked_fields_mask);
|
||||
|
||||
//strings
|
||||
for (unsigned int i = 0; i < jitdesc->numFields; i++) {
|
||||
@ -292,43 +386,35 @@ void CDeltaClearMarkFieldsJIT::processStrings(Addr src, Addr dst, Addr delta) {
|
||||
if (jitField->type != DT_STRING)
|
||||
continue;
|
||||
|
||||
mov(eax, esi);
|
||||
mov(edx, edi);
|
||||
add(eax, jitField->offset);
|
||||
add(edx, jitField->offset);
|
||||
// will be parallel
|
||||
lea(eax, ptr[esi + jitField->offset]);
|
||||
lea(edx, ptr[edi + jitField->offset]);
|
||||
|
||||
push(eax);
|
||||
push(edx);
|
||||
mov(ecx, (size_t)&Q_stricmp);
|
||||
call(ecx);
|
||||
add(esp, 8);
|
||||
xor_(ecx, ecx);
|
||||
test(eax, eax);
|
||||
setnz(cl);
|
||||
movzx(cx, cl);
|
||||
|
||||
|
||||
int flagsOffset = (jitField->id * sizeof(delta_description_t) + offsetof(delta_description_t, flags));
|
||||
mov(word_ptr[ebx + flagsOffset], cx);
|
||||
shl(ecx, jitField->id & 31);
|
||||
or_(ptr[ebx + delta_markbits_offset + ((jitField->id > 31) ? 4 : 0)], ecx);
|
||||
}
|
||||
}
|
||||
|
||||
class CDeltaJit {
|
||||
public:
|
||||
CDeltaClearMarkFieldsJIT* cleanMarkCheckFunc;
|
||||
delta_t* delta;
|
||||
CDeltaJit::CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc) {
|
||||
delta = _delta;
|
||||
cleanMarkCheckFunc = _cleanMarkCheckFunc;
|
||||
}
|
||||
|
||||
CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc) {
|
||||
delta = _delta;
|
||||
cleanMarkCheckFunc = _cleanMarkCheckFunc;
|
||||
CDeltaJit::~CDeltaJit() {
|
||||
if (cleanMarkCheckFunc) {
|
||||
delete cleanMarkCheckFunc;
|
||||
cleanMarkCheckFunc = NULL;
|
||||
}
|
||||
|
||||
virtual ~CDeltaJit() {
|
||||
if (cleanMarkCheckFunc) {
|
||||
delete cleanMarkCheckFunc;
|
||||
cleanMarkCheckFunc = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
CDeltaJitRegistry::CDeltaJitRegistry() {
|
||||
|
||||
@ -365,26 +451,56 @@ void CDeltaJitRegistry::CreateAndRegisterDeltaJIT(delta_t* delta) {
|
||||
RegisterDeltaJit(delta, deltaJit);
|
||||
}
|
||||
|
||||
NOINLINE void DELTAJit_ClearAndMarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields) {
|
||||
CDeltaJit* DELTAJit_LookupDeltaJit(const char* callsite, delta_t *pFields) {
|
||||
CDeltaJit* deltaJit = g_DeltaJitRegistry.GetJITByDelta(pFields);
|
||||
if (!deltaJit) {
|
||||
rehlds_syserror("%s: JITted delta encoder not found for delta %p", __FUNCTION__, pFields);
|
||||
return;
|
||||
rehlds_syserror("%s: JITted delta encoder not found for delta %p", callsite, pFields);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CDeltaClearMarkFieldsJIT &func = *deltaJit->cleanMarkCheckFunc;
|
||||
func(from, to, pFields);
|
||||
return deltaJit;
|
||||
}
|
||||
|
||||
NOINLINE int DELTAJit_Feilds_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields) {
|
||||
CDeltaJit* deltaJit = g_DeltaJitRegistry.GetJITByDelta(pFields);
|
||||
if (!deltaJit) {
|
||||
rehlds_syserror("%s: JITted delta encoder not found for delta %p", __FUNCTION__, pFields);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NOINLINE int DELTAJit_Fields_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields) {
|
||||
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
|
||||
CDeltaClearMarkFieldsJIT &func = *deltaJit->cleanMarkCheckFunc;
|
||||
return func(from, to, pFields);
|
||||
return func(from, to, deltaJit);
|
||||
}
|
||||
|
||||
void DELTAJit_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount) {
|
||||
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
|
||||
|
||||
bits[0] = deltaJit->marked_fields_mask[0];
|
||||
bits[1] = deltaJit->marked_fields_mask[1];
|
||||
*bytecount = deltaJit->markedFieldsMaskSize;
|
||||
}
|
||||
|
||||
void DELTAJit_SetFieldByIndex(struct delta_s *pFields, int fieldNumber) {
|
||||
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
|
||||
|
||||
if (fieldNumber > 31)
|
||||
deltaJit->marked_fields_mask[1] |= (1 << (fieldNumber & 0x1F));
|
||||
else
|
||||
deltaJit->marked_fields_mask[0] |= (1 << fieldNumber);
|
||||
|
||||
}
|
||||
|
||||
void DELTAJit_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber) {
|
||||
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
|
||||
|
||||
if (fieldNumber > 31)
|
||||
deltaJit->marked_fields_mask[1] &= ~(1 << (fieldNumber & 0x1F));
|
||||
else
|
||||
deltaJit->marked_fields_mask[0] &= ~(1 << fieldNumber);
|
||||
}
|
||||
|
||||
qboolean DELTAJit_IsFieldMarked(delta_t* pFields, int fieldNumber) {
|
||||
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
|
||||
|
||||
if (fieldNumber > 31)
|
||||
return deltaJit->marked_fields_mask[1] & (1 << (fieldNumber & 0x1F));
|
||||
|
||||
return deltaJit->marked_fields_mask[0] & (1 << fieldNumber);
|
||||
}
|
||||
|
||||
void CDeltaJitRegistry::Cleanup() {
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "maintypes.h"
|
||||
|
||||
#define DELTAJIT_MAX_BLOCKS 32
|
||||
#define DELTAJIT_MAX_FIELDS 96
|
||||
#define DELTAJIT_MAX_FIELDS 56
|
||||
|
||||
struct deltajit_field {
|
||||
unsigned int id;
|
||||
@ -23,6 +23,7 @@ struct deltajit_memblock_field {
|
||||
struct deltajit_memblock {
|
||||
unsigned int numFields;
|
||||
deltajit_memblock_field fields[24];
|
||||
bool isEmpty() const;
|
||||
};
|
||||
|
||||
struct deltajitdata_t {
|
||||
@ -57,5 +58,8 @@ public:
|
||||
|
||||
extern CDeltaJitRegistry g_DeltaJitRegistry;
|
||||
|
||||
extern void DELTAJit_ClearAndMarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
extern int DELTAJit_Feilds_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
extern int DELTAJit_Fields_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields);
|
||||
extern void DELTAJit_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount);
|
||||
extern void DELTAJit_SetFieldByIndex(struct delta_s *pFields, int fieldNumber);
|
||||
extern void DELTAJit_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber);
|
||||
extern qboolean DELTAJit_IsFieldMarked(delta_t* pFields, int fieldNumber);
|
@ -1387,11 +1387,17 @@ void SV_WriteClientdataToMessage(client_t *client, sizebuf_t *msg)
|
||||
else
|
||||
fdata = &host_client->frames[bits].weapondata[i];
|
||||
|
||||
if (DELTA_CheckDelta((byte *)fdata, (byte *)tdata, (delta_t *)g_pweapondelta))
|
||||
if (DELTA_CheckDelta((byte *)fdata, (byte *)tdata, g_pweapondelta))
|
||||
{
|
||||
MSG_WriteBits(1, 1);
|
||||
MSG_WriteBits(i, 6);
|
||||
DELTA_WriteDelta((byte *)fdata, (byte *)tdata, TRUE, (delta_t *)g_pweapondelta, NULL);
|
||||
|
||||
#if defined (REHLDS_OPT_PEDANTIC) || defined (REHLDS_FIXES)
|
||||
// all calculations are already done
|
||||
_DELTA_WriteDelta((byte *)fdata, (byte *)tdata, TRUE, g_pweapondelta, NULL, TRUE);
|
||||
#else
|
||||
DELTA_WriteDelta((byte *)fdata, (byte *)tdata, TRUE, g_pweapondelta, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,13 @@ struct delta_test_struct_t {
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct delta_res_t
|
||||
{
|
||||
qboolean sendfields;
|
||||
int bits[2];
|
||||
int bytecount;
|
||||
};
|
||||
|
||||
NOINLINE void _InitDeltaField(delta_description_t* fieldDesc, int expectedOffset, int type, const char* name, int off, short sz, int bits, float preMult, float postMult) {
|
||||
if (expectedOffset != off) {
|
||||
rehlds_syserror("%s: Expected and real offset mismatch (%d != %d)", expectedOffset, off);
|
||||
@ -52,24 +59,38 @@ NOINLINE void _FillTestDelta(delta_test_struct_t* data, char val) {
|
||||
data->wb_20 = (float)val;
|
||||
}
|
||||
|
||||
NOINLINE void _DoMarkFields(void* src, void* dst, delta_t* delta, bool useJit) {
|
||||
NOINLINE qboolean _DoMarkFields(void* src, void* dst, delta_t* delta, bool useJit) {
|
||||
qboolean sendfields;
|
||||
if (useJit) {
|
||||
DELTAJit_ClearAndMarkSendFields((unsigned char*)src, (unsigned char*)dst, delta);
|
||||
DELTA_ClearFlags(delta);
|
||||
return DELTAJit_Fields_Clear_Mark_Check((unsigned char*)src, (unsigned char*)dst, delta);
|
||||
} else {
|
||||
DELTA_ClearFlags(delta);
|
||||
DELTA_MarkSendFields((unsigned char*)src, (unsigned char*)dst, delta);
|
||||
sendfields = DELTA_CountSendFields(delta);
|
||||
}
|
||||
|
||||
return sendfields;
|
||||
}
|
||||
|
||||
NOINLINE bool _CheckFieldMarked(delta_t* delta, int fieldIdx, int usejit) {
|
||||
if (usejit) {
|
||||
return DELTAJit_IsFieldMarked(delta, fieldIdx) != 0;
|
||||
} else {
|
||||
return delta->pdd[fieldIdx].flags & FDT_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE void _EnsureFieldsChanged(const char* callsite, const char* action, bool changed, delta_t* delta, ...) {
|
||||
NOINLINE void _EnsureFieldsChanged(const char* callsite, const char* action, int usejit, bool changed, delta_t* delta, ...) {
|
||||
va_list vargs;
|
||||
va_start(vargs, delta);
|
||||
const char* fieldName = va_arg(vargs, const char*);
|
||||
while (fieldName) {
|
||||
delta_description_t* field = NULL;
|
||||
for (int i = 0; i < delta->fieldCount; i++) {
|
||||
if (!strcmp(fieldName, delta->pdd[i].fieldName)) {
|
||||
field = &delta->pdd[i];
|
||||
int idx = 0;
|
||||
for (; idx < delta->fieldCount; idx++) {
|
||||
if (!strcmp(fieldName, delta->pdd[idx].fieldName)) {
|
||||
field = &delta->pdd[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -82,7 +103,8 @@ NOINLINE void _EnsureFieldsChanged(const char* callsite, const char* action, boo
|
||||
rehlds_syserror("%s: %s: Field '%s' is marked as processed", callsite, action, fieldName);
|
||||
}
|
||||
|
||||
if ((field->flags == 1) ^ changed) {
|
||||
|
||||
if (_CheckFieldMarked(delta, idx, usejit) ^ changed) {
|
||||
rehlds_syserror("%s: %s: Field '%s' is expected to be marked", callsite, action, fieldName);
|
||||
}
|
||||
|
||||
@ -96,15 +118,38 @@ NOINLINE void _EnsureFieldsChanged(const char* callsite, const char* action, boo
|
||||
if (field->flags & 0x80)
|
||||
continue;
|
||||
|
||||
if ((field->flags == 1) ^ !changed) {
|
||||
if (_CheckFieldMarked(delta, i, usejit) ^ !changed) {
|
||||
rehlds_syserror("%s: %s: Field '%s' is expected to be unmarked", callsite, action, field->fieldName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE void _GetBitmaskAndBytecount(delta_t* delta, int* bits, int* bytecount, int usejit) {
|
||||
if (usejit) {
|
||||
DELTAJit_SetSendFlagBits(delta, bits, bytecount);
|
||||
}
|
||||
else {
|
||||
DELTA_SetSendFlagBits(delta, bits, bytecount);
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE void _CompareDeltaResults(const char* callsite, delta_res_t* def, delta_res_t* jit, int testscount)
|
||||
{
|
||||
for (int i = 0; i < testscount; i++)
|
||||
{
|
||||
if (!!def[i].sendfields != !!jit[i].sendfields)
|
||||
rehlds_syserror("%s: Test %i: !!sendfields not equals %i|%i", callsite, i, !!def[i].sendfields, !!jit[i].sendfields);
|
||||
if (memcmp(def[i].bits, jit[i].bits, 8))
|
||||
rehlds_syserror("%s: Test %i: bits not equals %p.%p|%p.%p", callsite, i, def[i].bits[0], def[i].bits[1], jit[i].bits[0], jit[i].bits[1]);
|
||||
if (def[i].bytecount != jit[i].bytecount)
|
||||
rehlds_syserror("%s: Test %i: bytecount not equal %i|%i", callsite, i, def[i].bytecount, jit[i].bytecount);
|
||||
}
|
||||
}
|
||||
|
||||
NOINLINE delta_t* _CreateTestDeltaDesc() {
|
||||
delta_test_struct_t d;
|
||||
static delta_description_t _fields[32];
|
||||
delta_test_struct_t d; d; // "use" d variable
|
||||
|
||||
_InitDeltaField(&_fields[0], 0x00, DT_BYTE, "b_00", offsetof(delta_test_struct_t, b_00), 1, 8, 1.0f, 1.0f);
|
||||
_InitDeltaField(&_fields[1], 0x01, DT_BYTE, "b_01", offsetof(delta_test_struct_t, b_01), 1, 8, 1.0f, 1.0f);
|
||||
@ -150,180 +195,225 @@ NOINLINE delta_t* _CreateTestDeltaDesc() {
|
||||
};
|
||||
|
||||
TEST(MarkFieldsTest_Simple_Primitives, Delta, 1000) {
|
||||
|
||||
delta_t* delta = _CreateTestDeltaDesc();
|
||||
|
||||
delta_test_struct_t d1;
|
||||
delta_test_struct_t d2;
|
||||
delta_res_t res[2][10];
|
||||
|
||||
memset(res[0], 0xCC, sizeof(res) / 2);
|
||||
memset(res[1], 0xDD, sizeof(res) / 2);
|
||||
|
||||
for (int usejit = 0; usejit <= 1; usejit++) {
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", true, delta, NULL);
|
||||
res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", usejit, true, delta, NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x72);
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", false, delta, NULL);
|
||||
res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", usejit, false, delta, NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.b_01 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Byte_0BlockCheck", true, delta, "b_01", NULL);
|
||||
res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Byte_0BlockCheck", usejit, true, delta, "b_01", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.b_11 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Byte_1BlockCheck", true, delta, "b_11", NULL);
|
||||
res[usejit][3].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][3].bits, &res[usejit][3].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Byte_1BlockCheck", usejit, true, delta, "b_11", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.s_02 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Short_0BlockCheck", true, delta, "s_02", NULL);
|
||||
res[usejit][4].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][4].bits, &res[usejit][4].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Short_0BlockCheck", usejit, true, delta, "s_02", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.s_12 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Short_1BlockCheck", true, delta, "s_12", NULL);
|
||||
res[usejit][5].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][5].bits, &res[usejit][5].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Short_1BlockCheck", usejit, true, delta, "s_12", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_04 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Int_0BlockCheck", true, delta, "i_04", NULL);
|
||||
res[usejit][6].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][6].bits, &res[usejit][6].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Int_0BlockCheck", usejit, true, delta, "i_04", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_14 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Int_1BlockCheck", true, delta, "i_14", NULL);
|
||||
res[usejit][7].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][7].bits, &res[usejit][7].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Int_1BlockCheck", usejit, true, delta, "i_14", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.f_08 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", true, delta, "f_08", NULL);
|
||||
res[usejit][8].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][8].bits, &res[usejit][8].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", usejit, true, delta, "f_08", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.f_18 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", true, delta, "f_18", NULL);
|
||||
res[usejit][9].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][9].bits, &res[usejit][9].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", usejit, true, delta, "f_18", NULL);
|
||||
}
|
||||
|
||||
_CompareDeltaResults(__FUNCTION__, res[0], res[1], 10);
|
||||
SV_Shutdown();
|
||||
}
|
||||
|
||||
TEST(MarkFieldsTest_InterBlock, Delta, 1000) {
|
||||
|
||||
delta_t* delta = _CreateTestDeltaDesc();
|
||||
|
||||
delta_test_struct_t d1;
|
||||
delta_test_struct_t d2;
|
||||
delta_res_t res[2][14];
|
||||
|
||||
memset(res[0], 0xCC, sizeof(res) / 2);
|
||||
memset(res[1], 0xDD, sizeof(res) / 2);
|
||||
|
||||
for (int usejit = 0; usejit <= 1; usejit++) {
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.b_4D = d2.b_52 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards", true, delta, "b_4D", "b_52", NULL);
|
||||
res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards", usejit, true, delta, "b_4D", "b_52", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.b_4D = d2.b_52 = 0;
|
||||
d2.i_4E = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards_and_val", true, delta, "b_4D", "b_52", "i_4E", NULL);
|
||||
res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards_and_val", usejit, true, delta, "b_4D", "b_52", "i_4E", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_4E = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val", true, delta, "i_4E", NULL);
|
||||
res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val", usejit, true, delta, "i_4E", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_4E &= 0xFFFFFF00;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_0b", true, delta, "i_4E", NULL);
|
||||
res[usejit][3].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][3].bits, &res[usejit][3].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_0b", usejit, true, delta, "i_4E", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_4E &= 0xFFFF00FF;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_1b", true, delta, "i_4E", NULL);
|
||||
res[usejit][4].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][4].bits, &res[usejit][4].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_1b", usejit, true, delta, "i_4E", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_4E &= 0xFF00FFFF;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_2b", true, delta, "i_4E", NULL);
|
||||
res[usejit][5].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][5].bits, &res[usejit][5].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_2b", usejit, true, delta, "i_4E", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_4E &= 0x00FFFFFF;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_3b", true, delta, "i_4E", NULL);
|
||||
res[usejit][6].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][6].bits, &res[usejit][6].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_3b", usejit, true, delta, "i_4E", NULL);
|
||||
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.b_5C = d2.b_61 = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards", true, delta, "b_5C", "b_61", NULL);
|
||||
res[usejit][7].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][7].bits, &res[usejit][7].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards", usejit, true, delta, "b_5C", "b_61", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.b_5C = d2.b_61 = 0;
|
||||
d2.i_5D = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards_and_val", true, delta, "b_5C", "b_61", "i_5D", NULL);
|
||||
res[usejit][8].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][8].bits, &res[usejit][8].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards_and_val", usejit, true, delta, "b_5C", "b_61", "i_5D", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_5D = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val", true, delta, "i_5D", NULL);
|
||||
res[usejit][9].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][9].bits, &res[usejit][9].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val", usejit, true, delta, "i_5D", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_5D &= 0xFFFFFF00;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_0b", true, delta, "i_5D", NULL);
|
||||
res[usejit][10].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][10].bits, &res[usejit][10].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_0b", usejit, true, delta, "i_5D", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_5D &= 0xFFFF00FF;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_1b", true, delta, "i_5D", NULL);
|
||||
res[usejit][11].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][11].bits, &res[usejit][11].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_1b", usejit, true, delta, "i_5D", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_5D &= 0xFF00FFFF;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_2b", true, delta, "i_5D", NULL);
|
||||
res[usejit][12].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][12].bits, &res[usejit][12].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_2b", usejit, true, delta, "i_5D", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
|
||||
d2.i_5D &= 0x00FFFFFF;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_3b", true, delta, "i_5D", NULL);
|
||||
|
||||
res[usejit][13].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][13].bits, &res[usejit][13].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_3b", usejit, true, delta, "i_5D", NULL);
|
||||
}
|
||||
|
||||
_CompareDeltaResults(__FUNCTION__, res[0], res[1], 14);
|
||||
SV_Shutdown();
|
||||
}
|
||||
|
||||
TEST(MarkFieldsTest_Strings, Delta, 1000) {
|
||||
|
||||
delta_t* delta = _CreateTestDeltaDesc();
|
||||
|
||||
delta_test_struct_t d1;
|
||||
delta_test_struct_t d2;
|
||||
delta_res_t res[2][4];
|
||||
|
||||
memset(res[0], 0xCC, sizeof(res) / 2);
|
||||
memset(res[1], 0xDD, sizeof(res) / 2);
|
||||
|
||||
for (int usejit = 0; usejit <= 1; usejit++) {
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d2.s_24[0] = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_empty", true, delta, "s_24", NULL);
|
||||
res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_empty", usejit, true, delta, "s_24", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d1.s_24[0] = 0;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_empty2", true, delta, "s_24", NULL);
|
||||
res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_empty2", usejit, true, delta, "s_24", NULL);
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d1.s_24[0] = d2.s_24[0] = 0;
|
||||
d1.s_24[1] = 'd'; d2.s_24[1] = 'e';
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_both_empty_with_garbage", true, delta, NULL);
|
||||
res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_both_empty_with_garbage", usejit, true, delta, NULL);
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d1.s_24[1] = 'C';
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_case_check", true, delta, NULL);
|
||||
res[usejit][3].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][3].bits, &res[usejit][3].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "Str_case_check", usejit, true, delta, NULL);
|
||||
}
|
||||
|
||||
_CompareDeltaResults(__FUNCTION__, res[0], res[1], 4);
|
||||
SV_Shutdown();
|
||||
}
|
||||
|
||||
@ -338,25 +428,32 @@ TEST(MarkFieldsTest_TimeWindow, Delta, 1000) {
|
||||
|
||||
delta_test_struct_t d1;
|
||||
delta_test_struct_t d2;
|
||||
delta_res_t res[2][3];
|
||||
|
||||
memset(res[0], 0xCC, sizeof(res) / 2);
|
||||
memset(res[1], 0xDD, sizeof(res) / 2);
|
||||
|
||||
for (int usejit = 0; usejit <= 1; usejit++) {
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d2.w8_1C = 0.001f; d1.w8_1C = 0.0011f;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Below_Precision", true, delta, rehds_fixes ? "w8_1C" : NULL, NULL);
|
||||
res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Below_Precision", usejit, true, delta, rehds_fixes ? "w8_1C" : NULL, NULL);
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d2.w8_1C = 0.1f; d1.w8_1C = 0.11f; //precision check, 0.11f is actually 0.10999
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision", true, delta, rehds_fixes ? "w8_1C" : NULL, NULL);
|
||||
res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision1", usejit, true, delta, rehds_fixes ? "w8_1C" : NULL, NULL);
|
||||
|
||||
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
|
||||
d2.w8_1C = 0.1f; d1.w8_1C = 0.12f;
|
||||
_DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision", true, delta, "w8_1C", NULL);
|
||||
|
||||
res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0);
|
||||
_GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit);
|
||||
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision2", usejit, true, delta, "w8_1C", NULL);
|
||||
}
|
||||
|
||||
_CompareDeltaResults(__FUNCTION__, res[0], res[1], 3);
|
||||
SV_Shutdown();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user