VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

I currently have the registers implemented as follows:

#include "headers/packed.h" //Packed type!
typedef struct PACKED //The registers!
{

//Info: with union, first low data then high data!
union
{
struct
{
#ifdef IS_BIG_ENDIAN
word EAXDUMMY;
#endif
struct
{
union
{
word AX;
struct
{
#ifndef IS_BIG_ENDIAN
byte AL;
byte AH;
#else
byte AH;
byte AL;
#endif
};
};
};
#ifndef IS_BIG_ENDIAN
word EAXDUMMY;
#endif
};
uint_32 EAX;
};

union
{
struct
{
#ifdef IS_BIG_ENDIAN
word EBXDUMMY;
#endif
struct
{
union
{
word BX;
struct
{
#ifndef IS_BIG_ENDIAN
byte BL;
byte BH;
#else
byte BH;
byte BL;
#endif
};
};
};
Show last 221 lines
			#ifndef IS_BIG_ENDIAN
word EBXDUMMY;
#endif
};
uint_32 EBX;
};

union
{
struct
{
#ifdef IS_BIG_ENDIAN
word ECXDUMMY;
#endif
struct
{
union
{
word CX;
struct
{
#ifndef IS_BIG_ENDIAN
byte CL;
byte CH;
#else
byte CH;
byte CL;
#endif
};
};
};
#ifndef IS_BIG_ENDIAN
word ECXDUMMY;
#endif
};
uint_32 ECX;
};

union
{
struct
{
#ifdef IS_BIG_ENDIAN
word EDXDUMMY;
#endif
struct
{
union
{
word DX;
struct
{
#ifndef IS_BIG_ENDIAN
byte DL;
byte DH;
#else
byte DH;
byte DL;
#endif
};
};
};
#ifndef IS_BIG_ENDIAN
word EDXDUMMY;
#endif
};
uint_32 EDX;
};

union
{
uint_32 ESP; //ESP!
struct
{
#ifdef IS_BIG_ENDIAN
word ESPDUMMY;
#endif
word SP; //Stack pointer
#ifndef IS_BIG_ENDIAN
word ESPDUMMY; //Dummy!
#endif
};
};
union
{
uint_32 EBP; //EBP!
struct
{
#ifdef IS_BIG_ENDIAN
word EBPDUMMY;
#endif
word BP; //Base pointer
#ifndef IS_BIG_ENDIAN
word EBPDUMMY; //Dummy!
#endif
};
};
union
{
uint_32 ESI; //ESI
struct
{
#ifdef IS_BIG_ENDIAN
word ESIDUMMY;
#endif
word SI; //Source index
#ifndef IS_BIG_ENDIAN
word ESIDUMMY; //Dummy!
#endif
};
};

union
{
uint_32 EDI; //EDI
struct
{
#ifdef IS_BIG_ENDIAN
word EDIDUMMY;
#endif
word DI; //Destination index
#ifndef IS_BIG_ENDIAN
word EDIDUMMY; //Dummy!
#endif
};
};

union
{
uint_32 EIP; //EIP
struct
{
#ifdef IS_BIG_ENDIAN
word EIPDUMMY;
#endif
word IP; //Instruction pointer; CS:IP=Current instruction; Reset at load of program
#ifndef IS_BIG_ENDIAN
word EIPDUMMY; //Dummy!
#endif
};
};

word CS; //Code segment: start of program code; used by instructions and jumps.
word DS; //Data segment: beginning of data storage section of memory; used by data manipulation
word ES; //Extra segment: used for operations where data is transferred from one segment to another
word SS; //Stack segment: stack segment
word FS; //???
word GS; //???

union
{
struct
{
#ifdef IS_BIG_ENDIAN
word EFLAGSDUMMY;
#endif
word FLAGS; //8086 Flags!
#ifndef IS_BIG_ENDIAN
word EFLAGSDUMMY; //Dummy!
#endif
};
uint_32 EFLAGS;
};

struct
{
//Tables:
DTR_PTR GDTR; //GDTR pointer (48-bits) Global Descriptor Table Register
DTR_PTR IDTR; //IDTR pointer (48-bits) Interrupt Descriptor Table Register
word LDTR; //LDTR pointer (16-bits) Local Descriptor Table Register (points to an index in the GDT)
word TR; //TR (16-bits) Talk Register: currently executing task (points to an index in the GDT)

union
{
uint_32 CR[8];
struct
{
uint_32 CR0;
uint_32 CR1; //Unused!
uint_32 CR2; //Page Fault Linear Address
uint_32 CR3;
uint_32 CR4; //4 unused CRs until Pentium!
uint_32 CR5;
uint_32 CR6;
uint_32 CR7;
}; //CR0-3!
}; //CR0-3!
union
{
uint_32 DR[8]; //All debugger registers! index 4=>6 and index 5=>7!
struct
{
uint_32 DR0;
uint_32 DR1;
uint_32 DR2;
uint_32 DR3;
uint_32 DR4; //Existant on Pentium+ only! Redirected to DR6 on 386+, except when enabled using CR4.
uint_32 noDRregister; //Not defined: DR5 on Pentium! Redirected to DR7 on 386+(when not disabled using CR4).
uint_32 DR6; //DR4->6 on 386+, DR6 on Pentium+!
uint_32 DR7; //DR5->7 on 386+, DR7 on Pentium+!
};
}; //DR0-7; 4=6&5=7!
union
{
uint_32 TRX[8]; //All debugger registers! index 4=>6 and index 5=>7!
struct
{
uint_32 TR0;
uint_32 TR1;
uint_32 TR2;
uint_32 TR3;
uint_32 TR4;
uint_32 TR5;
uint_32 TR6;
uint_32 TR7;
};
}; //DR0-7; 4=6&5=7!
}; //Special registers!
} CPU_registers; //Registers
#include "headers/endpacked.h" //End of packed type!

The issue with this is that with the latest (GCC 9) compiler, it complains about pretty much all of those when storing a pointer or using a pointer to it?

warning: taking address of packed member of 'struct <anonymous>' may result in an unaligned pointer value [-Waddress-of-packed-member]

Is there any way to fix this without having to change all my code in incompatible ways? How should I implement this in a cross-platform cross-compiler way?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 2 of 14, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie

In a micro interpreter I wrote for a one off thing;

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#pragma pack(1)
typedef struct udtRegister
{
union
{
struct { uint32_t ex; };
#ifndef BIG_ENDIAN
struct { uint16_t __ignore0; uint16_t x; };
struct { uint16_t __ignore1; uint8_t h; uint8_t l; };
#else
struct { uint16_t x; uint16_t __ignore0; };
struct { uint8_t l; uint8_t h; uint16_t __ignore1; };
#endif
};
} uRegister;

enum eRegs { r_AX = 0, r_CX, r_DX, r_BX, r_SP, r_BP, r_SI, r_DI, r_REGMAX };
enum eSREgs { r_CS = 0 , r_DS, r_ES, r_SS, r_FS, r_GS, r_SREGMAX };

typedef struct udtRegs
{
uRegister regs[r_REGMAX];
uint16_t sregs[r_SREGMAX];
uint32_t flags;
uint32_t ip;
} uRegs;
#pragma pack()

int main(void)
{
uRegs r;

memset(&r, 0x0, sizeof(uRegs));

r.regs[r_AX].ex = 0xDEADBEEF;

printf("eax=0x%08"PRIx32"\n", r.regs[r_AX].ex);
printf("ax=0x%08"PRIx16"\n", r.regs[r_AX].x);
printf("ah=0x%08"PRIx8"\n", r.regs[r_AX].h);
printf("al=0x%08"PRIx8"\n", r.regs[r_AX].l);

return 0;
}
bcactus@workstation.cactus:/tmp$ clang -02 x.c -o x && ./x
eax=0xdeadbeef
ax=0x0000beef
ah=0x000000be
al=0x000000ef

--/\-[ Stu : Bloody Cactus :: [ https://bloodycactus.com :: http://kråketær.com ]-/\--

Reply 3 of 14, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've changed it a bit in the meantime(I didn't see any replies when I started. Took me all day to adjust all references througout the emulator):

//General Purpose register support!

#include "headers/packed.h"
typedef struct PACKED
{
uint_32 reg32;
word reg16[2];
byte reg8[4];
} registersplitter;
#include "headers/endpacked.h"

#ifdef IS_BIG_ENDIAN
#define GPREG16_LO 1
#define GPREG8_LO 1
#define GPREG8_HI 0
#else
#define GPREG16_LO 0
#define GPREG8_LO 0
#define GPREG8_HI 1
#endif

enum
{
GPREG_EAX = 0,
GPREG_EBX = 1,
GPREG_ECX = 2,
GPREG_EDX = 3,
GPREG_ESP = 4,
GPREG_EBP = 5,
GPREG_ESI = 6,
GPREG_EDI = 7,
GPREG_EIP = 8,
GPREG_EFLAGS = 9
}; //All general purpose registers locations in the list!

//Short versions of the registers allocated with the above values as input!
#define REG8_LO(reg) CPU[activeCPU].registers->gpregisters[reg].reg8[GPREG8_LO]
#define REG8_HI(reg) CPU[activeCPU].registers->gpregisters[reg].reg8[GPREG8_HI]
#define REG16_LO(reg) CPU[activeCPU].registers->gpregisters[reg].reg16[GPREG16_LO]
#define REG32(reg) CPU[activeCPU].registers->gpregisters[reg].reg32
//Registers version:
#define REG8R_LO(list,reg) list->gpregisters[reg].reg8[GPREG8_LO]
#define REG8R_HI(list,reg) list->gpregisters[reg].reg8[GPREG8_HI]
#define REG16R_LO(list,reg) list->gpregisters[reg].reg16[GPREG16_LO]
#define REG32R(list,reg) list->gpregisters[reg].reg32
//Direct version:
#define REG8D_LO(list,reg) list.gpregisters[reg].reg8[GPREG8_LO]
#define REG8D_HI(list,reg) list.gpregisters[reg].reg8[GPREG8_HI]
#define REG16D_LO(list,reg) list.gpregisters[reg].reg16[GPREG16_LO]
#define REG32D(list,reg) list.gpregisters[reg].reg32

#define REGR_AL(list) REG8R_LO(list,GPREG_EAX)
#define REGR_AH(list) REG8R_HI(list,GPREG_EAX)
#define REGR_AX(list) REG16R_LO(list,GPREG_EAX)
#define REGR_EAX(list) REG32R(list,GPREG_EAX)
#define REGR_BL(list) REG8R_LO(list,GPREG_EBX)
#define REGR_BH(list) REG8R_HI(list,GPREG_EBX)
#define REGR_BX(list) REG16R_LO(list,GPREG_EBX)
#define REGR_EBX(list) REG32R(list,GPREG_EBX)
#define REGR_CL(list) REG8R_LO(list,GPREG_ECX)
Show last 50 lines
#define REGR_CH(list) REG8R_HI(list,GPREG_ECX)
#define REGR_CX(list) REG16R_LO(list,GPREG_ECX)
#define REGR_ECX(list) REG32R(list,GPREG_ECX)
#define REGR_DL(list) REG8R_LO(list,GPREG_EDX)
#define REGR_DH(list) REG8R_HI(list,GPREG_EDX)
#define REGR_DX(list) REG16R_LO(list,GPREG_EDX)
#define REGR_EDX(list) REG32R(list,GPREG_EDX)
#define REGR_SP(list) REG16R_LO(list,GPREG_ESP)
#define REGR_ESP(list) REG32R(list,GPREG_ESP)
#define REGR_BP(list) REG16R_LO(list,GPREG_EBP)
#define REGR_EBP(list) REG32R(list,GPREG_EBP)
#define REGR_SI(list) REG16R_LO(list,GPREG_ESI)
#define REGR_ESI(list) REG32R(list,GPREG_ESI)
#define REGR_DI(list) REG16R_LO(list,GPREG_EDI)
#define REGR_EDI(list) REG32R(list,GPREG_EDI)
#define REGR_IP(list) REG16R_LO(list,GPREG_EIP)
#define REGR_EIP(list) REG32R(list,GPREG_EIP)
#define REGR_FLAGS(list) REG16R_LO(list,GPREG_EFLAGS)
#define REGR_EFLAGS(list) REG32R(list,GPREG_EFLAGS)

//Direct version
#define REGD_AL(list) REG8D_LO(list,GPREG_EAX)
#define REGD_AH(list) REG8D_HI(list,GPREG_EAX)
#define REGD_AX(list) REG16D_LO(list,GPREG_EAX)
#define REGD_EAX(list) REG32D(list,GPREG_EAX)
#define REGD_BL(list) REG8D_LO(list,GPREG_EBX)
#define REGD_BH(list) REG8D_HI(list,GPREG_EBX)
#define REGD_BX(list) REG16D_LO(list,GPREG_EBX)
#define REGD_EBX(list) REG32D(list,GPREG_EBX)
#define REGD_CL(list) REG8D_LO(list,GPREG_ECX)
#define REGD_CH(list) REG8D_HI(list,GPREG_ECX)
#define REGD_CX(list) REG16D_LO(list,GPREG_ECX)
#define REGD_ECX(list) REG32D(list,GPREG_ECX)
#define REGD_DL(list) REG8D_LO(list,GPREG_EDX)
#define REGD_DH(list) REG8D_HI(list,GPREG_EDX)
#define REGD_DX(list) REG16D_LO(list,GPREG_EDX)
#define REGD_EDX(list) REG32D(list,GPREG_EDX)
#define REGD_SP(list) REG16D_LO(list,GPREG_ESP)
#define REGD_ESP(list) REG32D(list,GPREG_ESP)
#define REGD_BP(list) REG16D_LO(list,GPREG_EBP)
#define REGD_EBP(list) REG32D(list,GPREG_EBP)
#define REGD_SI(list) REG16D_LO(list,GPREG_ESI)
#define REGD_ESI(list) REG32D(list,GPREG_ESI)
#define REGD_DI(list) REG16D_LO(list,GPREG_EDI)
#define REGD_EDI(list) REG32D(list,GPREG_EDI)
#define REGD_IP(list) REG16D_LO(list,GPREG_EIP)
#define REGD_EIP(list) REG32D(list,GPREG_EIP)
#define REGD_FLAGS(list) REG16D_LO(list,GPREG_EFLAGS)
#define REGD_EFLAGS(list) REG32D(list,GPREG_EFLAGS)

Actual registers in the CPU:

#include "headers/packed.h" //Packed type!
typedef struct PACKED //The registers!
{
//First, the General Purpose registers!
registersplitter gpregisters[10]; //10 general purpose registers! EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI, EIP, EFLAGS!
//Info: with union, first low data then high data!

word CS; //Code segment: start of program code; used by instructions and jumps.
word DS; //Data segment: beginning of data storage section of memory; used by data manipulation
word ES; //Extra segment: used for operations where data is transferred from one segment to another
word SS; //Stack segment: stack segment
word FS; //???
word GS; //???

struct
{
//Tables:
DTR_PTR GDTR; //GDTR pointer (48-bits) Global Descriptor Table Register
DTR_PTR IDTR; //IDTR pointer (48-bits) Interrupt Descriptor Table Register
word LDTR; //LDTR pointer (16-bits) Local Descriptor Table Register (points to an index in the GDT)
word TR; //TR (16-bits) Talk Register: currently executing task (points to an index in the GDT)

union
{
uint_32 CR[8];
struct
{
uint_32 CR0;
uint_32 CR1; //Unused!
uint_32 CR2; //Page Fault Linear Address
uint_32 CR3;
uint_32 CR4; //4 unused CRs until Pentium!
uint_32 CR5;
uint_32 CR6;
uint_32 CR7;
}; //CR0-3!
}; //CR0-3!
union
{
uint_32 DR[8]; //All debugger registers! index 4=>6 and index 5=>7!
struct
{
uint_32 DR0;
uint_32 DR1;
uint_32 DR2;
uint_32 DR3;
uint_32 DR4; //Existant on Pentium+ only! Redirected to DR6 on 386+, except when enabled using CR4.
uint_32 noDRregister; //Not defined: DR5 on Pentium! Redirected to DR7 on 386+(when not disabled using CR4).
uint_32 DR6; //DR4->6 on 386+, DR6 on Pentium+!
uint_32 DR7; //DR5->7 on 386+, DR7 on Pentium+!
};
}; //DR0-7; 4=6&5=7!
union
{
uint_32 TRX[8]; //All debugger registers! index 4=>6 and index 5=>7!
struct
{
uint_32 TR0;
uint_32 TR1;
uint_32 TR2;
Show last 11 lines
				uint_32 TR3;
uint_32 TR4;
uint_32 TR5;
uint_32 TR6;
uint_32 TR7;
};
}; //DR0-7; 4=6&5=7!
}; //Special registers!
} CPU_registers; //Registers
#include "headers/endpacked.h" //End of packed type!

In the easyregs.h (which is now used in all possible cases, instead of addressing the registers directly):

//Accumulator register:
#define REG_AL REG8_LO(GPREG_EAX)
#define REG_AH REG8_HI(GPREG_EAX)
#define REG_EAX REG32(GPREG_EAX)
#define REG_AX REG16_LO(GPREG_EAX)

//Base register:
#define REG_BL REG8_LO(GPREG_EBX)
#define REG_BH REG8_HI(GPREG_EBX)
#define REG_EBX REG32(GPREG_EBX)
#define REG_BX REG16_LO(GPREG_EBX)

//Counter register:
#define REG_CL REG8_LO(GPREG_ECX)
#define REG_CH REG8_HI(GPREG_ECX)
#define REG_ECX REG32(GPREG_ECX)
#define REG_CX REG16_LO(GPREG_ECX)

//Data register:
#define REG_DL REG8_LO(GPREG_EDX)
#define REG_DH REG8_HI(GPREG_EDX)
#define REG_EDX REG32(GPREG_EDX)
#define REG_DX REG16_LO(GPREG_EDX)

//Segment registers
#define REG_CS CPU[activeCPU].registers->CS
#define REG_DS CPU[activeCPU].registers->DS
#define REG_ES CPU[activeCPU].registers->ES
#define REG_FS CPU[activeCPU].registers->FS
#define REG_GS CPU[activeCPU].registers->GS
#define REG_SS CPU[activeCPU].registers->SS

//Indexes and pointers
#define REG_EDI REG32(GPREG_EDI)
#define REG_DI REG16_LO(GPREG_EDI)
#define REG_ESI REG32(GPREG_ESI)
#define REG_SI REG16_LO(GPREG_ESI)
#define REG_EBP REG32(GPREG_EBP)
#define REG_BP REG16_LO(GPREG_EBP)
#define REG_ESP REG32(GPREG_ESP)
#define REG_SP REG16_LO(GPREG_ESP)
#define REG_EIP REG32(GPREG_EIP)
#define REG_IP REG16_LO(GPREG_EIP)
#define REG_EFLAGS REG32(GPREG_EFLAGS)
#define REG_FLAGS REG16_LO(GPREG_EFLAGS)

Also, the packed part is to make it not add padding to each of the byte/word registers. That would cause trouble when using it?

For some reason, this 'improvement' seems to have prevented the Pentium emulation to post (at least until the screen is setup)? POST code is 0x13 on the Compaq Deskpro 386 BIOS.

Edit: Whoops.

#include "headers/packed.h"
typedef union PACKED
{
uint_32 reg32;
word reg16[2];
byte reg8[4];
} registersplitter;
#include "headers/endpacked.h"

That needed to be a union to keep working. A struct makes all *X/*L/*H/FLAGS/IP not sharing bits with their 16/32-bit counterparts.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 4 of 14, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

Also, the packed part is to make it not add padding to each of the byte/word registers. That would cause trouble when using it?

Padding is only added when a member doesn't fall on a boundary that is a multiple of its size. Where do you see that happening?

Reply 5 of 14, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've adjusted to be as follows(for all registers but the CRn/TRn/DRn/GDTR/LDTR registers:

typedef union
{
uint_32 reg32;
word reg16[2];
byte reg8[4];
} registersplitter;

Won't that cause issues with different architectures and (data?) bus widths? Like alignment?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 6 of 14, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

Not as long as the types are properly defined to the correct widths...
It does seem a bit strange to have one type with the size in the name (uint_32), a very vaguely named "word" type and byte which is always 8-bits but isn't called uint_8. What is wrong with just using the stdint.h types?

Reply 7 of 14, by superfury

User metadata
Rank l33t++
Rank
l33t++

Also just fixed the 80286 and 80386&80486 LOADALL instruction buffers (for their data loaded from memory to load into the register and descriptor states) to no longer use the packed attribute. The compiler was also complaining about those (when loading them from memory and passing the 16-bit/32-bit item array as a pointer from a packed union).

@jmarsh: The word type and byte type are aliases (using typedef) of the uint16_t and uint8_t types in the general header.

So(from the common emulator framework headers/types.h):

typedef uint8_t byte;
typedef uint16_t word;
typedef int8_t sbyte; //Signed!
typedef int16_t sword; //Signed!

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 8 of 14, by superfury

User metadata
Rank l33t++
Rank
l33t++

I'm wondering though... Won't natural alignment on different processors cause issues with those buffers of LOADALL? Like aligning the word values on 32-bit alignment? That would cause the whole LOADALL structure to malfunction loading it's data into the register/descriptor states(every other variable being cleared)?

The naming of the byte and word types probably still comes from the first programming language I've used(Turbo Pascal 6.0 until I switched to C for PSP, then Windows, then Android software).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 9 of 14, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

C guarantees the alignment of a type matches its size (at least for sizes up to the platform's natural word size).

If you have a struct that has a uint16_t member followed by a uint32_t, padding is required to align the latter. The alignment of the struct overall will also be equal to the alignment of its largest member i.e. 4 bytes.

Reply 10 of 14, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:
So(from the common emulator framework headers/types.h): […]
Show full quote

So(from the common emulator framework headers/types.h):

typedef uint8_t byte;
typedef uint16_t word;
typedef int8_t sbyte; //Signed!
typedef int16_t sword; //Signed!

I consider that confusing and obsfucated. Just use <stdint.h> and <inttypes.h> and stick to uint16_t / int16_t etc.

--/\-[ Stu : Bloody Cactus :: [ https://bloodycactus.com :: http://kråketær.com ]-/\--

Reply 11 of 14, by superfury

User metadata
Rank l33t++
Rank
l33t++

How is that confusing and obfuscated? The Intel syntax assembly language uses those very same terms (byte, word, dword ptr)? I simply prefixed a 's' for their signed versions. Altbough 32-bit/64-bit variables are an exception(uint_32, int_32, uint_64, int_64).

Those 8/16-bit versions basically have their roots in me originally starting to programming in pascal, which uses byte and word(as does assembly). Those two I still use throughout my projects (to me, actually using uint8_t and uint16_t everywhere is the strange thing). And when you talk about a byte or (double)word value, everyone that knows software knows what you're talking about, don't they?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 12 of 14, by superfury

User metadata
Rank l33t++
Rank
l33t++
jmarsh wrote:

C guarantees the alignment of a type matches its size (at least for sizes up to the platform's natural word size).

If you have a struct that has a uint16_t member followed by a uint32_t, padding is required to align the latter. The alignment of the struct overall will also be equal to the alignment of its largest member i.e. 4 bytes.

In that case it's good I still have the packed attribute available on the app. Imagine a 48-bit pointer(IDTR/GDTR) being aligned to 32-bit but loaded as 3 16-bit offsets during LIDT/LGDT). Or the byte/word interleaved segment descriptor format(already stripped the bitfields out everywhere due to incompatibility).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 13 of 14, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie
BloodyCactus wrote:

I consider that confusing and obsfucated. Just use <stdint.h> and <inttypes.h> and stick to uint16_t / int16_t etc.

Completely agree, they are the "standard" types for a reason.

superfury wrote:

when you talk about a byte or (double)word value, everyone that knows software knows what you're talking about, don't they?

No.
Is a "byte" signed or unsigned?
A "word" is a generic term for a multibyte value. Is it 2 bytes? 4 bytes? 8 bytes? It makes sense if you also use dword, oword etc. to differentiate the sizes but you're not doing that.

superfury wrote:

In that case it's good I still have the packed attribute available on the app.

Sure if you insist on defining far pointers as structs, but you don't need it for register definitions because there's no padding required.

Reply 14 of 14, by BloodyCactus

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

How is that confusing and obfuscated? The Intel syntax assembly language uses those very same terms (byte, word, dword ptr)? I simply prefixed a 's' for their signed versions. Altbough 32-bit/64-bit variables are an exception(uint_32, int_32, uint_64, int_64).

to me, your writing C, not Assembler. Use C conventions, the c library gives you those in stdint.h + inttypes.h
but obviously, use whatever its your app.

--/\-[ Stu : Bloody Cactus :: [ https://bloodycactus.com :: http://kråketær.com ]-/\--