feat: multi-user system, bug fixes, security & performance fixes, and more
This commit is contained in:
@@ -36,11 +36,19 @@ namespace Montauk {
|
|||||||
auto* proc = Sched::GetCurrentProcessPtr();
|
auto* proc = Sched::GetCurrentProcessPtr();
|
||||||
if (proc == nullptr) return 0;
|
if (proc == nullptr) return 0;
|
||||||
|
|
||||||
|
// Guard against overflow before rounding
|
||||||
|
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
||||||
|
if (size > 0xFFFFFFFFFFFF0000ULL) return 0;
|
||||||
|
|
||||||
// Round up to page boundary
|
// Round up to page boundary
|
||||||
size = (size + 0xFFF) & ~0xFFFULL;
|
size = (size + 0xFFF) & ~0xFFFULL;
|
||||||
if (size == 0) size = 0x1000;
|
if (size == 0) size = 0x1000;
|
||||||
|
|
||||||
uint64_t userVa = proc->heapNext;
|
uint64_t userVa = proc->heapNext;
|
||||||
|
|
||||||
|
// Ensure allocation stays within user address space
|
||||||
|
if (userVa + size < userVa || userVa + size > USER_SPACE_END) return 0;
|
||||||
|
|
||||||
uint64_t numPages = size / 0x1000;
|
uint64_t numPages = size / 0x1000;
|
||||||
|
|
||||||
// Allocate physical pages and map them into the process
|
// Allocate physical pages and map them into the process
|
||||||
|
|||||||
@@ -38,6 +38,23 @@ extern "C" void SyscallEntry();
|
|||||||
|
|
||||||
namespace Montauk {
|
namespace Montauk {
|
||||||
|
|
||||||
|
// ---- User pointer validation ----
|
||||||
|
// Reject pointers that fall in the kernel-half of the address space
|
||||||
|
// (canonical high addresses, i.e. >= 0x0000800000000000).
|
||||||
|
// This prevents userspace from tricking the kernel into reading/writing
|
||||||
|
// kernel memory via syscall arguments.
|
||||||
|
|
||||||
|
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
||||||
|
|
||||||
|
static bool IsUserPtr(uint64_t addr) {
|
||||||
|
return addr == 0 || addr < USER_SPACE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that a pointer is non-null and in user space
|
||||||
|
static bool ValidUserPtr(uint64_t addr) {
|
||||||
|
return addr != 0 && addr < USER_SPACE_END;
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Dispatch ----
|
// ---- Dispatch ----
|
||||||
|
|
||||||
extern "C" int64_t SyscallDispatch(SyscallFrame* frame) {
|
extern "C" int64_t SyscallDispatch(SyscallFrame* frame) {
|
||||||
@@ -59,14 +76,17 @@ namespace Montauk {
|
|||||||
case SYS_GETPID:
|
case SYS_GETPID:
|
||||||
return (int64_t)Sys_GetPid();
|
return (int64_t)Sys_GetPid();
|
||||||
case SYS_PRINT:
|
case SYS_PRINT:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_Print((const char*)frame->arg1);
|
Sys_Print((const char*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_PUTCHAR:
|
case SYS_PUTCHAR:
|
||||||
Sys_Putchar((char)frame->arg1);
|
Sys_Putchar((char)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_OPEN:
|
case SYS_OPEN:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_Open((const char*)frame->arg1);
|
return (int64_t)Sys_Open((const char*)frame->arg1);
|
||||||
case SYS_READ:
|
case SYS_READ:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2,
|
return (int64_t)Sys_Read((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||||
frame->arg3, frame->arg4);
|
frame->arg3, frame->arg4);
|
||||||
case SYS_GETSIZE:
|
case SYS_GETSIZE:
|
||||||
@@ -75,6 +95,7 @@ namespace Montauk {
|
|||||||
Sys_Close((int)frame->arg1);
|
Sys_Close((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_READDIR:
|
case SYS_READDIR:
|
||||||
|
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_ReadDir((const char*)frame->arg1,
|
return (int64_t)Sys_ReadDir((const char*)frame->arg1,
|
||||||
(const char**)frame->arg2,
|
(const char**)frame->arg2,
|
||||||
(int)frame->arg3);
|
(int)frame->arg3);
|
||||||
@@ -88,11 +109,13 @@ namespace Montauk {
|
|||||||
case SYS_GETMILLISECONDS:
|
case SYS_GETMILLISECONDS:
|
||||||
return (int64_t)Sys_GetMilliseconds();
|
return (int64_t)Sys_GetMilliseconds();
|
||||||
case SYS_GETINFO:
|
case SYS_GETINFO:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_GetInfo((SysInfo*)frame->arg1);
|
Sys_GetInfo((SysInfo*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_ISKEYAVAILABLE:
|
case SYS_ISKEYAVAILABLE:
|
||||||
return (int64_t)Sys_IsKeyAvailable();
|
return (int64_t)Sys_IsKeyAvailable();
|
||||||
case SYS_GETKEY:
|
case SYS_GETKEY:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_GetKey((KeyEvent*)frame->arg1);
|
Sys_GetKey((KeyEvent*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_GETCHAR:
|
case SYS_GETCHAR:
|
||||||
@@ -100,11 +123,14 @@ namespace Montauk {
|
|||||||
case SYS_PING:
|
case SYS_PING:
|
||||||
return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2);
|
return (int64_t)Sys_Ping((uint32_t)frame->arg1, (uint32_t)frame->arg2);
|
||||||
case SYS_SPAWN:
|
case SYS_SPAWN:
|
||||||
return (int64_t)Sys_Spawn((const char*)frame->arg1, (const char*)frame->arg2);
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
|
return (int64_t)Sys_Spawn((const char*)frame->arg1,
|
||||||
|
IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
||||||
case SYS_WAITPID:
|
case SYS_WAITPID:
|
||||||
Sys_WaitPid((int)frame->arg1);
|
Sys_WaitPid((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_FBINFO:
|
case SYS_FBINFO:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_FbInfo((FbInfo*)frame->arg1);
|
Sys_FbInfo((FbInfo*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_FBMAP:
|
case SYS_FBMAP:
|
||||||
@@ -112,6 +138,7 @@ namespace Montauk {
|
|||||||
case SYS_TERMSIZE:
|
case SYS_TERMSIZE:
|
||||||
return (int64_t)Sys_TermSize();
|
return (int64_t)Sys_TermSize();
|
||||||
case SYS_GETARGS:
|
case SYS_GETARGS:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2);
|
return (int64_t)Sys_GetArgs((char*)frame->arg1, frame->arg2);
|
||||||
case SYS_RESET:
|
case SYS_RESET:
|
||||||
Sys_Reset();
|
Sys_Reset();
|
||||||
@@ -120,6 +147,7 @@ namespace Montauk {
|
|||||||
Sys_Shutdown();
|
Sys_Shutdown();
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_GETTIME:
|
case SYS_GETTIME:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_GetTime((DateTime*)frame->arg1);
|
Sys_GetTime((DateTime*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SOCKET:
|
case SYS_SOCKET:
|
||||||
@@ -133,61 +161,83 @@ namespace Montauk {
|
|||||||
case SYS_ACCEPT:
|
case SYS_ACCEPT:
|
||||||
return (int64_t)Sys_Accept((int)frame->arg1);
|
return (int64_t)Sys_Accept((int)frame->arg1);
|
||||||
case SYS_SEND:
|
case SYS_SEND:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
return (int64_t)Sys_Send((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_RECV:
|
case SYS_RECV:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_Recv((int)frame->arg1, (uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
return (int64_t)Sys_Recv((int)frame->arg1, (uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_CLOSESOCK:
|
case SYS_CLOSESOCK:
|
||||||
Sys_CloseSock((int)frame->arg1);
|
Sys_CloseSock((int)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_GETNETCFG:
|
case SYS_GETNETCFG:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_GetNetCfg((NetCfg*)frame->arg1);
|
Sys_GetNetCfg((NetCfg*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SETNETCFG:
|
case SYS_SETNETCFG:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1);
|
return (int64_t)Sys_SetNetCfg((const NetCfg*)frame->arg1);
|
||||||
case SYS_SENDTO:
|
case SYS_SENDTO:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_SendTo((int)frame->arg1, (const uint8_t*)frame->arg2,
|
return (int64_t)Sys_SendTo((int)frame->arg1, (const uint8_t*)frame->arg2,
|
||||||
(uint32_t)frame->arg3, (uint32_t)frame->arg4,
|
(uint32_t)frame->arg3, (uint32_t)frame->arg4,
|
||||||
(uint16_t)frame->arg5);
|
(uint16_t)frame->arg5);
|
||||||
case SYS_RECVFROM:
|
case SYS_RECVFROM:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2,
|
return (int64_t)Sys_RecvFrom((int)frame->arg1, (uint8_t*)frame->arg2,
|
||||||
(uint32_t)frame->arg3, (uint32_t*)frame->arg4,
|
(uint32_t)frame->arg3,
|
||||||
(uint16_t*)frame->arg5);
|
IsUserPtr(frame->arg4) ? (uint32_t*)frame->arg4 : nullptr,
|
||||||
|
IsUserPtr(frame->arg5) ? (uint16_t*)frame->arg5 : nullptr);
|
||||||
case SYS_FWRITE:
|
case SYS_FWRITE:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2,
|
return (int64_t)Sys_FWrite((int)frame->arg1, (const uint8_t*)frame->arg2,
|
||||||
frame->arg3, frame->arg4);
|
frame->arg3, frame->arg4);
|
||||||
case SYS_FCREATE:
|
case SYS_FCREATE:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_FCreate((const char*)frame->arg1);
|
return (int64_t)Sys_FCreate((const char*)frame->arg1);
|
||||||
case SYS_FDELETE:
|
case SYS_FDELETE:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_FDelete((const char*)frame->arg1);
|
return (int64_t)Sys_FDelete((const char*)frame->arg1);
|
||||||
case SYS_FMKDIR:
|
case SYS_FMKDIR:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_FMkdir((const char*)frame->arg1);
|
return (int64_t)Sys_FMkdir((const char*)frame->arg1);
|
||||||
case SYS_DRIVELIST:
|
case SYS_DRIVELIST:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_TERMSCALE:
|
case SYS_TERMSCALE:
|
||||||
return Sys_TermScale(frame->arg1, frame->arg2);
|
return Sys_TermScale(frame->arg1, frame->arg2);
|
||||||
case SYS_RESOLVE:
|
case SYS_RESOLVE:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_Resolve((const char*)frame->arg1);
|
return Sys_Resolve((const char*)frame->arg1);
|
||||||
case SYS_GETRANDOM:
|
case SYS_GETRANDOM:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2);
|
return Sys_GetRandom((uint8_t*)frame->arg1, frame->arg2);
|
||||||
case SYS_KLOG:
|
case SYS_KLOG:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Kt::ReadKernelLog((char*)frame->arg1, frame->arg2);
|
return Kt::ReadKernelLog((char*)frame->arg1, frame->arg2);
|
||||||
case SYS_MOUSESTATE:
|
case SYS_MOUSESTATE:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_MouseState((MouseState*)frame->arg1);
|
Sys_MouseState((MouseState*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SETMOUSEBOUNDS:
|
case SYS_SETMOUSEBOUNDS:
|
||||||
Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2);
|
Sys_SetMouseBounds((int32_t)frame->arg1, (int32_t)frame->arg2);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_SPAWN_REDIR:
|
case SYS_SPAWN_REDIR:
|
||||||
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1, (const char*)frame->arg2);
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
|
return (int64_t)Sys_SpawnRedir((const char*)frame->arg1,
|
||||||
|
IsUserPtr(frame->arg2) ? (const char*)frame->arg2 : nullptr);
|
||||||
case SYS_CHILDIO_READ:
|
case SYS_CHILDIO_READ:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_ChildIoRead((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_CHILDIO_WRITE:
|
case SYS_CHILDIO_WRITE:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_ChildIoWrite((int)frame->arg1, (const char*)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_CHILDIO_WRITEKEY:
|
case SYS_CHILDIO_WRITEKEY:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_ChildIoWriteKey((int)frame->arg1, (const KeyEvent*)frame->arg2);
|
return (int64_t)Sys_ChildIoWriteKey((int)frame->arg1, (const KeyEvent*)frame->arg2);
|
||||||
case SYS_CHILDIO_SETTERMSZ:
|
case SYS_CHILDIO_SETTERMSZ:
|
||||||
return (int64_t)Sys_ChildIoSetTermsz((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_ChildIoSetTermsz((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_WINCREATE:
|
case SYS_WINCREATE:
|
||||||
|
if (!ValidUserPtr(frame->arg1) || !ValidUserPtr(frame->arg4)) return -1;
|
||||||
return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2,
|
return (int64_t)Sys_WinCreate((const char*)frame->arg1, (int)frame->arg2,
|
||||||
(int)frame->arg3, (WinCreateResult*)frame->arg4);
|
(int)frame->arg3, (WinCreateResult*)frame->arg4);
|
||||||
case SYS_WINDESTROY:
|
case SYS_WINDESTROY:
|
||||||
@@ -195,16 +245,20 @@ namespace Montauk {
|
|||||||
case SYS_WINPRESENT:
|
case SYS_WINPRESENT:
|
||||||
return (int64_t)Sys_WinPresent((int)frame->arg1);
|
return (int64_t)Sys_WinPresent((int)frame->arg1);
|
||||||
case SYS_WINPOLL:
|
case SYS_WINPOLL:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2);
|
return (int64_t)Sys_WinPoll((int)frame->arg1, (WinEvent*)frame->arg2);
|
||||||
case SYS_WINENUM:
|
case SYS_WINENUM:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_WinEnum((WinInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_WINMAP:
|
case SYS_WINMAP:
|
||||||
return (int64_t)Sys_WinMap((int)frame->arg1);
|
return (int64_t)Sys_WinMap((int)frame->arg1);
|
||||||
case SYS_WINSENDEVENT:
|
case SYS_WINSENDEVENT:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return (int64_t)Sys_WinSendEvent((int)frame->arg1, (const WinEvent*)frame->arg2);
|
return (int64_t)Sys_WinSendEvent((int)frame->arg1, (const WinEvent*)frame->arg2);
|
||||||
case SYS_WINRESIZE:
|
case SYS_WINRESIZE:
|
||||||
return (int64_t)Sys_WinResize((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
return (int64_t)Sys_WinResize((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_PROCLIST:
|
case SYS_PROCLIST:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_ProcList((ProcInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_KILL: {
|
case SYS_KILL: {
|
||||||
// Free heap allocations for the target process before killing it
|
// Free heap allocations for the target process before killing it
|
||||||
@@ -217,8 +271,10 @@ namespace Montauk {
|
|||||||
return (int64_t)Sys_Kill((int)frame->arg1);
|
return (int64_t)Sys_Kill((int)frame->arg1);
|
||||||
}
|
}
|
||||||
case SYS_DEVLIST:
|
case SYS_DEVLIST:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_DevList((DevInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_DISKINFO:
|
case SYS_DISKINFO:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_DiskInfo((DiskInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_WINSETSCALE:
|
case SYS_WINSETSCALE:
|
||||||
return (int64_t)Sys_WinSetScale((int)frame->arg1);
|
return (int64_t)Sys_WinSetScale((int)frame->arg1);
|
||||||
@@ -227,41 +283,53 @@ namespace Montauk {
|
|||||||
case SYS_WINSETCURSOR:
|
case SYS_WINSETCURSOR:
|
||||||
return (int64_t)Sys_WinSetCursor((int)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_WinSetCursor((int)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_MEMSTATS:
|
case SYS_MEMSTATS:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
Sys_MemStats((MemStats*)frame->arg1);
|
Sys_MemStats((MemStats*)frame->arg1);
|
||||||
return 0;
|
return 0;
|
||||||
case SYS_PARTLIST:
|
case SYS_PARTLIST:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_PartList((PartInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_DISKREAD:
|
case SYS_DISKREAD:
|
||||||
|
if (!ValidUserPtr(frame->arg4)) return -1;
|
||||||
return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2,
|
return (int64_t)Sys_DiskRead((int)frame->arg1, frame->arg2,
|
||||||
(uint32_t)frame->arg3, (void*)frame->arg4);
|
(uint32_t)frame->arg3, (void*)frame->arg4);
|
||||||
case SYS_DISKWRITE:
|
case SYS_DISKWRITE:
|
||||||
|
if (!ValidUserPtr(frame->arg4)) return -1;
|
||||||
return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2,
|
return (int64_t)Sys_DiskWrite((int)frame->arg1, frame->arg2,
|
||||||
(uint32_t)frame->arg3, (const void*)frame->arg4);
|
(uint32_t)frame->arg3, (const void*)frame->arg4);
|
||||||
case SYS_GPTINIT:
|
case SYS_GPTINIT:
|
||||||
return (int64_t)Sys_GptInit((int)frame->arg1);
|
return (int64_t)Sys_GptInit((int)frame->arg1);
|
||||||
case SYS_GPTADD:
|
case SYS_GPTADD:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1);
|
return (int64_t)Sys_GptAdd((const GptAddParams*)frame->arg1);
|
||||||
case SYS_FSMOUNT:
|
case SYS_FSMOUNT:
|
||||||
return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2);
|
return (int64_t)Sys_FsMount((int)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_FSFORMAT:
|
case SYS_FSFORMAT:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return (int64_t)Sys_FsFormat((const FsFormatParams*)frame->arg1);
|
return (int64_t)Sys_FsFormat((const FsFormatParams*)frame->arg1);
|
||||||
case SYS_AUDIOOPEN:
|
case SYS_AUDIOOPEN:
|
||||||
return Sys_AudioOpen((uint32_t)frame->arg1, (uint8_t)frame->arg2, (uint8_t)frame->arg3);
|
return Sys_AudioOpen((uint32_t)frame->arg1, (uint8_t)frame->arg2, (uint8_t)frame->arg3);
|
||||||
case SYS_AUDIOCLOSE:
|
case SYS_AUDIOCLOSE:
|
||||||
return Sys_AudioClose((int)frame->arg1);
|
return Sys_AudioClose((int)frame->arg1);
|
||||||
case SYS_AUDIOWRITE:
|
case SYS_AUDIOWRITE:
|
||||||
|
if (!ValidUserPtr(frame->arg2)) return -1;
|
||||||
return Sys_AudioWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
return Sys_AudioWrite((int)frame->arg1, (const uint8_t*)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_AUDIOCTL:
|
case SYS_AUDIOCTL:
|
||||||
return Sys_AudioCtl((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
return Sys_AudioCtl((int)frame->arg1, (int)frame->arg2, (int)frame->arg3);
|
||||||
case SYS_BTSCAN:
|
case SYS_BTSCAN:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3);
|
return Sys_BtScan((BtScanResult*)frame->arg1, (int)frame->arg2, (uint32_t)frame->arg3);
|
||||||
case SYS_BTCONNECT:
|
case SYS_BTCONNECT:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_BtConnect((const uint8_t*)frame->arg1);
|
return Sys_BtConnect((const uint8_t*)frame->arg1);
|
||||||
case SYS_BTDISCONNECT:
|
case SYS_BTDISCONNECT:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_BtDisconnect((const uint8_t*)frame->arg1);
|
return Sys_BtDisconnect((const uint8_t*)frame->arg1);
|
||||||
case SYS_BTLIST:
|
case SYS_BTLIST:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2);
|
return Sys_BtList((BtDevInfo*)frame->arg1, (int)frame->arg2);
|
||||||
case SYS_BTINFO:
|
case SYS_BTINFO:
|
||||||
|
if (!ValidUserPtr(frame->arg1)) return -1;
|
||||||
return Sys_BtInfo((BtAdapterInfo*)frame->arg1);
|
return Sys_BtInfo((BtAdapterInfo*)frame->arg1);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ namespace WinServer {
|
|||||||
}
|
}
|
||||||
if (slotIdx < 0) return -1;
|
if (slotIdx < 0) return -1;
|
||||||
|
|
||||||
// Validate dimensions
|
// Validate dimensions (cap at 16384 to prevent integer overflow in w*h*4)
|
||||||
if (w <= 0 || h <= 0) return -1;
|
if (w <= 0 || h <= 0 || w > 16384 || h > 16384) return -1;
|
||||||
uint64_t bufSize = (uint64_t)w * h * 4;
|
uint64_t bufSize = (uint64_t)w * h * 4;
|
||||||
int numPages = (int)((bufSize + 0xFFF) / 0x1000);
|
int numPages = (int)((bufSize + 0xFFF) / 0x1000);
|
||||||
if (numPages > MaxPixelPages) return -1;
|
if (numPages > MaxPixelPages) return -1;
|
||||||
@@ -207,7 +207,7 @@ namespace WinServer {
|
|||||||
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
if (windowId < 0 || windowId >= MaxWindows) return -1;
|
||||||
WindowSlot& slot = g_slots[windowId];
|
WindowSlot& slot = g_slots[windowId];
|
||||||
if (!slot.used || slot.ownerPid != callerPid) return -1;
|
if (!slot.used || slot.ownerPid != callerPid) return -1;
|
||||||
if (newW <= 0 || newH <= 0) return -1;
|
if (newW <= 0 || newH <= 0 || newW > 16384 || newH > 16384) return -1;
|
||||||
if (newW == slot.width && newH == slot.height) {
|
if (newW == slot.width && newH == slot.height) {
|
||||||
outVa = slot.ownerVa;
|
outVa = slot.ownerVa;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -338,6 +338,73 @@ namespace Fs::Ramdisk {
|
|||||||
return fileCount++;
|
return fileCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Delete(const char* path) {
|
||||||
|
if (path == nullptr) return -1;
|
||||||
|
if (path[0] == '/') path++;
|
||||||
|
|
||||||
|
for (int i = 0; i < fileCount; i++) {
|
||||||
|
if (StrEqual(fileTable[i].name, path)) {
|
||||||
|
// Free heap-allocated data
|
||||||
|
if (fileTable[i].heapAllocated && fileTable[i].data) {
|
||||||
|
Memory::g_heap->Free(fileTable[i].data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift remaining entries down
|
||||||
|
for (int j = i; j < fileCount - 1; j++) {
|
||||||
|
fileTable[j] = fileTable[j + 1];
|
||||||
|
}
|
||||||
|
fileCount--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
int Mkdir(const char* path) {
|
||||||
|
if (path == nullptr) return -1;
|
||||||
|
if (fileCount >= MaxFiles) return -1;
|
||||||
|
if (path[0] == '/') path++;
|
||||||
|
|
||||||
|
// Check if directory already exists
|
||||||
|
for (int i = 0; i < fileCount; i++) {
|
||||||
|
if (StrEqual(fileTable[i].name, path) && fileTable[i].isDirectory) {
|
||||||
|
return 0; // already exists
|
||||||
|
}
|
||||||
|
// Also check with trailing slash
|
||||||
|
int pathLen = StrLen(path);
|
||||||
|
int entryLen = StrLen(fileTable[i].name);
|
||||||
|
if (entryLen == pathLen + 1 && fileTable[i].name[entryLen - 1] == '/' &&
|
||||||
|
fileTable[i].isDirectory) {
|
||||||
|
bool match = true;
|
||||||
|
for (int j = 0; j < pathLen; j++) {
|
||||||
|
if (path[j] != fileTable[i].name[j]) { match = false; break; }
|
||||||
|
}
|
||||||
|
if (match) return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create directory entry (stored with trailing slash for tar convention)
|
||||||
|
FileEntry& entry = fileTable[fileCount];
|
||||||
|
|
||||||
|
int nameLen = 0;
|
||||||
|
while (nameLen < MaxNameLen - 2 && path[nameLen] != '\0') {
|
||||||
|
entry.name[nameLen] = path[nameLen];
|
||||||
|
nameLen++;
|
||||||
|
}
|
||||||
|
// Add trailing slash
|
||||||
|
entry.name[nameLen++] = '/';
|
||||||
|
entry.name[nameLen] = '\0';
|
||||||
|
|
||||||
|
entry.data = nullptr;
|
||||||
|
entry.size = 0;
|
||||||
|
entry.capacity = 0;
|
||||||
|
entry.isDirectory = true;
|
||||||
|
entry.heapAllocated = false;
|
||||||
|
|
||||||
|
fileCount++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int GetFileCount() {
|
int GetFileCount() {
|
||||||
return fileCount;
|
return fileCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ namespace Fs::Ramdisk {
|
|||||||
void Close(int handle);
|
void Close(int handle);
|
||||||
|
|
||||||
int ReadDir(const char* path, const char** outNames, int maxEntries);
|
int ReadDir(const char* path, const char** outNames, int maxEntries);
|
||||||
|
int Delete(const char* path);
|
||||||
|
int Mkdir(const char* path);
|
||||||
int GetFileCount();
|
int GetFileCount();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -199,8 +199,8 @@ extern "C" void kmain() {
|
|||||||
Fs::Ramdisk::ReadDir,
|
Fs::Ramdisk::ReadDir,
|
||||||
Fs::Ramdisk::Write,
|
Fs::Ramdisk::Write,
|
||||||
Fs::Ramdisk::Create,
|
Fs::Ramdisk::Create,
|
||||||
nullptr,
|
Fs::Ramdisk::Delete,
|
||||||
nullptr
|
Fs::Ramdisk::Mkdir
|
||||||
};
|
};
|
||||||
Fs::Vfs::RegisterDrive(0, &ramdiskDriver);
|
Fs::Vfs::RegisterDrive(0, &ramdiskDriver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ namespace Memory {
|
|||||||
|
|
||||||
void* PageFrameAllocator::AllocateZeroed() {
|
void* PageFrameAllocator::AllocateZeroed() {
|
||||||
auto page = Allocate();
|
auto page = Allocate();
|
||||||
|
if (page == nullptr) return nullptr;
|
||||||
memset(page, 0, 0x1000);
|
memset(page, 0, 0x1000);
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
|
|||||||
@@ -171,7 +171,9 @@ namespace Net::Dns {
|
|||||||
// Compression pointer
|
// Compression pointer
|
||||||
if (offset + 1 >= packetLen) return -1;
|
if (offset + 1 >= packetLen) return -1;
|
||||||
if (!jumped) returnOffset = offset + 2;
|
if (!jumped) returnOffset = offset + 2;
|
||||||
offset = ((len & 0x3F) << 8) | packet[offset + 1];
|
int target = ((len & 0x3F) << 8) | packet[offset + 1];
|
||||||
|
if (target >= packetLen) return -1; // Pointer beyond packet bounds
|
||||||
|
offset = target;
|
||||||
jumped = true;
|
jumped = true;
|
||||||
maxJumps--;
|
maxJumps--;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ namespace Net::Ipv4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t totalLen = Ntohs(hdr->TotalLength);
|
uint16_t totalLen = Ntohs(hdr->TotalLength);
|
||||||
if (totalLen > length) {
|
if (totalLen < ihl || totalLen > length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,9 @@ namespace Sched {
|
|||||||
// Load ELF into the process's address space
|
// Load ELF into the process's address space
|
||||||
uint64_t entry = ElfLoad(vfsPath, pml4Phys);
|
uint64_t entry = ElfLoad(vfsPath, pml4Phys);
|
||||||
if (entry == 0) {
|
if (entry == 0) {
|
||||||
|
// Free the PML4 and any pages allocated during ELF load
|
||||||
|
Memory::VMM::Paging::FreeUserHalf(pml4Phys);
|
||||||
|
Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,18 +130,29 @@ namespace Sched {
|
|||||||
void* firstPage = Memory::g_pfa->AllocateZeroed();
|
void* firstPage = Memory::g_pfa->AllocateZeroed();
|
||||||
if (firstPage == nullptr) {
|
if (firstPage == nullptr) {
|
||||||
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for kernel stack";
|
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for kernel stack";
|
||||||
|
Memory::VMM::Paging::FreeUserHalf(pml4Phys);
|
||||||
|
Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
void* stackMem = Memory::g_pfa->ReallocConsecutive(firstPage, StackPages);
|
void* stackMem = Memory::g_pfa->ReallocConsecutive(firstPage, StackPages);
|
||||||
if (stackMem == nullptr) {
|
if (stackMem == nullptr) {
|
||||||
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to allocate contiguous kernel stack";
|
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to allocate contiguous kernel stack";
|
||||||
Memory::g_pfa->Free(firstPage);
|
Memory::g_pfa->Free(firstPage);
|
||||||
|
Memory::VMM::Paging::FreeUserHalf(pml4Phys);
|
||||||
|
Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* kernelStackBase = (uint8_t*)stackMem;
|
uint8_t* kernelStackBase = (uint8_t*)stackMem;
|
||||||
uint64_t kernelStackTop = (uint64_t)kernelStackBase + StackSize;
|
uint64_t kernelStackTop = (uint64_t)kernelStackBase + StackSize;
|
||||||
|
|
||||||
|
// Helper to clean up all resources allocated so far on failure
|
||||||
|
auto cleanupOnFail = [&]() {
|
||||||
|
Memory::VMM::Paging::FreeUserHalf(pml4Phys);
|
||||||
|
Memory::g_pfa->Free((void*)Memory::HHDM(pml4Phys));
|
||||||
|
Memory::g_pfa->Free(stackMem, StackPages);
|
||||||
|
};
|
||||||
|
|
||||||
// Allocate user stack pages and map them in the process PML4
|
// Allocate user stack pages and map them in the process PML4
|
||||||
uint64_t userStackBase = UserStackTop - UserStackSize;
|
uint64_t userStackBase = UserStackTop - UserStackSize;
|
||||||
uint64_t topStackPagePhys = 0;
|
uint64_t topStackPagePhys = 0;
|
||||||
@@ -146,11 +160,14 @@ namespace Sched {
|
|||||||
void* page = Memory::g_pfa->AllocateZeroed();
|
void* page = Memory::g_pfa->AllocateZeroed();
|
||||||
if (page == nullptr) {
|
if (page == nullptr) {
|
||||||
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for user stack";
|
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for user stack";
|
||||||
|
cleanupOnFail();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint64_t physAddr = Memory::SubHHDM((uint64_t)page);
|
uint64_t physAddr = Memory::SubHHDM((uint64_t)page);
|
||||||
if (!Memory::VMM::Paging::MapUserIn(pml4Phys, physAddr, userStackBase + i * 0x1000)) {
|
if (!Memory::VMM::Paging::MapUserIn(pml4Phys, physAddr, userStackBase + i * 0x1000)) {
|
||||||
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to map user stack page";
|
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to map user stack page";
|
||||||
|
Memory::g_pfa->Free(page);
|
||||||
|
cleanupOnFail();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (i == UserStackPages - 1) topStackPagePhys = physAddr;
|
if (i == UserStackPages - 1) topStackPagePhys = physAddr;
|
||||||
@@ -162,11 +179,14 @@ namespace Sched {
|
|||||||
void* stubPage = Memory::g_pfa->AllocateZeroed();
|
void* stubPage = Memory::g_pfa->AllocateZeroed();
|
||||||
if (stubPage == nullptr) {
|
if (stubPage == nullptr) {
|
||||||
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for exit stub";
|
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Out of memory for exit stub";
|
||||||
|
cleanupOnFail();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint64_t stubPhys = Memory::SubHHDM((uint64_t)stubPage);
|
uint64_t stubPhys = Memory::SubHHDM((uint64_t)stubPage);
|
||||||
if (!Memory::VMM::Paging::MapUserIn(pml4Phys, stubPhys, ExitStubAddr)) {
|
if (!Memory::VMM::Paging::MapUserIn(pml4Phys, stubPhys, ExitStubAddr)) {
|
||||||
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to map exit stub";
|
Kt::KernelLogStream(Kt::ERROR, "Sched") << "Failed to map exit stub";
|
||||||
|
Memory::g_pfa->Free(stubPage);
|
||||||
|
cleanupOnFail();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,19 +311,26 @@ namespace Sched {
|
|||||||
oldRspPtr = &idleSavedRsp;
|
oldRspPtr = &idleSavedRsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int oldPid = currentPid;
|
||||||
currentPid = next;
|
currentPid = next;
|
||||||
processTable[next].state = ProcessState::Running;
|
processTable[next].state = ProcessState::Running;
|
||||||
processTable[next].sliceRemaining = TimeSliceMs;
|
processTable[next].sliceRemaining = TimeSliceMs;
|
||||||
|
|
||||||
uint64_t newCR3 = processTable[next].pml4Phys;
|
uint64_t newCR3 = processTable[next].pml4Phys;
|
||||||
|
|
||||||
|
// Disable interrupts while updating global kernel RSP and TSS,
|
||||||
|
// preventing an interrupt from using stale values mid-update.
|
||||||
|
asm volatile("cli");
|
||||||
|
|
||||||
// Update kernel RSP for SYSCALL entry
|
// Update kernel RSP for SYSCALL entry
|
||||||
g_kernelRsp = processTable[next].kernelStackTop;
|
g_kernelRsp = processTable[next].kernelStackTop;
|
||||||
|
|
||||||
// Update TSS RSP0 for hardware interrupts from ring 3
|
// Update TSS RSP0 for hardware interrupts from ring 3
|
||||||
Hal::g_tss.rsp0 = processTable[next].kernelStackTop;
|
Hal::g_tss.rsp0 = processTable[next].kernelStackTop;
|
||||||
|
|
||||||
uint8_t* oldFpu = (currentPid >= 0) ? processTable[currentPid].fpuState : nullptr;
|
asm volatile("sti");
|
||||||
|
|
||||||
|
uint8_t* oldFpu = (oldPid >= 0) ? processTable[oldPid].fpuState : nullptr;
|
||||||
uint8_t* newFpu = processTable[next].fpuState;
|
uint8_t* newFpu = processTable[next].fpuState;
|
||||||
SchedContextSwitch(oldRspPtr, processTable[next].savedRsp, newCR3, oldFpu, newFpu);
|
SchedContextSwitch(oldRspPtr, processTable[next].savedRsp, newCR3, oldFpu, newFpu);
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-10
@@ -59,7 +59,7 @@ BINDIR := bin
|
|||||||
PROGRAMS := $(notdir $(wildcard src/*))
|
PROGRAMS := $(notdir $(wildcard src/*))
|
||||||
|
|
||||||
# Programs with custom Makefiles (built separately).
|
# Programs with custom Makefiles (built separately).
|
||||||
CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop
|
CUSTOM_BUILDS := doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop login shell
|
||||||
SYSTEM_PROGRAMS := $(filter-out $(CUSTOM_BUILDS),$(PROGRAMS))
|
SYSTEM_PROGRAMS := $(filter-out $(CUSTOM_BUILDS),$(PROGRAMS))
|
||||||
|
|
||||||
# Build targets: system programs go to bin/os/, apps go to bin/apps/<name>/.
|
# Build targets: system programs go to bin/os/, apps go to bin/apps/<name>/.
|
||||||
@@ -78,12 +78,12 @@ WWWDST := $(patsubst $(WWWDIR)/%,$(BINDIR)/www/%,$(WWWSRC))
|
|||||||
# CA certificate bundle.
|
# CA certificate bundle.
|
||||||
CA_CERTS := $(BINDIR)/etc/ca-certificates.crt
|
CA_CERTS := $(BINDIR)/etc/ca-certificates.crt
|
||||||
|
|
||||||
# Home directory placeholder.
|
# Common shared assets (wallpapers, etc.)
|
||||||
HOMEKEEP := $(BINDIR)/home/.keep
|
COMMONKEEP := $(BINDIR)/common/.keep
|
||||||
|
|
||||||
.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth desktop icons fonts bearssl libc tls libjpeg install-apps
|
.PHONY: all clean doom fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth login desktop shell icons fonts bearssl libc tls libjpeg install-apps
|
||||||
|
|
||||||
all: bearssl libc libjpeg tls $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth doom desktop icons fonts install-apps $(MANDST) $(WWWDST) $(CA_CERTS) $(HOMEKEEP)
|
all: bearssl libc libjpeg tls $(TARGETS) fetch wiki wikipedia weather imageviewer fontpreview spreadsheet pdfviewer disks devexplorer installer volume music bluetooth doom login desktop shell icons fonts install-apps $(MANDST) $(WWWDST) $(CA_CERTS) $(COMMONKEEP)
|
||||||
|
|
||||||
# Build BearSSL static library (cross-compiled for freestanding x86_64).
|
# Build BearSSL static library (cross-compiled for freestanding x86_64).
|
||||||
BEARSSL_INCLUDES := -isystem $(shell cd .. && pwd)/kernel/freestnd-c-hdrs/x86_64/include -isystem $(abspath include/libc)
|
BEARSSL_INCLUDES := -isystem $(shell cd .. && pwd)/kernel/freestnd-c-hdrs/x86_64/include -isystem $(abspath include/libc)
|
||||||
@@ -164,8 +164,16 @@ music: libc
|
|||||||
bluetooth: libc
|
bluetooth: libc
|
||||||
$(MAKE) -C src/bluetooth
|
$(MAKE) -C src/bluetooth
|
||||||
|
|
||||||
# Build desktop via its own Makefile (depends on libc and libjpeg for wallpaper).
|
# Build login screen via its own Makefile (depends on bearssl and libc).
|
||||||
desktop: libc libjpeg
|
login: bearssl libc
|
||||||
|
$(MAKE) -C src/login
|
||||||
|
|
||||||
|
# Build shell via its own Makefile (multi-file build).
|
||||||
|
shell:
|
||||||
|
$(MAKE) -C src/shell
|
||||||
|
|
||||||
|
# Build desktop via its own Makefile (depends on libc, libjpeg, and bearssl for user.h).
|
||||||
|
desktop: libc libjpeg bearssl
|
||||||
$(MAKE) -C src/desktop
|
$(MAKE) -C src/desktop
|
||||||
|
|
||||||
# Copy SVG icons for the desktop into bin/icons/.
|
# Copy SVG icons for the desktop into bin/icons/.
|
||||||
@@ -199,9 +207,9 @@ $(CA_CERTS): data/ca-certificates.crt
|
|||||||
mkdir -p $(BINDIR)/etc
|
mkdir -p $(BINDIR)/etc
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
# Create empty home directory with a keep file.
|
# Ensure common assets directory exists.
|
||||||
$(HOMEKEEP):
|
$(COMMONKEEP):
|
||||||
mkdir -p $(BINDIR)/home
|
mkdir -p $(BINDIR)/common
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
# Build each system program from its source files.
|
# Build each system program from its source files.
|
||||||
@@ -218,6 +226,8 @@ clean:
|
|||||||
$(MAKE) -C lib/tls clean
|
$(MAKE) -C lib/tls clean
|
||||||
$(MAKE) -C src/fetch clean
|
$(MAKE) -C src/fetch clean
|
||||||
$(MAKE) -C src/doom clean
|
$(MAKE) -C src/doom clean
|
||||||
|
$(MAKE) -C src/login clean
|
||||||
|
$(MAKE) -C src/shell clean
|
||||||
$(MAKE) -C src/desktop clean
|
$(MAKE) -C src/desktop clean
|
||||||
$(MAKE) -C src/wikipedia clean
|
$(MAKE) -C src/wikipedia clean
|
||||||
$(MAKE) -C src/weather clean
|
$(MAKE) -C src/weather clean
|
||||||
|
|||||||
@@ -60,6 +60,12 @@ struct DesktopState {
|
|||||||
int window_count;
|
int window_count;
|
||||||
int focused_window;
|
int focused_window;
|
||||||
|
|
||||||
|
// Current user context
|
||||||
|
char current_user[32];
|
||||||
|
char home_dir[128]; // "0:/users/<username>"
|
||||||
|
char user_config_dir[128]; // "0:/users/<username>/config"
|
||||||
|
bool is_admin;
|
||||||
|
|
||||||
Montauk::MouseState mouse;
|
Montauk::MouseState mouse;
|
||||||
uint8_t prev_buttons;
|
uint8_t prev_buttons;
|
||||||
|
|
||||||
@@ -93,9 +99,11 @@ struct DesktopState {
|
|||||||
SvgIcon icon_settings;
|
SvgIcon icon_settings;
|
||||||
SvgIcon icon_reboot;
|
SvgIcon icon_reboot;
|
||||||
SvgIcon icon_shutdown;
|
SvgIcon icon_shutdown;
|
||||||
|
SvgIcon icon_logout;
|
||||||
|
|
||||||
SvgIcon icon_procmgr;
|
SvgIcon icon_procmgr;
|
||||||
SvgIcon icon_mandelbrot;
|
SvgIcon icon_mandelbrot;
|
||||||
|
SvgIcon icon_volume;
|
||||||
|
|
||||||
// External apps discovered from 0:/apps/ manifests
|
// External apps discovered from 0:/apps/ manifests
|
||||||
ExternalApp external_apps[MAX_EXTERNAL_APPS];
|
ExternalApp external_apps[MAX_EXTERNAL_APPS];
|
||||||
@@ -109,6 +117,14 @@ struct DesktopState {
|
|||||||
uint64_t net_cfg_last_poll;
|
uint64_t net_cfg_last_poll;
|
||||||
Rect net_icon_rect;
|
Rect net_icon_rect;
|
||||||
|
|
||||||
|
bool vol_popup_open;
|
||||||
|
Rect vol_icon_rect;
|
||||||
|
int vol_level; // 0-100
|
||||||
|
bool vol_muted;
|
||||||
|
int vol_pre_mute; // volume before mute
|
||||||
|
bool vol_dragging; // slider drag in progress
|
||||||
|
uint64_t vol_last_poll;
|
||||||
|
|
||||||
int screen_w, screen_h;
|
int screen_w, screen_h;
|
||||||
|
|
||||||
// IDs of external windows we've sent a close event to but that haven't
|
// IDs of external windows we've sent a close event to but that haven't
|
||||||
@@ -119,6 +135,15 @@ struct DesktopState {
|
|||||||
int closing_ext_count;
|
int closing_ext_count;
|
||||||
|
|
||||||
DesktopSettings settings;
|
DesktopSettings settings;
|
||||||
|
|
||||||
|
// Lock screen state
|
||||||
|
bool screen_locked;
|
||||||
|
char lock_password[64];
|
||||||
|
int lock_password_len;
|
||||||
|
char lock_error[128];
|
||||||
|
bool lock_show_error;
|
||||||
|
char lock_display_name[64];
|
||||||
|
SvgIcon icon_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Forward declarations - implemented in main.cpp
|
// Forward declarations - implemented in main.cpp
|
||||||
|
|||||||
@@ -0,0 +1,316 @@
|
|||||||
|
/*
|
||||||
|
* http.hpp
|
||||||
|
* Simple HTTP request builder and response parser for MontaukOS
|
||||||
|
* Wraps tls::https_fetch() and raw sockets for ergonomic HTTP usage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <tls/tls.hpp>
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Response
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct Response {
|
||||||
|
int status; // HTTP status code (200, 404, etc.) or -1 on error
|
||||||
|
const char* headers; // Pointer into raw buffer (header block)
|
||||||
|
int headers_len;
|
||||||
|
const char* body; // Pointer into raw buffer (body)
|
||||||
|
int body_len;
|
||||||
|
char* raw; // Owned buffer — caller must free with montauk::mfree()
|
||||||
|
int raw_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse raw HTTP response in-place. Sets pointers into buf (does not copy).
|
||||||
|
// Returns status code, or -1 if unparseable.
|
||||||
|
inline int parse_response(char* buf, int len, Response* out) {
|
||||||
|
out->raw = buf;
|
||||||
|
out->raw_len = len;
|
||||||
|
out->status = -1;
|
||||||
|
out->headers = nullptr;
|
||||||
|
out->headers_len = 0;
|
||||||
|
out->body = nullptr;
|
||||||
|
out->body_len = 0;
|
||||||
|
|
||||||
|
if (len < 12) return -1; // "HTTP/1.x NNN"
|
||||||
|
|
||||||
|
// Parse status code from "HTTP/1.x NNN"
|
||||||
|
const char* p = buf;
|
||||||
|
while (*p && *p != ' ') p++;
|
||||||
|
if (*p != ' ') return -1;
|
||||||
|
p++;
|
||||||
|
int code = 0;
|
||||||
|
for (int i = 0; i < 3 && *p >= '0' && *p <= '9'; i++, p++)
|
||||||
|
code = code * 10 + (*p - '0');
|
||||||
|
out->status = code;
|
||||||
|
|
||||||
|
// Headers start after the status line
|
||||||
|
const char* hdr_start = buf;
|
||||||
|
while (hdr_start < buf + len - 1) {
|
||||||
|
if (*hdr_start == '\r' && *(hdr_start + 1) == '\n') { hdr_start += 2; break; }
|
||||||
|
if (*hdr_start == '\n') { hdr_start++; break; }
|
||||||
|
hdr_start++;
|
||||||
|
}
|
||||||
|
out->headers = hdr_start;
|
||||||
|
|
||||||
|
// Find \r\n\r\n boundary between headers and body
|
||||||
|
for (const char* s = hdr_start; s < buf + len - 3; s++) {
|
||||||
|
if (s[0] == '\r' && s[1] == '\n' && s[2] == '\r' && s[3] == '\n') {
|
||||||
|
out->headers_len = (int)(s - hdr_start);
|
||||||
|
out->body = s + 4;
|
||||||
|
out->body_len = len - (int)(out->body - buf);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No body separator found — entire remainder is headers
|
||||||
|
out->headers_len = len - (int)(hdr_start - buf);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a header value by name (case-insensitive match on the name).
|
||||||
|
// Writes value into out_val (up to max_len), returns true if found.
|
||||||
|
inline bool get_header(const Response* resp, const char* name, char* out_val, int max_len) {
|
||||||
|
if (!resp->headers || resp->headers_len == 0) return false;
|
||||||
|
int name_len = montauk::slen(name);
|
||||||
|
const char* p = resp->headers;
|
||||||
|
const char* end = resp->headers + resp->headers_len;
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
// Case-insensitive prefix match
|
||||||
|
bool match = true;
|
||||||
|
if (p + name_len >= end) { match = false; }
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < name_len; i++) {
|
||||||
|
char a = p[i], b = name[i];
|
||||||
|
if (a >= 'A' && a <= 'Z') a += 32;
|
||||||
|
if (b >= 'A' && b <= 'Z') b += 32;
|
||||||
|
if (a != b) { match = false; break; }
|
||||||
|
}
|
||||||
|
if (match && p[name_len] != ':') match = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const char* v = p + name_len + 1;
|
||||||
|
while (v < end && *v == ' ') v++; // skip OWS
|
||||||
|
int i = 0;
|
||||||
|
while (v < end && *v != '\r' && *v != '\n' && i < max_len - 1)
|
||||||
|
out_val[i++] = *v++;
|
||||||
|
out_val[i] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip to next line
|
||||||
|
while (p < end && *p != '\n') p++;
|
||||||
|
if (p < end) p++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free a response's raw buffer.
|
||||||
|
inline void free_response(Response* resp) {
|
||||||
|
if (resp->raw) { montauk::mfree(resp->raw); resp->raw = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Request builder (internal)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline int build_request(char* buf, int buf_size,
|
||||||
|
const char* method, const char* host,
|
||||||
|
const char* path, const char* content_type,
|
||||||
|
const char* body_data, int body_len,
|
||||||
|
const char* extra_headers) {
|
||||||
|
char* p = buf;
|
||||||
|
char* end = buf + buf_size - 1;
|
||||||
|
|
||||||
|
auto append = [&](const char* s) {
|
||||||
|
while (*s && p < end) *p++ = *s++;
|
||||||
|
};
|
||||||
|
auto append_int = [&](int n) {
|
||||||
|
char tmp[16]; int ti = 0;
|
||||||
|
if (n == 0) { if (p < end) *p++ = '0'; return; }
|
||||||
|
while (n > 0) { tmp[ti++] = '0' + (n % 10); n /= 10; }
|
||||||
|
for (int j = ti - 1; j >= 0 && p < end; j--) *p++ = tmp[j];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Request line
|
||||||
|
append(method); append(" "); append(path); append(" HTTP/1.1\r\n");
|
||||||
|
|
||||||
|
// Host
|
||||||
|
append("Host: "); append(host); append("\r\n");
|
||||||
|
|
||||||
|
// Content headers (for POST/PUT/PATCH)
|
||||||
|
if (body_data && body_len > 0) {
|
||||||
|
if (content_type) {
|
||||||
|
append("Content-Type: "); append(content_type); append("\r\n");
|
||||||
|
}
|
||||||
|
append("Content-Length: "); append_int(body_len); append("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra headers (caller-supplied, must include \r\n terminators)
|
||||||
|
if (extra_headers) append(extra_headers);
|
||||||
|
|
||||||
|
append("Connection: close\r\n");
|
||||||
|
append("\r\n");
|
||||||
|
|
||||||
|
int header_len = (int)(p - buf);
|
||||||
|
|
||||||
|
// Append body
|
||||||
|
if (body_data && body_len > 0 && header_len + body_len < buf_size) {
|
||||||
|
montauk::memcpy(p, body_data, body_len);
|
||||||
|
p += body_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)(p - buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Public API
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// GET request over HTTPS. Returns parsed response. Caller must free_response().
|
||||||
|
inline Response get(const char* host, const char* path,
|
||||||
|
const tls::TrustAnchors& tas,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr,
|
||||||
|
tls::AbortCheckFn abort_check = nullptr) {
|
||||||
|
Response resp = {};
|
||||||
|
resp.status = -1;
|
||||||
|
|
||||||
|
uint32_t ip = montauk::resolve(host);
|
||||||
|
if (!ip) return resp;
|
||||||
|
|
||||||
|
char req[1024];
|
||||||
|
int reqLen = build_request(req, sizeof(req), "GET", host, path,
|
||||||
|
nullptr, nullptr, 0, extra_headers);
|
||||||
|
|
||||||
|
char* buf = (char*)montauk::malloc(resp_buf_size);
|
||||||
|
if (!buf) return resp;
|
||||||
|
|
||||||
|
int n = tls::https_fetch(host, ip, 443, req, reqLen, tas,
|
||||||
|
buf, resp_buf_size - 1, abort_check);
|
||||||
|
if (n <= 0) { montauk::mfree(buf); return resp; }
|
||||||
|
buf[n] = 0;
|
||||||
|
|
||||||
|
parse_response(buf, n, &resp);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST request over HTTPS. Returns parsed response. Caller must free_response().
|
||||||
|
inline Response post(const char* host, const char* path,
|
||||||
|
const char* content_type,
|
||||||
|
const char* body_data, int body_len,
|
||||||
|
const tls::TrustAnchors& tas,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr,
|
||||||
|
tls::AbortCheckFn abort_check = nullptr) {
|
||||||
|
Response resp = {};
|
||||||
|
resp.status = -1;
|
||||||
|
|
||||||
|
uint32_t ip = montauk::resolve(host);
|
||||||
|
if (!ip) return resp;
|
||||||
|
|
||||||
|
int req_size = 1024 + body_len;
|
||||||
|
char* req = (char*)montauk::malloc(req_size);
|
||||||
|
if (!req) return resp;
|
||||||
|
|
||||||
|
int reqLen = build_request(req, req_size, "POST", host, path,
|
||||||
|
content_type, body_data, body_len,
|
||||||
|
extra_headers);
|
||||||
|
|
||||||
|
char* buf = (char*)montauk::malloc(resp_buf_size);
|
||||||
|
if (!buf) { montauk::mfree(req); return resp; }
|
||||||
|
|
||||||
|
int n = tls::https_fetch(host, ip, 443, req, reqLen, tas,
|
||||||
|
buf, resp_buf_size - 1, abort_check);
|
||||||
|
montauk::mfree(req);
|
||||||
|
|
||||||
|
if (n <= 0) { montauk::mfree(buf); return resp; }
|
||||||
|
buf[n] = 0;
|
||||||
|
|
||||||
|
parse_response(buf, n, &resp);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic request over HTTPS (PUT, PATCH, DELETE, etc.).
|
||||||
|
inline Response request(const char* method,
|
||||||
|
const char* host, const char* path,
|
||||||
|
const char* content_type,
|
||||||
|
const char* body_data, int body_len,
|
||||||
|
const tls::TrustAnchors& tas,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr,
|
||||||
|
tls::AbortCheckFn abort_check = nullptr) {
|
||||||
|
Response resp = {};
|
||||||
|
resp.status = -1;
|
||||||
|
|
||||||
|
uint32_t ip = montauk::resolve(host);
|
||||||
|
if (!ip) return resp;
|
||||||
|
|
||||||
|
int req_size = 1024 + (body_len > 0 ? body_len : 0);
|
||||||
|
char* req = (char*)montauk::malloc(req_size);
|
||||||
|
if (!req) return resp;
|
||||||
|
|
||||||
|
int reqLen = build_request(req, req_size, method, host, path,
|
||||||
|
content_type, body_data, body_len,
|
||||||
|
extra_headers);
|
||||||
|
|
||||||
|
char* buf = (char*)montauk::malloc(resp_buf_size);
|
||||||
|
if (!buf) { montauk::mfree(req); return resp; }
|
||||||
|
|
||||||
|
int n = tls::https_fetch(host, ip, 443, req, reqLen, tas,
|
||||||
|
buf, resp_buf_size - 1, abort_check);
|
||||||
|
montauk::mfree(req);
|
||||||
|
|
||||||
|
if (n <= 0) { montauk::mfree(buf); return resp; }
|
||||||
|
buf[n] = 0;
|
||||||
|
|
||||||
|
parse_response(buf, n, &resp);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plain HTTP (no TLS) GET over port 80.
|
||||||
|
inline Response get_plain(const char* host, const char* path,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr) {
|
||||||
|
Response resp = {};
|
||||||
|
resp.status = -1;
|
||||||
|
|
||||||
|
uint32_t ip = montauk::resolve(host);
|
||||||
|
if (!ip) return resp;
|
||||||
|
|
||||||
|
char req[1024];
|
||||||
|
int reqLen = build_request(req, sizeof(req), "GET", host, path,
|
||||||
|
nullptr, nullptr, 0, extra_headers);
|
||||||
|
|
||||||
|
int sock = montauk::socket(Montauk::SOCK_TCP);
|
||||||
|
if (sock < 0) return resp;
|
||||||
|
if (montauk::connect(sock, ip, 80) < 0) { montauk::closesocket(sock); return resp; }
|
||||||
|
|
||||||
|
montauk::send(sock, req, reqLen);
|
||||||
|
|
||||||
|
char* buf = (char*)montauk::malloc(resp_buf_size);
|
||||||
|
if (!buf) { montauk::closesocket(sock); return resp; }
|
||||||
|
|
||||||
|
int total = 0;
|
||||||
|
while (total < resp_buf_size - 1) {
|
||||||
|
int n = montauk::recv(sock, buf + total, resp_buf_size - 1 - total);
|
||||||
|
if (n <= 0) break;
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
montauk::closesocket(sock);
|
||||||
|
|
||||||
|
if (total <= 0) { montauk::mfree(buf); return resp; }
|
||||||
|
buf[total] = 0;
|
||||||
|
|
||||||
|
parse_response(buf, total, &resp);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
@@ -247,14 +247,98 @@ namespace config {
|
|||||||
char* text = serialize(doc);
|
char* text = serialize(doc);
|
||||||
int textLen = montauk::slen(text);
|
int textLen = montauk::slen(text);
|
||||||
|
|
||||||
// Try to open existing file, create if not found
|
// Delete and recreate to ensure file is exactly the right size
|
||||||
|
// (no ftruncate syscall available, so this avoids stale trailing data)
|
||||||
|
montauk::fdelete(path);
|
||||||
|
int handle = montauk::fcreate(path);
|
||||||
|
if (handle < 0) {
|
||||||
|
montauk::mfree(text);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen);
|
||||||
|
montauk::close(handle);
|
||||||
|
montauk::mfree(text);
|
||||||
|
return ret < 0 ? ret : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Per-user config ----
|
||||||
|
|
||||||
|
// Build path: "0:/users/<username>/config/<name>.toml"
|
||||||
|
inline void build_user_path(char* out, int outSz, const char* username, const char* name) {
|
||||||
|
int p = 0;
|
||||||
|
const char* prefix = "0:/users/";
|
||||||
|
while (*prefix && p < outSz - 2) out[p++] = *prefix++;
|
||||||
|
while (*username && p < outSz - 2) out[p++] = *username++;
|
||||||
|
const char* mid = "/config/";
|
||||||
|
while (*mid && p < outSz - 2) out[p++] = *mid++;
|
||||||
|
while (*name && p < outSz - 6) out[p++] = *name++;
|
||||||
|
const char* ext = ".toml";
|
||||||
|
while (*ext && p < outSz - 1) out[p++] = *ext++;
|
||||||
|
out[p] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure per-user config directory exists
|
||||||
|
inline void ensure_user_dir(const char* username) {
|
||||||
|
char dir[128];
|
||||||
|
int p = 0;
|
||||||
|
const char* prefix = "0:/users/";
|
||||||
|
while (*prefix && p < 126) dir[p++] = *prefix++;
|
||||||
|
while (*username && p < 126) dir[p++] = *username++;
|
||||||
|
dir[p] = '\0';
|
||||||
|
montauk::fmkdir(dir);
|
||||||
|
|
||||||
|
const char* suffix = "/config";
|
||||||
|
while (*suffix && p < 126) dir[p++] = *suffix++;
|
||||||
|
dir[p] = '\0';
|
||||||
|
montauk::fmkdir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load a per-user config file
|
||||||
|
inline toml::Doc load_user(const char* username, const char* name) {
|
||||||
|
char path[192];
|
||||||
|
build_user_path(path, sizeof(path), username, name);
|
||||||
|
|
||||||
int handle = montauk::open(path);
|
int handle = montauk::open(path);
|
||||||
if (handle < 0) {
|
if (handle < 0) {
|
||||||
handle = montauk::fcreate(path);
|
toml::Doc doc;
|
||||||
if (handle < 0) {
|
doc.init();
|
||||||
montauk::mfree(text);
|
return doc;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
uint64_t size = montauk::getsize(handle);
|
||||||
|
if (size == 0) {
|
||||||
|
montauk::close(handle);
|
||||||
|
toml::Doc doc;
|
||||||
|
doc.init();
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* text = (char*)montauk::malloc(size + 1);
|
||||||
|
montauk::read(handle, (uint8_t*)text, 0, size);
|
||||||
|
montauk::close(handle);
|
||||||
|
text[size] = '\0';
|
||||||
|
|
||||||
|
toml::Doc doc = toml::parse(text);
|
||||||
|
montauk::mfree(text);
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save a per-user config file
|
||||||
|
inline int save_user(const char* username, const char* name, toml::Doc* doc) {
|
||||||
|
ensure_user_dir(username);
|
||||||
|
|
||||||
|
char path[192];
|
||||||
|
build_user_path(path, sizeof(path), username, name);
|
||||||
|
|
||||||
|
char* text = serialize(doc);
|
||||||
|
int textLen = montauk::slen(text);
|
||||||
|
|
||||||
|
montauk::fdelete(path);
|
||||||
|
int handle = montauk::fcreate(path);
|
||||||
|
if (handle < 0) {
|
||||||
|
montauk::mfree(text);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen);
|
int ret = montauk::fwrite(handle, (const uint8_t*)text, 0, textLen);
|
||||||
@@ -272,12 +356,28 @@ namespace config {
|
|||||||
|
|
||||||
// ---- In-place modification helpers ----
|
// ---- In-place modification helpers ----
|
||||||
|
|
||||||
|
// Free any dynamically allocated data owned by a value (without freeing key)
|
||||||
|
namespace detail {
|
||||||
|
inline void free_value_data(toml::Value* v) {
|
||||||
|
if (v->type == toml::Type::String && v->str)
|
||||||
|
montauk::mfree(v->str);
|
||||||
|
else if (v->type == toml::Type::Array || v->type == toml::Type::Table) {
|
||||||
|
for (int i = 0; i < v->array.count; i++) {
|
||||||
|
if (v->array.items[i]) v->array.items[i]->destroy();
|
||||||
|
}
|
||||||
|
if (v->array.items) montauk::mfree(v->array.items);
|
||||||
|
v->array.items = nullptr;
|
||||||
|
v->array.count = 0;
|
||||||
|
v->array.cap = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set or overwrite a string value in the doc.
|
// Set or overwrite a string value in the doc.
|
||||||
inline void set_string(toml::Doc* doc, const char* key, const char* val) {
|
inline void set_string(toml::Doc* doc, const char* key, const char* val) {
|
||||||
auto* existing = doc->get(key);
|
auto* existing = doc->get(key);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (existing->type == toml::Type::String && existing->str)
|
detail::free_value_data(existing);
|
||||||
montauk::mfree(existing->str);
|
|
||||||
existing->type = toml::Type::String;
|
existing->type = toml::Type::String;
|
||||||
existing->str = toml::Value::dup(val);
|
existing->str = toml::Value::dup(val);
|
||||||
} else {
|
} else {
|
||||||
@@ -289,8 +389,7 @@ namespace config {
|
|||||||
inline void set_int(toml::Doc* doc, const char* key, int64_t val) {
|
inline void set_int(toml::Doc* doc, const char* key, int64_t val) {
|
||||||
auto* existing = doc->get(key);
|
auto* existing = doc->get(key);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (existing->type == toml::Type::String && existing->str)
|
detail::free_value_data(existing);
|
||||||
montauk::mfree(existing->str);
|
|
||||||
existing->type = toml::Type::Int;
|
existing->type = toml::Type::Int;
|
||||||
existing->ival = val;
|
existing->ival = val;
|
||||||
} else {
|
} else {
|
||||||
@@ -302,8 +401,7 @@ namespace config {
|
|||||||
inline void set_bool(toml::Doc* doc, const char* key, bool val) {
|
inline void set_bool(toml::Doc* doc, const char* key, bool val) {
|
||||||
auto* existing = doc->get(key);
|
auto* existing = doc->get(key);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
if (existing->type == toml::Type::String && existing->str)
|
detail::free_value_data(existing);
|
||||||
montauk::mfree(existing->str);
|
|
||||||
existing->type = toml::Type::Bool;
|
existing->type = toml::Type::Bool;
|
||||||
existing->bval = val;
|
existing->bval = val;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ namespace heap_detail {
|
|||||||
g_initialized = true;
|
g_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Guard against overflow: size + Header must not wrap
|
||||||
|
if (size > UINT64_MAX - sizeof(Header) - 15)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
uint64_t needed = size + sizeof(Header);
|
uint64_t needed = size + sizeof(Header);
|
||||||
needed = (needed + 15) & ~15ULL;
|
needed = (needed + 15) & ~15ULL;
|
||||||
|
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ namespace montauk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void strncpy(char* dst, const char* src, int max) {
|
inline void strncpy(char* dst, const char* src, int max) {
|
||||||
|
if (max <= 0) return;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (src[i] && i < max - 1) { dst[i] = src[i]; i++; }
|
while (src[i] && i < max - 1) { dst[i] = src[i]; i++; }
|
||||||
dst[i] = '\0';
|
dst[i] = '\0';
|
||||||
|
|||||||
@@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* user.h
|
||||||
|
* User database, password hashing, and authentication for MontaukOS
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/config.h>
|
||||||
|
#include <bearssl_hash.h>
|
||||||
|
|
||||||
|
namespace montauk {
|
||||||
|
namespace user {
|
||||||
|
|
||||||
|
static constexpr int MAX_USERS = 16;
|
||||||
|
|
||||||
|
struct UserInfo {
|
||||||
|
char username[32];
|
||||||
|
char display_name[64];
|
||||||
|
char password_hash[65]; // 64 hex chars + null
|
||||||
|
char salt[33]; // 32 hex chars + null
|
||||||
|
char role[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---- String helpers ----
|
||||||
|
|
||||||
|
inline void str_cat(char* dst, const char* src, int max) {
|
||||||
|
int len = montauk::slen(dst);
|
||||||
|
int i = 0;
|
||||||
|
while (src[i] && len < max - 1) {
|
||||||
|
dst[len++] = src[i++];
|
||||||
|
}
|
||||||
|
dst[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void build_user_key(char* out, int sz, const char* username, const char* field) {
|
||||||
|
int p = 0;
|
||||||
|
const char* prefix = "users.";
|
||||||
|
while (*prefix && p < sz - 1) out[p++] = *prefix++;
|
||||||
|
while (*username && p < sz - 1) out[p++] = *username++;
|
||||||
|
if (p < sz - 1) out[p++] = '.';
|
||||||
|
while (*field && p < sz - 1) out[p++] = *field++;
|
||||||
|
out[p] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Path helpers ----
|
||||||
|
|
||||||
|
inline void home_dir(const char* username, char* out, int sz) {
|
||||||
|
int p = 0;
|
||||||
|
const char* prefix = "0:/users/";
|
||||||
|
while (*prefix && p < sz - 1) out[p++] = *prefix++;
|
||||||
|
while (*username && p < sz - 1) out[p++] = *username++;
|
||||||
|
out[p] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void config_dir(const char* username, char* out, int sz) {
|
||||||
|
home_dir(username, out, sz);
|
||||||
|
str_cat(out, "/config", sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Hex conversion helpers ----
|
||||||
|
|
||||||
|
inline void bytes_to_hex(const uint8_t* bytes, int len, char* out) {
|
||||||
|
const char* digits = "0123456789abcdef";
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
out[i * 2] = digits[(bytes[i] >> 4) & 0x0F];
|
||||||
|
out[i * 2 + 1] = digits[bytes[i] & 0x0F];
|
||||||
|
}
|
||||||
|
out[len * 2] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int hex_char_val(char c) {
|
||||||
|
if (c >= '0' && c <= '9') return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f') return 10 + c - 'a';
|
||||||
|
if (c >= 'A' && c <= 'F') return 10 + c - 'A';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int hex_to_bytes(const char* hex, uint8_t* out, int maxBytes) {
|
||||||
|
int i = 0;
|
||||||
|
while (hex[i * 2] && hex[i * 2 + 1] && i < maxBytes) {
|
||||||
|
int hi = hex_char_val(hex[i * 2]);
|
||||||
|
int lo = hex_char_val(hex[i * 2 + 1]);
|
||||||
|
if (hi < 0 || lo < 0) return i;
|
||||||
|
out[i] = (uint8_t)((hi << 4) | lo);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Password hashing (SHA-256) ----
|
||||||
|
|
||||||
|
inline void hash_password(const char* password, const char* salt_hex, char* out_hex64) {
|
||||||
|
uint8_t salt_bytes[16];
|
||||||
|
int salt_len = hex_to_bytes(salt_hex, salt_bytes, 16);
|
||||||
|
int pass_len = montauk::slen(password);
|
||||||
|
|
||||||
|
br_sha256_context ctx;
|
||||||
|
br_sha256_init(&ctx);
|
||||||
|
br_sha256_update(&ctx, salt_bytes, salt_len);
|
||||||
|
br_sha256_update(&ctx, password, pass_len);
|
||||||
|
|
||||||
|
uint8_t hash[32];
|
||||||
|
br_sha256_out(&ctx, hash);
|
||||||
|
bytes_to_hex(hash, 32, out_hex64);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool verify_password(const char* password, const char* salt_hex, const char* stored_hex64) {
|
||||||
|
char computed[65];
|
||||||
|
hash_password(password, salt_hex, computed);
|
||||||
|
|
||||||
|
int diff = 0;
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
diff |= computed[i] ^ stored_hex64[i];
|
||||||
|
}
|
||||||
|
return diff == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- User database I/O ----
|
||||||
|
|
||||||
|
inline int load_users(UserInfo* buf, int max) {
|
||||||
|
auto doc = config::load("users");
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < doc.entries.count && count < max; i++) {
|
||||||
|
auto* v = doc.entries.items[i];
|
||||||
|
if (!v->key) continue;
|
||||||
|
|
||||||
|
if (!montauk::starts_with(v->key, "users.")) continue;
|
||||||
|
const char* after = v->key + 6;
|
||||||
|
|
||||||
|
int dot = -1;
|
||||||
|
for (int j = 0; after[j]; j++) {
|
||||||
|
if (after[j] == '.') { dot = j; break; }
|
||||||
|
}
|
||||||
|
if (dot <= 0) continue;
|
||||||
|
|
||||||
|
if (!montauk::streq(after + dot + 1, "display_name")) continue;
|
||||||
|
|
||||||
|
UserInfo* u = &buf[count];
|
||||||
|
montauk::memset(u, 0, sizeof(UserInfo));
|
||||||
|
int ulen = dot < 31 ? dot : 31;
|
||||||
|
montauk::memcpy(u->username, after, ulen);
|
||||||
|
u->username[ulen] = '\0';
|
||||||
|
|
||||||
|
if (v->type == montauk::toml::Type::String && v->str)
|
||||||
|
montauk::strncpy(u->display_name, v->str, sizeof(u->display_name));
|
||||||
|
|
||||||
|
char prefix[64];
|
||||||
|
int plen = 0;
|
||||||
|
const char* pfx = "users.";
|
||||||
|
while (*pfx) prefix[plen++] = *pfx++;
|
||||||
|
for (int j = 0; j < ulen; j++) prefix[plen++] = u->username[j];
|
||||||
|
prefix[plen] = '\0';
|
||||||
|
|
||||||
|
char key[96];
|
||||||
|
|
||||||
|
montauk::strcpy(key, prefix);
|
||||||
|
str_cat(key, ".password_hash", 96);
|
||||||
|
const char* ph = doc.get_string(key, "");
|
||||||
|
montauk::strncpy(u->password_hash, ph, sizeof(u->password_hash));
|
||||||
|
|
||||||
|
montauk::strcpy(key, prefix);
|
||||||
|
str_cat(key, ".salt", 96);
|
||||||
|
const char* s = doc.get_string(key, "");
|
||||||
|
montauk::strncpy(u->salt, s, sizeof(u->salt));
|
||||||
|
|
||||||
|
montauk::strcpy(key, prefix);
|
||||||
|
str_cat(key, ".role", 96);
|
||||||
|
const char* r = doc.get_string(key, "user");
|
||||||
|
montauk::strncpy(u->role, r, sizeof(u->role));
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.destroy();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int save_users(const UserInfo* buf, int count) {
|
||||||
|
montauk::toml::Doc doc;
|
||||||
|
doc.init();
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const UserInfo* u = &buf[i];
|
||||||
|
char key[96];
|
||||||
|
|
||||||
|
build_user_key(key, 96, u->username, "display_name");
|
||||||
|
config::set_string(&doc, key, u->display_name);
|
||||||
|
|
||||||
|
build_user_key(key, 96, u->username, "password_hash");
|
||||||
|
config::set_string(&doc, key, u->password_hash);
|
||||||
|
|
||||||
|
build_user_key(key, 96, u->username, "salt");
|
||||||
|
config::set_string(&doc, key, u->salt);
|
||||||
|
|
||||||
|
build_user_key(key, 96, u->username, "role");
|
||||||
|
config::set_string(&doc, key, u->role);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = config::save("users", &doc);
|
||||||
|
doc.destroy();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Authentication ----
|
||||||
|
|
||||||
|
inline bool authenticate(const char* username, const char* password) {
|
||||||
|
UserInfo users[MAX_USERS];
|
||||||
|
int count = load_users(users, MAX_USERS);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (montauk::streq(users[i].username, username)) {
|
||||||
|
return verify_password(password, users[i].salt, users[i].password_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- User management ----
|
||||||
|
|
||||||
|
inline bool create_user(const char* username, const char* display_name,
|
||||||
|
const char* password, const char* role) {
|
||||||
|
UserInfo users[MAX_USERS];
|
||||||
|
int count = load_users(users, MAX_USERS);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (montauk::streq(users[i].username, username)) return false;
|
||||||
|
}
|
||||||
|
if (count >= MAX_USERS) return false;
|
||||||
|
|
||||||
|
UserInfo* u = &users[count];
|
||||||
|
montauk::memset(u, 0, sizeof(UserInfo));
|
||||||
|
montauk::strncpy(u->username, username, 31);
|
||||||
|
montauk::strncpy(u->display_name, display_name, 63);
|
||||||
|
montauk::strncpy(u->role, role, 15);
|
||||||
|
|
||||||
|
uint8_t salt_bytes[16];
|
||||||
|
montauk::getrandom(salt_bytes, 16);
|
||||||
|
bytes_to_hex(salt_bytes, 16, u->salt);
|
||||||
|
|
||||||
|
hash_password(password, u->salt, u->password_hash);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
save_users(users, count);
|
||||||
|
|
||||||
|
// Create home directory structure
|
||||||
|
char dir[128];
|
||||||
|
home_dir(username, dir, sizeof(dir));
|
||||||
|
montauk::fmkdir(dir);
|
||||||
|
|
||||||
|
char subdir[128];
|
||||||
|
montauk::strcpy(subdir, dir);
|
||||||
|
str_cat(subdir, "/config", 128);
|
||||||
|
montauk::fmkdir(subdir);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool delete_user(const char* username) {
|
||||||
|
UserInfo users[MAX_USERS];
|
||||||
|
int count = load_users(users, MAX_USERS);
|
||||||
|
|
||||||
|
int idx = -1;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (montauk::streq(users[i].username, username)) { idx = i; break; }
|
||||||
|
}
|
||||||
|
if (idx < 0) return false;
|
||||||
|
|
||||||
|
for (int i = idx; i < count - 1; i++) {
|
||||||
|
users[i] = users[i + 1];
|
||||||
|
}
|
||||||
|
count--;
|
||||||
|
|
||||||
|
save_users(users, count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool change_password(const char* username, const char* new_password) {
|
||||||
|
UserInfo users[MAX_USERS];
|
||||||
|
int count = load_users(users, MAX_USERS);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (montauk::streq(users[i].username, username)) {
|
||||||
|
uint8_t salt_bytes[16];
|
||||||
|
montauk::getrandom(salt_bytes, 16);
|
||||||
|
bytes_to_hex(salt_bytes, 16, users[i].salt);
|
||||||
|
|
||||||
|
hash_password(new_password, users[i].salt, users[i].password_hash);
|
||||||
|
|
||||||
|
save_users(users, count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Session (current logged-in user) ----
|
||||||
|
|
||||||
|
// Write the current session after successful login.
|
||||||
|
// Stores username in 0:/config/session.toml so any app can query it.
|
||||||
|
inline void set_session(const char* username) {
|
||||||
|
montauk::toml::Doc doc;
|
||||||
|
doc.init();
|
||||||
|
config::set_string(&doc, "session.username", username);
|
||||||
|
config::save("session", &doc);
|
||||||
|
doc.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the session (on logout).
|
||||||
|
inline void clear_session() {
|
||||||
|
montauk::fdelete("0:/config/session.toml");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the current username into buf. Returns true if a session exists.
|
||||||
|
inline bool get_session_username(char* buf, int bufSz) {
|
||||||
|
auto doc = config::load("session");
|
||||||
|
const char* name = doc.get_string("session.username", "");
|
||||||
|
bool found = (name[0] != '\0');
|
||||||
|
if (found) {
|
||||||
|
montauk::strncpy(buf, name, bufSz);
|
||||||
|
}
|
||||||
|
doc.destroy();
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current user's home directory. Returns true if a session exists.
|
||||||
|
inline bool get_home_dir(char* buf, int bufSz) {
|
||||||
|
char username[32];
|
||||||
|
if (!get_session_username(username, sizeof(username))) return false;
|
||||||
|
home_dir(username, buf, bufSz);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace user
|
||||||
|
} // namespace montauk
|
||||||
@@ -395,6 +395,10 @@ void *malloc(size_t size) {
|
|||||||
g_heapInit = 1;
|
g_heapInit = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Guard against overflow: size + Header must not wrap */
|
||||||
|
if (size > (uint64_t)-1 - sizeof(struct HeapHeader) - 15)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
uint64_t needed = size + sizeof(struct HeapHeader);
|
uint64_t needed = size + sizeof(struct HeapHeader);
|
||||||
needed = (needed + 15) & ~15ULL;
|
needed = (needed + 15) & ~15ULL;
|
||||||
|
|
||||||
@@ -455,6 +459,9 @@ void free(void *ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *calloc(size_t nmemb, size_t size) {
|
void *calloc(size_t nmemb, size_t size) {
|
||||||
|
/* Check for multiplication overflow */
|
||||||
|
if (nmemb != 0 && size > (size_t)-1 / nmemb)
|
||||||
|
return NULL;
|
||||||
size_t total = nmemb * size;
|
size_t total = nmemb * size;
|
||||||
void *p = malloc(total);
|
void *p = malloc(total);
|
||||||
if (p) memset(p, 0, total);
|
if (p) memset(p, 0, total);
|
||||||
@@ -540,7 +547,36 @@ long strtol(const char *nptr, char **endptr, int base) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned long strtoul(const char *nptr, char **endptr, int base) {
|
unsigned long strtoul(const char *nptr, char **endptr, int base) {
|
||||||
return (unsigned long)strtol(nptr, endptr, base);
|
const char *s = nptr;
|
||||||
|
unsigned long val = 0;
|
||||||
|
|
||||||
|
while (isspace((unsigned char)*s)) s++;
|
||||||
|
/* strtoul allows an optional leading + or - (result is negated for -) */
|
||||||
|
int neg = 0;
|
||||||
|
if (*s == '-') { neg = 1; s++; }
|
||||||
|
else if (*s == '+') { s++; }
|
||||||
|
|
||||||
|
if (base == 0) {
|
||||||
|
if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { base = 16; s += 2; }
|
||||||
|
else if (*s == '0') { base = 8; s++; }
|
||||||
|
else base = 10;
|
||||||
|
} else if (base == 16 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) {
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*s) {
|
||||||
|
int digit;
|
||||||
|
if (*s >= '0' && *s <= '9') digit = *s - '0';
|
||||||
|
else if (*s >= 'a' && *s <= 'z') digit = *s - 'a' + 10;
|
||||||
|
else if (*s >= 'A' && *s <= 'Z') digit = *s - 'A' + 10;
|
||||||
|
else break;
|
||||||
|
if (digit >= base) break;
|
||||||
|
val = val * (unsigned long)base + (unsigned long)digit;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr) *endptr = (char *)s;
|
||||||
|
return neg ? (unsigned long)(-(long)val) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *getenv(const char *name) {
|
char *getenv(const char *name) {
|
||||||
|
|||||||
Binary file not shown.
@@ -37,7 +37,8 @@
|
|||||||
0:/games/ Games (doom)
|
0:/games/ Games (doom)
|
||||||
0:/man/ Manual pages
|
0:/man/ Manual pages
|
||||||
0:/www/ Web server content
|
0:/www/ Web server content
|
||||||
0:/home/ User home directory
|
0:/common/ Shared assets (wallpapers, etc.)
|
||||||
|
0:/users/ Per-user home directories
|
||||||
|
|
||||||
.SH SHELL
|
.SH SHELL
|
||||||
The interactive shell is the primary way to interact with
|
The interactive shell is the primary way to interact with
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ endif
|
|||||||
PROG_INC := ../../include
|
PROG_INC := ../../include
|
||||||
JPEG_LIB := ../../lib/libjpeg
|
JPEG_LIB := ../../lib/libjpeg
|
||||||
LIBC_LIB := ../../lib/libc
|
LIBC_LIB := ../../lib/libc
|
||||||
|
BEARSSL := ../../lib/bearssl
|
||||||
LINK_LD := ../../link.ld
|
LINK_LD := ../../link.ld
|
||||||
BINDIR := ../../bin
|
BINDIR := ../../bin
|
||||||
OBJDIR := obj
|
OBJDIR := obj
|
||||||
@@ -48,6 +49,8 @@ CXXFLAGS := \
|
|||||||
-mcmodel=small \
|
-mcmodel=small \
|
||||||
-MMD -MP \
|
-MMD -MP \
|
||||||
-I $(PROG_INC) \
|
-I $(PROG_INC) \
|
||||||
|
-isystem $(PROG_INC)/libc \
|
||||||
|
-I $(BEARSSL)/inc \
|
||||||
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||||
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||||
|
|
||||||
@@ -79,7 +82,7 @@ all: $(TARGET)
|
|||||||
|
|
||||||
# ---- Libraries ----
|
# ---- Libraries ----
|
||||||
|
|
||||||
LIBS := $(JPEG_LIB)/libjpeg.a $(LIBC_LIB)/liblibc.a
|
LIBS := $(JPEG_LIB)/libjpeg.a $(BEARSSL)/libbearssl.a $(LIBC_LIB)/liblibc.a
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(LIBS) $(LINK_LD) Makefile
|
$(TARGET): $(OBJS) $(LIBS) $(LINK_LD) Makefile
|
||||||
mkdir -p $(BINDIR)/os
|
mkdir -p $(BINDIR)/os
|
||||||
|
|||||||
@@ -360,7 +360,12 @@ static void filemanager_go_up(FileManagerState* fm) {
|
|||||||
if (fm->current_path[i] == '/') { last_slash = i; break; }
|
if (fm->current_path[i] == '/') { last_slash = i; break; }
|
||||||
}
|
}
|
||||||
if (last_slash >= 0) {
|
if (last_slash >= 0) {
|
||||||
fm->current_path[last_slash + 1] = '\0';
|
// Keep the slash only if it's the root slash (right after "N:")
|
||||||
|
if (last_slash > 0 && fm->current_path[last_slash - 1] == ':') {
|
||||||
|
fm->current_path[last_slash + 1] = '\0';
|
||||||
|
} else {
|
||||||
|
fm->current_path[last_slash] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
filemanager_push_history(fm);
|
filemanager_push_history(fm);
|
||||||
filemanager_read_dir(fm);
|
filemanager_read_dir(fm);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "apps_common.hpp"
|
#include "apps_common.hpp"
|
||||||
#include "../wallpaper.hpp"
|
#include "../wallpaper.hpp"
|
||||||
|
#include <montauk/config.h>
|
||||||
|
#include <montauk/user.h>
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Settings state
|
// Settings state
|
||||||
@@ -13,11 +15,20 @@
|
|||||||
|
|
||||||
struct SettingsState {
|
struct SettingsState {
|
||||||
DesktopState* desktop;
|
DesktopState* desktop;
|
||||||
int active_tab; // 0=Appearance, 1=Display, 2=About
|
int active_tab; // 0=Appearance, 1=Display, 2=Users, 3=About
|
||||||
Montauk::SysInfo sys_info;
|
Montauk::SysInfo sys_info;
|
||||||
uint64_t uptime_ms;
|
uint64_t uptime_ms;
|
||||||
WallpaperFileList wp_files;
|
WallpaperFileList wp_files;
|
||||||
bool wp_scanned;
|
bool wp_scanned;
|
||||||
|
|
||||||
|
// Users tab
|
||||||
|
montauk::user::UserInfo users[16];
|
||||||
|
int user_count;
|
||||||
|
int selected_user; // index into users[], or -1
|
||||||
|
bool users_loaded;
|
||||||
|
|
||||||
|
char status_msg[128];
|
||||||
|
uint64_t status_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -69,8 +80,8 @@ static const Color accent_palette[SWATCH_COUNT] = {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
static constexpr int TAB_BAR_H = 36;
|
static constexpr int TAB_BAR_H = 36;
|
||||||
static constexpr int TAB_COUNT = 3;
|
static constexpr int TAB_COUNT = 4;
|
||||||
static const char* tab_labels[TAB_COUNT] = { "Appearance", "Display", "About" };
|
static const char* tab_labels[TAB_COUNT] = { "Appearance", "Display", "Users", "About" };
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Helper: check if two colors match
|
// Helper: check if two colors match
|
||||||
@@ -166,11 +177,11 @@ static void settings_draw_appearance(Canvas& c, SettingsState* st) {
|
|||||||
if (mode_image) {
|
if (mode_image) {
|
||||||
// Scan for images lazily
|
// Scan for images lazily
|
||||||
if (!st->wp_scanned) {
|
if (!st->wp_scanned) {
|
||||||
wallpaper_scan_dir("0:/home", &st->wp_files);
|
wallpaper_scan_dir(st->desktop->home_dir, &st->wp_files);
|
||||||
st->wp_scanned = true;
|
st->wp_scanned = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.text(x, y, "Images in 0:/home/", dim);
|
c.text(x, y, "Wallpapers", dim);
|
||||||
y += sfh + 6;
|
y += sfh + 6;
|
||||||
|
|
||||||
if (st->wp_files.count == 0) {
|
if (st->wp_files.count == 0) {
|
||||||
@@ -180,7 +191,8 @@ static void settings_draw_appearance(Canvas& c, SettingsState* st) {
|
|||||||
for (int i = 0; i < st->wp_files.count && i < 8; i++) {
|
for (int i = 0; i < st->wp_files.count && i < 8; i++) {
|
||||||
// Build full path for comparison
|
// Build full path for comparison
|
||||||
char fullpath[256];
|
char fullpath[256];
|
||||||
montauk::strcpy(fullpath, "0:/home/");
|
montauk::strcpy(fullpath, st->desktop->home_dir);
|
||||||
|
str_append(fullpath, "/", 256);
|
||||||
str_append(fullpath, st->wp_files.names[i], 256);
|
str_append(fullpath, st->wp_files.names[i], 256);
|
||||||
|
|
||||||
bool selected = s.bg_image &&
|
bool selected = s.bg_image &&
|
||||||
@@ -333,6 +345,702 @@ static void settings_draw_about(Canvas& c, SettingsState* st) {
|
|||||||
c.text(x, y, "Copyright (c) 2026 Daniel Hammer", dim);
|
c.text(x, y, "Copyright (c) 2026 Daniel Hammer", dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Config persistence
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int64_t color_to_int(Color c) {
|
||||||
|
return ((int64_t)c.r << 16) | ((int64_t)c.g << 8) | c.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color int_to_color(int64_t v) {
|
||||||
|
return Color::from_rgb((uint8_t)((v >> 16) & 0xFF),
|
||||||
|
(uint8_t)((v >> 8) & 0xFF),
|
||||||
|
(uint8_t)(v & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void settings_persist(SettingsState* st) {
|
||||||
|
DesktopSettings& s = st->desktop->settings;
|
||||||
|
const char* user = st->desktop->current_user;
|
||||||
|
|
||||||
|
montauk::toml::Doc doc;
|
||||||
|
doc.init();
|
||||||
|
|
||||||
|
// Background mode
|
||||||
|
const char* mode = s.bg_image ? "image" : (s.bg_gradient ? "gradient" : "solid");
|
||||||
|
montauk::config::set_string(&doc, "background.mode", mode);
|
||||||
|
|
||||||
|
// Wallpaper path
|
||||||
|
if (s.bg_image && s.bg_image_path[0])
|
||||||
|
montauk::config::set_string(&doc, "wallpaper.path", s.bg_image_path);
|
||||||
|
|
||||||
|
// Background colors
|
||||||
|
montauk::config::set_int(&doc, "background.solid_color", color_to_int(s.bg_solid));
|
||||||
|
montauk::config::set_int(&doc, "background.grad_top", color_to_int(s.bg_grad_top));
|
||||||
|
montauk::config::set_int(&doc, "background.grad_bottom", color_to_int(s.bg_grad_bottom));
|
||||||
|
|
||||||
|
// Appearance
|
||||||
|
montauk::config::set_int(&doc, "appearance.panel_color", color_to_int(s.panel_color));
|
||||||
|
montauk::config::set_int(&doc, "appearance.accent_color", color_to_int(s.accent_color));
|
||||||
|
|
||||||
|
// Display
|
||||||
|
montauk::config::set_int(&doc, "display.ui_scale", s.ui_scale);
|
||||||
|
montauk::config::set_bool(&doc, "display.clock_24h", s.clock_24h);
|
||||||
|
montauk::config::set_bool(&doc, "display.show_shadows", s.show_shadows);
|
||||||
|
|
||||||
|
montauk::config::save_user(user, "desktop", &doc);
|
||||||
|
doc.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Users tab
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void users_reload(SettingsState* st) {
|
||||||
|
st->user_count = montauk::user::load_users(st->users, 16);
|
||||||
|
st->users_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr int USER_BTN_H = 30;
|
||||||
|
static constexpr int USER_BTN_W = 100;
|
||||||
|
static constexpr int USER_FIELD_H = 32;
|
||||||
|
|
||||||
|
// Forward declarations for dialog openers
|
||||||
|
static void open_add_user_dialog(SettingsState* st);
|
||||||
|
static void open_change_pwd_dialog(SettingsState* st);
|
||||||
|
static void open_delete_user_dialog(SettingsState* st);
|
||||||
|
|
||||||
|
static int user_row_height() {
|
||||||
|
return system_font_height() * 2 + 12; // Two lines of text + padding
|
||||||
|
}
|
||||||
|
|
||||||
|
static void settings_draw_users(Canvas& c, SettingsState* st) {
|
||||||
|
if (!st->users_loaded) users_reload(st);
|
||||||
|
|
||||||
|
Color accent = st->desktop->settings.accent_color;
|
||||||
|
Color dim = Color::from_rgb(0x88, 0x88, 0x88);
|
||||||
|
Color card_bg = Color::from_rgb(0xF8, 0xF8, 0xF8);
|
||||||
|
int x = 16;
|
||||||
|
int y = 20;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int content_w = c.w - 2 * x;
|
||||||
|
int row_h = user_row_height();
|
||||||
|
|
||||||
|
if (!st->desktop->is_admin) {
|
||||||
|
c.text(x, y, "Admin access required to manage users.", dim);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// User list
|
||||||
|
for (int i = 0; i < st->user_count; i++) {
|
||||||
|
bool sel = (i == st->selected_user);
|
||||||
|
bool is_current = montauk::streq(st->users[i].username, st->desktop->current_user);
|
||||||
|
|
||||||
|
if (sel) {
|
||||||
|
c.fill_rounded_rect(x, y, content_w, row_h, 4, accent);
|
||||||
|
} else if (i % 2 == 0) {
|
||||||
|
c.fill_rounded_rect(x, y, content_w, row_h, 4, card_bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color tc = sel ? colors::WHITE : colors::TEXT_COLOR;
|
||||||
|
Color sc = sel ? Color::from_rgb(0xDD, 0xDD, 0xFF) : dim;
|
||||||
|
|
||||||
|
// Display name (primary line)
|
||||||
|
int text_y = y + 4;
|
||||||
|
c.text(x + 12, text_y, st->users[i].display_name, tc);
|
||||||
|
|
||||||
|
// Username (secondary line)
|
||||||
|
char sub[48];
|
||||||
|
if (is_current) {
|
||||||
|
snprintf(sub, sizeof(sub), "@%s (you)", st->users[i].username);
|
||||||
|
} else {
|
||||||
|
snprintf(sub, sizeof(sub), "@%s", st->users[i].username);
|
||||||
|
}
|
||||||
|
c.text(x + 12, text_y + sfh + 2, sub, sc);
|
||||||
|
|
||||||
|
// Role badge
|
||||||
|
const char* role = st->users[i].role;
|
||||||
|
int rw = text_width(role) + 12;
|
||||||
|
int badge_x = c.w - x - rw - 8;
|
||||||
|
int badge_y = y + (row_h - sfh - 4) / 2;
|
||||||
|
if (sel) {
|
||||||
|
c.fill_rounded_rect(badge_x, badge_y, rw, sfh + 4, (sfh + 4) / 2,
|
||||||
|
Color::from_rgb(0xFF, 0xFF, 0xFF));
|
||||||
|
c.text(badge_x + 6, badge_y + 2, role, accent);
|
||||||
|
} else {
|
||||||
|
bool is_admin_role = montauk::streq(role, "admin");
|
||||||
|
Color badge_bg = is_admin_role
|
||||||
|
? Color::from_rgb(0xE8, 0xD8, 0xF0)
|
||||||
|
: Color::from_rgb(0xE0, 0xE8, 0xF0);
|
||||||
|
Color badge_fg = is_admin_role
|
||||||
|
? Color::from_rgb(0x7B, 0x3E, 0xB8)
|
||||||
|
: Color::from_rgb(0x36, 0x7B, 0xF0);
|
||||||
|
c.fill_rounded_rect(badge_x, badge_y, rw, sfh + 4, (sfh + 4) / 2, badge_bg);
|
||||||
|
c.text(badge_x + 6, badge_y + 2, role, badge_fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
y += row_h + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
y += 8;
|
||||||
|
c.hline(x, y, content_w, colors::BORDER);
|
||||||
|
y += 16;
|
||||||
|
|
||||||
|
// Status message
|
||||||
|
if (st->status_msg[0] && (montauk::get_milliseconds() - st->status_time < 3000)) {
|
||||||
|
c.text(x, y, st->status_msg, accent);
|
||||||
|
y += sfh + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action buttons
|
||||||
|
int btn_x = x;
|
||||||
|
|
||||||
|
// Add User
|
||||||
|
c.fill_rounded_rect(btn_x, y, 90, USER_BTN_H, 4, accent);
|
||||||
|
{
|
||||||
|
int tw = text_width("Add User");
|
||||||
|
c.text(btn_x + (90 - tw) / 2, y + (USER_BTN_H - sfh) / 2, "Add User", colors::WHITE);
|
||||||
|
}
|
||||||
|
btn_x += 98;
|
||||||
|
|
||||||
|
// Change Password (disabled when no selection)
|
||||||
|
{
|
||||||
|
bool enabled = st->selected_user >= 0;
|
||||||
|
Color bg = enabled ? accent : Color::from_rgb(0xCC, 0xCC, 0xCC);
|
||||||
|
c.fill_rounded_rect(btn_x, y, USER_BTN_W, USER_BTN_H, 4, bg);
|
||||||
|
int tw = text_width("Change Pwd");
|
||||||
|
c.text(btn_x + (USER_BTN_W - tw) / 2, y + (USER_BTN_H - sfh) / 2, "Change Pwd", colors::WHITE);
|
||||||
|
}
|
||||||
|
btn_x += USER_BTN_W + 8;
|
||||||
|
|
||||||
|
// Delete (disabled when no selection)
|
||||||
|
{
|
||||||
|
bool enabled = st->selected_user >= 0;
|
||||||
|
Color del_bg = enabled ? Color::from_rgb(0xD0, 0x3E, 0x3E) : Color::from_rgb(0xCC, 0xCC, 0xCC);
|
||||||
|
c.fill_rounded_rect(btn_x, y, 70, USER_BTN_H, 4, del_bg);
|
||||||
|
int tw = text_width("Delete");
|
||||||
|
c.text(btn_x + (70 - tw) / 2, y + (USER_BTN_H - sfh) / 2, "Delete", colors::WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Dialog helpers
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void dialog_append(char* buf, int* len, int max, char ch) {
|
||||||
|
if (*len < max - 1) { buf[*len] = ch; (*len)++; buf[*len] = '\0'; }
|
||||||
|
}
|
||||||
|
static void dialog_backspace(char* buf, int* len) {
|
||||||
|
if (*len > 0) { (*len)--; buf[*len] = '\0'; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dialog_close_self(DesktopState* ds, void* app_data) {
|
||||||
|
for (int i = 0; i < ds->window_count; i++) {
|
||||||
|
if (ds->windows[i].app_data == app_data) {
|
||||||
|
desktop_close_window(ds, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_input_field(Canvas& c, int x, int y, int w, int h,
|
||||||
|
const char* label, const char* value,
|
||||||
|
bool focused, bool masked, Color accent) {
|
||||||
|
int sfh = system_font_height();
|
||||||
|
Color dim = Color::from_rgb(0x88, 0x88, 0x88);
|
||||||
|
|
||||||
|
c.text(x, y, label, dim);
|
||||||
|
y += sfh + 2;
|
||||||
|
Color border = focused ? accent : colors::BORDER;
|
||||||
|
c.fill_rounded_rect(x, y, w, h, 3, Color::from_rgb(0xF5, 0xF5, 0xF5));
|
||||||
|
c.rect(x, y, w, h, border);
|
||||||
|
|
||||||
|
if (masked) {
|
||||||
|
int vlen = montauk::slen(value);
|
||||||
|
char dots[65];
|
||||||
|
for (int i = 0; i < vlen && i < 64; i++) dots[i] = '*';
|
||||||
|
dots[vlen < 64 ? vlen : 64] = '\0';
|
||||||
|
c.text(x + 8, y + (h - sfh) / 2, dots, colors::TEXT_COLOR);
|
||||||
|
} else {
|
||||||
|
c.text(x + 8, y + (h - sfh) / 2, value, colors::TEXT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (focused) {
|
||||||
|
int tw = masked ? text_width("*") * montauk::slen(value) : text_width(value);
|
||||||
|
c.fill_rect(x + 8 + tw, y + 6, 2, h - 12, accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Add User Dialog
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
struct AddUserDialogState {
|
||||||
|
DesktopState* ds;
|
||||||
|
SettingsState* parent;
|
||||||
|
Color accent;
|
||||||
|
int field; // 0=username, 1=display_name, 2=password
|
||||||
|
char username[32]; int username_len;
|
||||||
|
char display[64]; int display_len;
|
||||||
|
char password[64]; int password_len;
|
||||||
|
bool role_admin;
|
||||||
|
char error[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void adduser_on_draw(Window* win, Framebuffer& fb) {
|
||||||
|
AddUserDialogState* st = (AddUserDialogState*)win->app_data;
|
||||||
|
if (!st) return;
|
||||||
|
|
||||||
|
Canvas c(win);
|
||||||
|
c.fill(colors::WINDOW_BG);
|
||||||
|
Color accent = st->accent;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int pad = 16;
|
||||||
|
int fw = c.w - 2 * pad;
|
||||||
|
int y = pad;
|
||||||
|
|
||||||
|
// Fields
|
||||||
|
draw_input_field(c, pad, y, fw, USER_FIELD_H, "Username", st->username,
|
||||||
|
st->field == 0, false, accent);
|
||||||
|
y += sfh + 2 + USER_FIELD_H + 10;
|
||||||
|
|
||||||
|
draw_input_field(c, pad, y, fw, USER_FIELD_H, "Display Name", st->display,
|
||||||
|
st->field == 1, false, accent);
|
||||||
|
y += sfh + 2 + USER_FIELD_H + 10;
|
||||||
|
|
||||||
|
draw_input_field(c, pad, y, fw, USER_FIELD_H, "Password", st->password,
|
||||||
|
st->field == 2, true, accent);
|
||||||
|
y += sfh + 2 + USER_FIELD_H + 12;
|
||||||
|
|
||||||
|
// Role toggle
|
||||||
|
Color dim = Color::from_rgb(0x88, 0x88, 0x88);
|
||||||
|
c.text(pad, y + 4, "Role:", dim);
|
||||||
|
int rbx = pad + 60;
|
||||||
|
draw_toggle_btn(c, rbx, y, 60, USER_BTN_H, "User", !st->role_admin, accent);
|
||||||
|
draw_toggle_btn(c, rbx + 68, y, 60, USER_BTN_H, "Admin", st->role_admin, accent);
|
||||||
|
y += USER_BTN_H + 14;
|
||||||
|
|
||||||
|
// Error message
|
||||||
|
if (st->error[0]) {
|
||||||
|
c.text(pad, y, st->error, Color::from_rgb(0xD0, 0x3E, 0x3E));
|
||||||
|
y += sfh + 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons at bottom
|
||||||
|
int btn_y = c.h - USER_BTN_H - pad;
|
||||||
|
c.fill_rounded_rect(pad, btn_y, 80, USER_BTN_H, 4, accent);
|
||||||
|
int tw = text_width("Create");
|
||||||
|
c.text(pad + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Create", colors::WHITE);
|
||||||
|
|
||||||
|
c.fill_rounded_rect(pad + 88, btn_y, 80, USER_BTN_H, 4, colors::WINDOW_BG);
|
||||||
|
c.rect(pad + 88, btn_y, 80, USER_BTN_H, colors::BORDER);
|
||||||
|
tw = text_width("Cancel");
|
||||||
|
c.text(pad + 88 + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Cancel", colors::TEXT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adduser_submit(AddUserDialogState* st) {
|
||||||
|
if (st->username_len == 0) {
|
||||||
|
montauk::strcpy(st->error, "Username is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (st->password_len == 0) {
|
||||||
|
montauk::strcpy(st->error, "Password is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char* dname = st->display_len > 0 ? st->display : st->username;
|
||||||
|
const char* role = st->role_admin ? "admin" : "user";
|
||||||
|
if (montauk::user::create_user(st->username, dname, st->password, role)) {
|
||||||
|
st->parent->users_loaded = false;
|
||||||
|
montauk::strcpy(st->parent->status_msg, "User created");
|
||||||
|
st->parent->status_time = montauk::get_milliseconds();
|
||||||
|
dialog_close_self(st->ds, st);
|
||||||
|
} else {
|
||||||
|
montauk::strcpy(st->error, "Failed (username taken?)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adduser_on_mouse(Window* win, MouseEvent& ev) {
|
||||||
|
AddUserDialogState* st = (AddUserDialogState*)win->app_data;
|
||||||
|
if (!st || !ev.left_pressed()) return;
|
||||||
|
|
||||||
|
Rect cr = win->content_rect();
|
||||||
|
int mx = ev.x - cr.x;
|
||||||
|
int my = ev.y - cr.y;
|
||||||
|
int pad = 16;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int fw = win->content_w - 2 * pad;
|
||||||
|
int y = pad;
|
||||||
|
|
||||||
|
// Username field hit
|
||||||
|
y += sfh + 2;
|
||||||
|
if (my >= y && my < y + USER_FIELD_H) { st->field = 0; return; }
|
||||||
|
y += USER_FIELD_H + 10;
|
||||||
|
|
||||||
|
// Display field hit
|
||||||
|
y += sfh + 2;
|
||||||
|
if (my >= y && my < y + USER_FIELD_H) { st->field = 1; return; }
|
||||||
|
y += USER_FIELD_H + 10;
|
||||||
|
|
||||||
|
// Password field hit
|
||||||
|
y += sfh + 2;
|
||||||
|
if (my >= y && my < y + USER_FIELD_H) { st->field = 2; return; }
|
||||||
|
y += USER_FIELD_H + 12;
|
||||||
|
|
||||||
|
// Role toggle
|
||||||
|
int rbx = pad + 60;
|
||||||
|
if (mx >= rbx && mx < rbx + 60 && my >= y && my < y + USER_BTN_H) {
|
||||||
|
st->role_admin = false; return;
|
||||||
|
}
|
||||||
|
if (mx >= rbx + 68 && mx < rbx + 128 && my >= y && my < y + USER_BTN_H) {
|
||||||
|
st->role_admin = true; return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bottom buttons
|
||||||
|
int btn_y = win->content_h - USER_BTN_H - pad;
|
||||||
|
if (my >= btn_y && my < btn_y + USER_BTN_H) {
|
||||||
|
if (mx >= pad && mx < pad + 80) { adduser_submit(st); return; }
|
||||||
|
if (mx >= pad + 88 && mx < pad + 168) { dialog_close_self(st->ds, st); return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adduser_on_key(Window* win, const Montauk::KeyEvent& key) {
|
||||||
|
AddUserDialogState* st = (AddUserDialogState*)win->app_data;
|
||||||
|
if (!st || !key.pressed) return;
|
||||||
|
|
||||||
|
if (key.ascii == '\n' || key.ascii == '\r' || key.scancode == 0x1C) {
|
||||||
|
adduser_submit(st); return;
|
||||||
|
}
|
||||||
|
if (key.scancode == 0x01) { dialog_close_self(st->ds, st); return; }
|
||||||
|
if (key.scancode == 0x0F) { st->field = (st->field + 1) % 3; return; }
|
||||||
|
if (key.ascii == '\b' || key.scancode == 0x0E) {
|
||||||
|
switch (st->field) {
|
||||||
|
case 0: dialog_backspace(st->username, &st->username_len); break;
|
||||||
|
case 1: dialog_backspace(st->display, &st->display_len); break;
|
||||||
|
case 2: dialog_backspace(st->password, &st->password_len); break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (key.ascii >= 0x20 && key.ascii < 0x7F) {
|
||||||
|
switch (st->field) {
|
||||||
|
case 0: dialog_append(st->username, &st->username_len, 31, key.ascii); break;
|
||||||
|
case 1: dialog_append(st->display, &st->display_len, 63, key.ascii); break;
|
||||||
|
case 2: dialog_append(st->password, &st->password_len, 63, key.ascii); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adduser_on_close(Window* win) {
|
||||||
|
if (win->app_data) { montauk::mfree(win->app_data); win->app_data = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void open_add_user_dialog(SettingsState* parent) {
|
||||||
|
DesktopState* ds = parent->desktop;
|
||||||
|
int w = 340, h = 340;
|
||||||
|
int wx = (ds->screen_w - w) / 2;
|
||||||
|
int wy = (ds->screen_h - h) / 2;
|
||||||
|
int idx = desktop_create_window(ds, "Add User", wx, wy, w, h);
|
||||||
|
if (idx < 0) return;
|
||||||
|
|
||||||
|
Window* win = &ds->windows[idx];
|
||||||
|
AddUserDialogState* st = (AddUserDialogState*)montauk::malloc(sizeof(AddUserDialogState));
|
||||||
|
montauk::memset(st, 0, sizeof(AddUserDialogState));
|
||||||
|
st->ds = ds;
|
||||||
|
st->parent = parent;
|
||||||
|
st->accent = ds->settings.accent_color;
|
||||||
|
|
||||||
|
win->app_data = st;
|
||||||
|
win->on_draw = adduser_on_draw;
|
||||||
|
win->on_mouse = adduser_on_mouse;
|
||||||
|
win->on_key = adduser_on_key;
|
||||||
|
win->on_close = adduser_on_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Change Password Dialog
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
struct ChPwdDialogState {
|
||||||
|
DesktopState* ds;
|
||||||
|
SettingsState* parent;
|
||||||
|
Color accent;
|
||||||
|
char username[32];
|
||||||
|
char display_name[64];
|
||||||
|
int field; // 0=new, 1=confirm
|
||||||
|
char new_pwd[64]; int new_len;
|
||||||
|
char confirm[64]; int confirm_len;
|
||||||
|
char error[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void chpwd_on_draw(Window* win, Framebuffer& fb) {
|
||||||
|
ChPwdDialogState* st = (ChPwdDialogState*)win->app_data;
|
||||||
|
if (!st) return;
|
||||||
|
|
||||||
|
Canvas c(win);
|
||||||
|
c.fill(colors::WINDOW_BG);
|
||||||
|
Color accent = st->accent;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int pad = 16;
|
||||||
|
int fw = c.w - 2 * pad;
|
||||||
|
int y = pad;
|
||||||
|
|
||||||
|
// Title
|
||||||
|
char title[80];
|
||||||
|
snprintf(title, sizeof(title), "Change password for %s", st->display_name);
|
||||||
|
c.text(pad, y, title, colors::TEXT_COLOR);
|
||||||
|
y += sfh + 12;
|
||||||
|
|
||||||
|
draw_input_field(c, pad, y, fw, USER_FIELD_H, "New Password", st->new_pwd,
|
||||||
|
st->field == 0, true, accent);
|
||||||
|
y += sfh + 2 + USER_FIELD_H + 10;
|
||||||
|
|
||||||
|
draw_input_field(c, pad, y, fw, USER_FIELD_H, "Confirm Password", st->confirm,
|
||||||
|
st->field == 1, true, accent);
|
||||||
|
y += sfh + 2 + USER_FIELD_H + 12;
|
||||||
|
|
||||||
|
// Error
|
||||||
|
if (st->error[0]) {
|
||||||
|
c.text(pad, y, st->error, Color::from_rgb(0xD0, 0x3E, 0x3E));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons at bottom
|
||||||
|
int btn_y = c.h - USER_BTN_H - pad;
|
||||||
|
c.fill_rounded_rect(pad, btn_y, 80, USER_BTN_H, 4, accent);
|
||||||
|
int tw = text_width("Save");
|
||||||
|
c.text(pad + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Save", colors::WHITE);
|
||||||
|
|
||||||
|
c.fill_rounded_rect(pad + 88, btn_y, 80, USER_BTN_H, 4, colors::WINDOW_BG);
|
||||||
|
c.rect(pad + 88, btn_y, 80, USER_BTN_H, colors::BORDER);
|
||||||
|
tw = text_width("Cancel");
|
||||||
|
c.text(pad + 88 + (80 - tw) / 2, btn_y + (USER_BTN_H - sfh) / 2, "Cancel", colors::TEXT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chpwd_submit(ChPwdDialogState* st) {
|
||||||
|
if (st->new_len == 0) {
|
||||||
|
montauk::strcpy(st->error, "Password cannot be empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!montauk::streq(st->new_pwd, st->confirm)) {
|
||||||
|
montauk::strcpy(st->error, "Passwords don't match");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
montauk::user::change_password(st->username, st->new_pwd);
|
||||||
|
montauk::strcpy(st->parent->status_msg, "Password changed");
|
||||||
|
st->parent->status_time = montauk::get_milliseconds();
|
||||||
|
dialog_close_self(st->ds, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chpwd_on_mouse(Window* win, MouseEvent& ev) {
|
||||||
|
ChPwdDialogState* st = (ChPwdDialogState*)win->app_data;
|
||||||
|
if (!st || !ev.left_pressed()) return;
|
||||||
|
|
||||||
|
Rect cr = win->content_rect();
|
||||||
|
int mx = ev.x - cr.x;
|
||||||
|
int my = ev.y - cr.y;
|
||||||
|
int pad = 16;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int y = pad + sfh + 12;
|
||||||
|
|
||||||
|
// New password field
|
||||||
|
y += sfh + 2;
|
||||||
|
if (my >= y && my < y + USER_FIELD_H) { st->field = 0; return; }
|
||||||
|
y += USER_FIELD_H + 10;
|
||||||
|
|
||||||
|
// Confirm field
|
||||||
|
y += sfh + 2;
|
||||||
|
if (my >= y && my < y + USER_FIELD_H) { st->field = 1; return; }
|
||||||
|
|
||||||
|
// Bottom buttons
|
||||||
|
int btn_y = win->content_h - USER_BTN_H - pad;
|
||||||
|
if (my >= btn_y && my < btn_y + USER_BTN_H) {
|
||||||
|
if (mx >= pad && mx < pad + 80) { chpwd_submit(st); return; }
|
||||||
|
if (mx >= pad + 88 && mx < pad + 168) { dialog_close_self(st->ds, st); return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chpwd_on_key(Window* win, const Montauk::KeyEvent& key) {
|
||||||
|
ChPwdDialogState* st = (ChPwdDialogState*)win->app_data;
|
||||||
|
if (!st || !key.pressed) return;
|
||||||
|
|
||||||
|
if (key.ascii == '\n' || key.ascii == '\r' || key.scancode == 0x1C) {
|
||||||
|
chpwd_submit(st); return;
|
||||||
|
}
|
||||||
|
if (key.scancode == 0x01) { dialog_close_self(st->ds, st); return; }
|
||||||
|
if (key.scancode == 0x0F) { st->field = (st->field + 1) % 2; return; }
|
||||||
|
if (key.ascii == '\b' || key.scancode == 0x0E) {
|
||||||
|
if (st->field == 0) dialog_backspace(st->new_pwd, &st->new_len);
|
||||||
|
else dialog_backspace(st->confirm, &st->confirm_len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (key.ascii >= 0x20 && key.ascii < 0x7F) {
|
||||||
|
if (st->field == 0) dialog_append(st->new_pwd, &st->new_len, 63, key.ascii);
|
||||||
|
else dialog_append(st->confirm, &st->confirm_len, 63, key.ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void chpwd_on_close(Window* win) {
|
||||||
|
if (win->app_data) { montauk::mfree(win->app_data); win->app_data = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void open_change_pwd_dialog(SettingsState* parent) {
|
||||||
|
if (parent->selected_user < 0) return;
|
||||||
|
DesktopState* ds = parent->desktop;
|
||||||
|
int w = 340, h = 260;
|
||||||
|
int wx = (ds->screen_w - w) / 2;
|
||||||
|
int wy = (ds->screen_h - h) / 2;
|
||||||
|
int idx = desktop_create_window(ds, "Change Password", wx, wy, w, h);
|
||||||
|
if (idx < 0) return;
|
||||||
|
|
||||||
|
Window* win = &ds->windows[idx];
|
||||||
|
ChPwdDialogState* st = (ChPwdDialogState*)montauk::malloc(sizeof(ChPwdDialogState));
|
||||||
|
montauk::memset(st, 0, sizeof(ChPwdDialogState));
|
||||||
|
st->ds = ds;
|
||||||
|
st->parent = parent;
|
||||||
|
st->accent = ds->settings.accent_color;
|
||||||
|
montauk::strncpy(st->username, parent->users[parent->selected_user].username, 31);
|
||||||
|
montauk::strncpy(st->display_name, parent->users[parent->selected_user].display_name, 63);
|
||||||
|
|
||||||
|
win->app_data = st;
|
||||||
|
win->on_draw = chpwd_on_draw;
|
||||||
|
win->on_mouse = chpwd_on_mouse;
|
||||||
|
win->on_key = chpwd_on_key;
|
||||||
|
win->on_close = chpwd_on_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Delete User Dialog
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
struct DeleteUserDialogState {
|
||||||
|
DesktopState* ds;
|
||||||
|
SettingsState* parent;
|
||||||
|
char username[32];
|
||||||
|
bool hover_delete, hover_cancel;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void deluser_on_draw(Window* win, Framebuffer& fb) {
|
||||||
|
DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data;
|
||||||
|
if (!st) return;
|
||||||
|
|
||||||
|
Canvas c(win);
|
||||||
|
c.fill(colors::WINDOW_BG);
|
||||||
|
int sfh = system_font_height();
|
||||||
|
|
||||||
|
char msg[96];
|
||||||
|
snprintf(msg, sizeof(msg), "Delete user \"%s\"?", st->username);
|
||||||
|
int tw = text_width(msg);
|
||||||
|
c.text((c.w - tw) / 2, 24, msg, colors::TEXT_COLOR);
|
||||||
|
|
||||||
|
const char* warn = "This action cannot be undone.";
|
||||||
|
tw = text_width(warn);
|
||||||
|
c.text((c.w - tw) / 2, 24 + sfh + 8, warn, Color::from_rgb(0x88, 0x88, 0x88));
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
int btn_w = 100, btn_h = 32;
|
||||||
|
int btn_y = c.h - btn_h - 20;
|
||||||
|
int gap = 20;
|
||||||
|
int total = btn_w * 2 + gap;
|
||||||
|
int bx = (c.w - total) / 2;
|
||||||
|
|
||||||
|
Color del_bg = st->hover_delete
|
||||||
|
? Color::from_rgb(0xDD, 0x44, 0x44)
|
||||||
|
: Color::from_rgb(0xD0, 0x3E, 0x3E);
|
||||||
|
c.button(bx, btn_y, btn_w, btn_h, "Delete", del_bg, colors::WHITE, 4);
|
||||||
|
|
||||||
|
Color cancel_bg = st->hover_cancel
|
||||||
|
? Color::from_rgb(0x99, 0x99, 0x99)
|
||||||
|
: Color::from_rgb(0x88, 0x88, 0x88);
|
||||||
|
c.button(bx + btn_w + gap, btn_y, btn_w, btn_h, "Cancel", cancel_bg, colors::WHITE, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deluser_on_mouse(Window* win, MouseEvent& ev) {
|
||||||
|
DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data;
|
||||||
|
if (!st) return;
|
||||||
|
|
||||||
|
Rect cr = win->content_rect();
|
||||||
|
int lx = ev.x - cr.x;
|
||||||
|
int ly = ev.y - cr.y;
|
||||||
|
|
||||||
|
int btn_w = 100, btn_h = 32;
|
||||||
|
int btn_y = win->content_h - btn_h - 20;
|
||||||
|
int gap = 20;
|
||||||
|
int total = btn_w * 2 + gap;
|
||||||
|
int bx = (win->content_w - total) / 2;
|
||||||
|
|
||||||
|
Rect db = {bx, btn_y, btn_w, btn_h};
|
||||||
|
Rect cb = {bx + btn_w + gap, btn_y, btn_w, btn_h};
|
||||||
|
st->hover_delete = db.contains(lx, ly);
|
||||||
|
st->hover_cancel = cb.contains(lx, ly);
|
||||||
|
|
||||||
|
if (ev.left_pressed()) {
|
||||||
|
if (st->hover_delete) {
|
||||||
|
montauk::user::delete_user(st->username);
|
||||||
|
st->parent->users_loaded = false;
|
||||||
|
st->parent->selected_user = -1;
|
||||||
|
montauk::strcpy(st->parent->status_msg, "User deleted");
|
||||||
|
st->parent->status_time = montauk::get_milliseconds();
|
||||||
|
dialog_close_self(st->ds, st);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (st->hover_cancel) {
|
||||||
|
dialog_close_self(st->ds, st);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deluser_on_key(Window* win, const Montauk::KeyEvent& key) {
|
||||||
|
DeleteUserDialogState* st = (DeleteUserDialogState*)win->app_data;
|
||||||
|
if (!st || !key.pressed) return;
|
||||||
|
|
||||||
|
if (key.ascii == '\n' || key.ascii == '\r') {
|
||||||
|
montauk::user::delete_user(st->username);
|
||||||
|
st->parent->users_loaded = false;
|
||||||
|
st->parent->selected_user = -1;
|
||||||
|
montauk::strcpy(st->parent->status_msg, "User deleted");
|
||||||
|
st->parent->status_time = montauk::get_milliseconds();
|
||||||
|
dialog_close_self(st->ds, st);
|
||||||
|
}
|
||||||
|
if (key.scancode == 0x01) {
|
||||||
|
dialog_close_self(st->ds, st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deluser_on_close(Window* win) {
|
||||||
|
if (win->app_data) { montauk::mfree(win->app_data); win->app_data = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void open_delete_user_dialog(SettingsState* parent) {
|
||||||
|
if (parent->selected_user < 0) return;
|
||||||
|
DesktopState* ds = parent->desktop;
|
||||||
|
|
||||||
|
// Don't allow deleting yourself
|
||||||
|
if (montauk::streq(parent->users[parent->selected_user].username, ds->current_user)) {
|
||||||
|
montauk::strcpy(parent->status_msg, "Cannot delete current user");
|
||||||
|
parent->status_time = montauk::get_milliseconds();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w = 300, h = 150;
|
||||||
|
int wx = (ds->screen_w - w) / 2;
|
||||||
|
int wy = (ds->screen_h - h) / 2;
|
||||||
|
int idx = desktop_create_window(ds, "Delete User", wx, wy, w, h);
|
||||||
|
if (idx < 0) return;
|
||||||
|
|
||||||
|
Window* win = &ds->windows[idx];
|
||||||
|
DeleteUserDialogState* st = (DeleteUserDialogState*)montauk::malloc(sizeof(DeleteUserDialogState));
|
||||||
|
montauk::memset(st, 0, sizeof(DeleteUserDialogState));
|
||||||
|
st->ds = ds;
|
||||||
|
st->parent = parent;
|
||||||
|
montauk::strncpy(st->username, parent->users[parent->selected_user].username, 31);
|
||||||
|
|
||||||
|
win->app_data = st;
|
||||||
|
win->on_draw = deluser_on_draw;
|
||||||
|
win->on_mouse = deluser_on_mouse;
|
||||||
|
win->on_key = deluser_on_key;
|
||||||
|
win->on_close = deluser_on_close;
|
||||||
|
}
|
||||||
|
|
||||||
static void settings_on_draw(Window* win, Framebuffer& fb) {
|
static void settings_on_draw(Window* win, Framebuffer& fb) {
|
||||||
SettingsState* st = (SettingsState*)win->app_data;
|
SettingsState* st = (SettingsState*)win->app_data;
|
||||||
if (!st) return;
|
if (!st) return;
|
||||||
@@ -372,7 +1080,8 @@ static void settings_on_draw(Window* win, Framebuffer& fb) {
|
|||||||
switch (st->active_tab) {
|
switch (st->active_tab) {
|
||||||
case 0: settings_draw_appearance(content, st); break;
|
case 0: settings_draw_appearance(content, st); break;
|
||||||
case 1: settings_draw_display(content, st); break;
|
case 1: settings_draw_display(content, st); break;
|
||||||
case 2: settings_draw_about(content, st); break;
|
case 2: settings_draw_users(content, st); break;
|
||||||
|
case 3: settings_draw_about(content, st); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,12 +1141,14 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
if (mx >= x && mx < x + 100 && cy >= y && cy < y + 16) {
|
if (mx >= x && mx < x + 100 && cy >= y && cy < y + 16) {
|
||||||
s.bg_gradient = true;
|
s.bg_gradient = true;
|
||||||
s.bg_image = false;
|
s.bg_image = false;
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Radio: Solid
|
// Radio: Solid
|
||||||
if (mx >= x + 120 && mx < x + 210 && cy >= y && cy < y + 16) {
|
if (mx >= x + 120 && mx < x + 210 && cy >= y && cy < y + 16) {
|
||||||
s.bg_gradient = false;
|
s.bg_gradient = false;
|
||||||
s.bg_image = false;
|
s.bg_image = false;
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Radio: Image
|
// Radio: Image
|
||||||
@@ -445,16 +1156,17 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
s.bg_image = true;
|
s.bg_image = true;
|
||||||
s.bg_gradient = false;
|
s.bg_gradient = false;
|
||||||
if (!st->wp_scanned) {
|
if (!st->wp_scanned) {
|
||||||
wallpaper_scan_dir("0:/home", &st->wp_files);
|
wallpaper_scan_dir(st->desktop->home_dir, &st->wp_files);
|
||||||
st->wp_scanned = true;
|
st->wp_scanned = true;
|
||||||
}
|
}
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += line_h + 4;
|
y += line_h + 4;
|
||||||
|
|
||||||
int idx;
|
int idx;
|
||||||
if (mode_image) {
|
if (mode_image) {
|
||||||
// "Images in 0:/home/" label
|
// Wallpaper file list
|
||||||
y += sfh + 6;
|
y += sfh + 6;
|
||||||
|
|
||||||
// File list clicks
|
// File list clicks
|
||||||
@@ -463,10 +1175,12 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
mx >= x && mx < win->content_w - x) {
|
mx >= x && mx < win->content_w - x) {
|
||||||
// Build full path and load wallpaper
|
// Build full path and load wallpaper
|
||||||
char fullpath[256];
|
char fullpath[256];
|
||||||
montauk::strcpy(fullpath, "0:/home/");
|
montauk::strcpy(fullpath, st->desktop->home_dir);
|
||||||
|
str_append(fullpath, "/", 256);
|
||||||
str_append(fullpath, st->wp_files.names[i], 256);
|
str_append(fullpath, st->wp_files.names[i], 256);
|
||||||
wallpaper_load(&s, fullpath,
|
wallpaper_load(&s, fullpath,
|
||||||
st->desktop->screen_w, st->desktop->screen_h);
|
st->desktop->screen_w, st->desktop->screen_h);
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += WP_ITEM_H;
|
y += WP_ITEM_H;
|
||||||
@@ -477,6 +1191,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Top swatches
|
// Top swatches
|
||||||
if (swatch_hit(mx, cy, x + 70, y, &idx)) {
|
if (swatch_hit(mx, cy, x + 70, y, &idx)) {
|
||||||
s.bg_grad_top = bg_palette[idx];
|
s.bg_grad_top = bg_palette[idx];
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += SWATCH_SIZE + 14;
|
y += SWATCH_SIZE + 14;
|
||||||
@@ -484,6 +1199,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Bottom swatches
|
// Bottom swatches
|
||||||
if (swatch_hit(mx, cy, x + 70, y, &idx)) {
|
if (swatch_hit(mx, cy, x + 70, y, &idx)) {
|
||||||
s.bg_grad_bottom = bg_palette[idx];
|
s.bg_grad_bottom = bg_palette[idx];
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += SWATCH_SIZE + 14;
|
y += SWATCH_SIZE + 14;
|
||||||
@@ -491,6 +1207,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Solid color swatches
|
// Solid color swatches
|
||||||
if (swatch_hit(mx, cy, x + 70, y, &idx)) {
|
if (swatch_hit(mx, cy, x + 70, y, &idx)) {
|
||||||
s.bg_solid = bg_palette[idx];
|
s.bg_solid = bg_palette[idx];
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += SWATCH_SIZE + 14;
|
y += SWATCH_SIZE + 14;
|
||||||
@@ -502,6 +1219,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Panel color swatches
|
// Panel color swatches
|
||||||
if (swatch_hit(mx, cy, x + 110, y, &idx)) {
|
if (swatch_hit(mx, cy, x + 110, y, &idx)) {
|
||||||
s.panel_color = panel_palette[idx];
|
s.panel_color = panel_palette[idx];
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += SWATCH_SIZE + 14;
|
y += SWATCH_SIZE + 14;
|
||||||
@@ -512,6 +1230,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Accent color swatches
|
// Accent color swatches
|
||||||
if (swatch_hit(mx, cy, x + 110, y, &idx)) {
|
if (swatch_hit(mx, cy, x + 110, y, &idx)) {
|
||||||
s.accent_color = accent_palette[idx];
|
s.accent_color = accent_palette[idx];
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (st->active_tab == 1) {
|
} else if (st->active_tab == 1) {
|
||||||
@@ -525,11 +1244,13 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Window Shadows: On
|
// Window Shadows: On
|
||||||
if (mx >= bx && mx < bx + btn_w && cy >= y && cy < y + btn_h) {
|
if (mx >= bx && mx < bx + btn_w && cy >= y && cy < y + btn_h) {
|
||||||
s.show_shadows = true;
|
s.show_shadows = true;
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Window Shadows: Off
|
// Window Shadows: Off
|
||||||
if (mx >= bx + btn_w + 8 && mx < bx + btn_w * 2 + 8 && cy >= y && cy < y + btn_h) {
|
if (mx >= bx + btn_w + 8 && mx < bx + btn_w * 2 + 8 && cy >= y && cy < y + btn_h) {
|
||||||
s.show_shadows = false;
|
s.show_shadows = false;
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += btn_h + 20 + 16;
|
y += btn_h + 20 + 16;
|
||||||
@@ -537,11 +1258,13 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
// Clock: 24h
|
// Clock: 24h
|
||||||
if (mx >= bx && mx < bx + btn_w && cy >= y && cy < y + btn_h) {
|
if (mx >= bx && mx < bx + btn_w && cy >= y && cy < y + btn_h) {
|
||||||
s.clock_24h = true;
|
s.clock_24h = true;
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Clock: 12h
|
// Clock: 12h
|
||||||
if (mx >= bx + btn_w + 8 && mx < bx + btn_w * 2 + 8 && cy >= y && cy < y + btn_h) {
|
if (mx >= bx + btn_w + 8 && mx < bx + btn_w * 2 + 8 && cy >= y && cy < y + btn_h) {
|
||||||
s.clock_24h = false;
|
s.clock_24h = false;
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
y += btn_h + 20 + 16;
|
y += btn_h + 20 + 16;
|
||||||
@@ -553,6 +1276,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
s.ui_scale = 0;
|
s.ui_scale = 0;
|
||||||
apply_ui_scale(0);
|
apply_ui_scale(0);
|
||||||
montauk::win_setscale(0);
|
montauk::win_setscale(0);
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Default
|
// Default
|
||||||
@@ -560,6 +1284,7 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
s.ui_scale = 1;
|
s.ui_scale = 1;
|
||||||
apply_ui_scale(1);
|
apply_ui_scale(1);
|
||||||
montauk::win_setscale(1);
|
montauk::win_setscale(1);
|
||||||
|
settings_persist(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Large
|
// Large
|
||||||
@@ -567,11 +1292,71 @@ static void settings_on_mouse(Window* win, MouseEvent& ev) {
|
|||||||
s.ui_scale = 2;
|
s.ui_scale = 2;
|
||||||
apply_ui_scale(2);
|
apply_ui_scale(2);
|
||||||
montauk::win_setscale(2);
|
montauk::win_setscale(2);
|
||||||
|
settings_persist(st);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (st->active_tab == 2) {
|
||||||
|
// Users tab
|
||||||
|
if (!st->desktop->is_admin) return;
|
||||||
|
|
||||||
|
int x = 16;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int y = 20;
|
||||||
|
int content_w = win->content_w - 2 * x;
|
||||||
|
int row_h = user_row_height();
|
||||||
|
|
||||||
|
// User list rows
|
||||||
|
for (int i = 0; i < st->user_count; i++) {
|
||||||
|
if (cy >= y && cy < y + row_h && mx >= x && mx < x + content_w) {
|
||||||
|
st->selected_user = (st->selected_user == i) ? -1 : i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += row_h + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator + gap
|
||||||
|
y += 8 + 1 + 16;
|
||||||
|
|
||||||
|
// Status message (if shown, takes space)
|
||||||
|
if (st->status_msg[0] && (montauk::get_milliseconds() - st->status_time < 3000)) {
|
||||||
|
y += sfh + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action buttons
|
||||||
|
int btn_x = x;
|
||||||
|
|
||||||
|
// Add User
|
||||||
|
if (mx >= btn_x && mx < btn_x + 90 && cy >= y && cy < y + USER_BTN_H) {
|
||||||
|
open_add_user_dialog(st);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btn_x += 98;
|
||||||
|
|
||||||
|
// Change Password
|
||||||
|
if (mx >= btn_x && mx < btn_x + USER_BTN_W && cy >= y && cy < y + USER_BTN_H) {
|
||||||
|
if (st->selected_user >= 0) open_change_pwd_dialog(st);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
btn_x += USER_BTN_W + 8;
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
if (mx >= btn_x && mx < btn_x + 70 && cy >= y && cy < y + USER_BTN_H) {
|
||||||
|
if (st->selected_user >= 0) open_delete_user_dialog(st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Keyboard
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void settings_on_key(Window* win, const Montauk::KeyEvent& key) {
|
||||||
|
// Settings main window no longer needs keyboard handling —
|
||||||
|
// text input is handled by dialog windows.
|
||||||
|
(void)win; (void)key;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Cleanup
|
// Cleanup
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -600,9 +1385,13 @@ void open_settings(DesktopState* ds) {
|
|||||||
st->uptime_ms = montauk::get_milliseconds();
|
st->uptime_ms = montauk::get_milliseconds();
|
||||||
st->wp_scanned = false;
|
st->wp_scanned = false;
|
||||||
st->wp_files.count = 0;
|
st->wp_files.count = 0;
|
||||||
|
st->selected_user = -1;
|
||||||
|
st->users_loaded = false;
|
||||||
|
st->status_msg[0] = '\0';
|
||||||
|
|
||||||
win->app_data = st;
|
win->app_data = st;
|
||||||
win->on_draw = settings_on_draw;
|
win->on_draw = settings_on_draw;
|
||||||
win->on_mouse = settings_on_mouse;
|
win->on_mouse = settings_on_mouse;
|
||||||
|
win->on_key = settings_on_key;
|
||||||
win->on_close = settings_on_close;
|
win->on_close = settings_on_close;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,149 @@
|
|||||||
|
|
||||||
#include "desktop_internal.hpp"
|
#include "desktop_internal.hpp"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Lock Screen Drawing
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static constexpr Color LOCK_CARD_BG = Color::from_rgb(0xFF, 0xFF, 0xFF);
|
||||||
|
static constexpr Color LOCK_FIELD_BG = Color::from_rgb(0xF5, 0xF5, 0xF5);
|
||||||
|
static constexpr Color LOCK_BORDER = Color::from_rgb(0xCC, 0xCC, 0xCC);
|
||||||
|
static constexpr Color LOCK_ACCENT = Color::from_rgb(0x36, 0x7B, 0xF0);
|
||||||
|
static constexpr Color LOCK_TEXT = Color::from_rgb(0x33, 0x33, 0x33);
|
||||||
|
static constexpr Color LOCK_DIM = Color::from_rgb(0x66, 0x66, 0x66);
|
||||||
|
static constexpr Color LOCK_ERROR = Color::from_rgb(0xE0, 0x40, 0x40);
|
||||||
|
static constexpr Color LOCK_BTN_TEXT = Color::from_rgb(0xFF, 0xFF, 0xFF);
|
||||||
|
static constexpr int LOCK_CARD_W = 360;
|
||||||
|
static constexpr int LOCK_FIELD_H = 36;
|
||||||
|
static constexpr int LOCK_BTN_H = 40;
|
||||||
|
|
||||||
|
void desktop_draw_lock_screen(DesktopState* ds) {
|
||||||
|
Framebuffer& fb = ds->fb;
|
||||||
|
int sw = ds->screen_w;
|
||||||
|
int sh = ds->screen_h;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
|
||||||
|
// Dark overlay on top of background
|
||||||
|
fb.fill_rect_alpha(0, 0, sw, sh, Color::from_rgba(0, 0, 0, 0x80));
|
||||||
|
|
||||||
|
// Clock display above card
|
||||||
|
Montauk::DateTime dt;
|
||||||
|
montauk::gettime(&dt);
|
||||||
|
char time_str[12];
|
||||||
|
snprintf(time_str, sizeof(time_str), "%02d:%02d", (int)dt.Hour, (int)dt.Minute);
|
||||||
|
|
||||||
|
// Calculate card dimensions
|
||||||
|
int error_h = ds->lock_show_error ? sfh + 8 : 0;
|
||||||
|
int card_h = 20 + sfh + 16 + sfh + 12 + sfh + 4 + LOCK_FIELD_H + 16 + LOCK_BTN_H + error_h + 20;
|
||||||
|
int card_x = (sw - LOCK_CARD_W) / 2;
|
||||||
|
int card_y = (sh - card_h) / 2;
|
||||||
|
|
||||||
|
// Draw time above card
|
||||||
|
int time_w = text_width(time_str);
|
||||||
|
draw_text(fb, (sw - time_w) / 2, card_y - sfh * 3, time_str, Color::from_rgb(0xFF, 0xFF, 0xFF));
|
||||||
|
|
||||||
|
// Date below time
|
||||||
|
{
|
||||||
|
int month_idx = dt.Month > 0 && dt.Month <= 12 ? dt.Month - 1 : 0;
|
||||||
|
char date_str[32];
|
||||||
|
snprintf(date_str, sizeof(date_str), "%s %d", month_names[month_idx], (int)dt.Day);
|
||||||
|
int dw = text_width(date_str);
|
||||||
|
draw_text(fb, (sw - dw) / 2, card_y - sfh * 2 + 4, date_str, Color::from_rgb(0xCC, 0xCC, 0xCC));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Card background with rounded corners
|
||||||
|
fill_rounded_rect(fb, card_x, card_y, LOCK_CARD_W, card_h, 12, LOCK_CARD_BG);
|
||||||
|
|
||||||
|
int x = card_x + 24;
|
||||||
|
int content_w = LOCK_CARD_W - 48;
|
||||||
|
int y = card_y + 20;
|
||||||
|
|
||||||
|
// Title (with optional lock icon beside it)
|
||||||
|
{
|
||||||
|
const char* title = "Locked";
|
||||||
|
int tw = text_width(title);
|
||||||
|
int icon_w = ds->icon_lock.pixels ? 20 : 0;
|
||||||
|
int gap = icon_w ? 8 : 0;
|
||||||
|
int total = icon_w + gap + tw;
|
||||||
|
int tx = card_x + (LOCK_CARD_W - total) / 2;
|
||||||
|
|
||||||
|
if (ds->icon_lock.pixels) {
|
||||||
|
fb.blit_alpha(tx, y + (sfh - 20) / 2, ds->icon_lock.width, ds->icon_lock.height, ds->icon_lock.pixels);
|
||||||
|
}
|
||||||
|
draw_text(fb, tx + icon_w + gap, y, title, LOCK_TEXT);
|
||||||
|
y += sfh + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Username display (cached at lock time)
|
||||||
|
{
|
||||||
|
int nw = text_width(ds->lock_display_name);
|
||||||
|
draw_text(fb, card_x + (LOCK_CARD_W - nw) / 2, y, ds->lock_display_name, LOCK_DIM);
|
||||||
|
y += sfh + 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password label
|
||||||
|
draw_text(fb, x, y, "Password", LOCK_DIM);
|
||||||
|
y += sfh + 4;
|
||||||
|
|
||||||
|
// Password field
|
||||||
|
{
|
||||||
|
fb.fill_rect(x, y, content_w, LOCK_FIELD_H, LOCK_FIELD_BG);
|
||||||
|
|
||||||
|
// 2px accent border (always active)
|
||||||
|
for (int i = 0; i < content_w; i++) { fb.put_pixel(x + i, y, LOCK_ACCENT); fb.put_pixel(x + i, y + 1, LOCK_ACCENT); }
|
||||||
|
for (int i = 0; i < content_w; i++) { fb.put_pixel(x + i, y + LOCK_FIELD_H - 1, LOCK_ACCENT); fb.put_pixel(x + i, y + LOCK_FIELD_H - 2, LOCK_ACCENT); }
|
||||||
|
for (int i = 0; i < LOCK_FIELD_H; i++) { fb.put_pixel(x, y + i, LOCK_ACCENT); fb.put_pixel(x + 1, y + i, LOCK_ACCENT); }
|
||||||
|
for (int i = 0; i < LOCK_FIELD_H; i++) { fb.put_pixel(x + content_w - 1, y + i, LOCK_ACCENT); fb.put_pixel(x + content_w - 2, y + i, LOCK_ACCENT); }
|
||||||
|
|
||||||
|
// Masked password text (clipped to field width)
|
||||||
|
char masked[65];
|
||||||
|
int len = ds->lock_password_len;
|
||||||
|
if (len > 64) len = 64;
|
||||||
|
int max_text_w = content_w - 10 - 10 - 2; // left pad, right pad, cursor
|
||||||
|
// Show only the trailing portion that fits
|
||||||
|
int vis = len;
|
||||||
|
{
|
||||||
|
char tmp[65];
|
||||||
|
for (int i = 0; i < len; i++) tmp[i] = '*';
|
||||||
|
tmp[len] = '\0';
|
||||||
|
while (vis > 0 && text_width(tmp + (len - vis)) > max_text_w)
|
||||||
|
vis--;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < vis; i++) masked[i] = '*';
|
||||||
|
masked[vis] = '\0';
|
||||||
|
|
||||||
|
int ty = y + (LOCK_FIELD_H - sfh) / 2;
|
||||||
|
draw_text(fb, x + 10, ty, masked, LOCK_TEXT);
|
||||||
|
|
||||||
|
// Cursor
|
||||||
|
int cx = x + 10 + text_width(masked);
|
||||||
|
fb.fill_rect(cx, ty, 2, sfh, LOCK_ACCENT);
|
||||||
|
|
||||||
|
y += LOCK_FIELD_H + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock button
|
||||||
|
{
|
||||||
|
fill_rounded_rect(fb, x, y, content_w, LOCK_BTN_H, 6, LOCK_ACCENT);
|
||||||
|
const char* label = "Unlock";
|
||||||
|
int tw = text_width(label);
|
||||||
|
int ty = y + (LOCK_BTN_H - sfh) / 2;
|
||||||
|
draw_text(fb, x + (content_w - tw) / 2, ty, label, LOCK_BTN_TEXT);
|
||||||
|
y += LOCK_BTN_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error message
|
||||||
|
if (ds->lock_show_error) {
|
||||||
|
y += 8;
|
||||||
|
int ew = text_width(ds->lock_error);
|
||||||
|
draw_text(fb, card_x + (LOCK_CARD_W - ew) / 2, y, ds->lock_error, LOCK_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Desktop Composition
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
void gui::desktop_compose(DesktopState* ds) {
|
void gui::desktop_compose(DesktopState* ds) {
|
||||||
Framebuffer& fb = ds->fb;
|
Framebuffer& fb = ds->fb;
|
||||||
|
|
||||||
@@ -45,6 +188,13 @@ void gui::desktop_compose(DesktopState* ds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lock screen: draw overlay and card, then cursor, and return early
|
||||||
|
if (ds->screen_locked) {
|
||||||
|
desktop_draw_lock_screen(ds);
|
||||||
|
draw_cursor(fb, ds->mouse.x, ds->mouse.y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Draw windows from bottom to top
|
// Draw windows from bottom to top
|
||||||
for (int i = 0; i < ds->window_count; i++) {
|
for (int i = 0; i < ds->window_count; i++) {
|
||||||
if (ds->windows[i].state != WIN_MINIMIZED && ds->windows[i].state != WIN_CLOSED) {
|
if (ds->windows[i].state != WIN_MINIMIZED && ds->windows[i].state != WIN_CLOSED) {
|
||||||
@@ -65,6 +215,11 @@ void gui::desktop_compose(DesktopState* ds) {
|
|||||||
desktop_draw_net_popup(ds);
|
desktop_draw_net_popup(ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw volume popup if open
|
||||||
|
if (ds->vol_popup_open) {
|
||||||
|
desktop_draw_vol_popup(ds);
|
||||||
|
}
|
||||||
|
|
||||||
// Draw right-click context menu if open
|
// Draw right-click context menu if open
|
||||||
if (ds->ctx_menu_open) {
|
if (ds->ctx_menu_open) {
|
||||||
static constexpr int CTX_MENU_W = 180;
|
static constexpr int CTX_MENU_W = 180;
|
||||||
|
|||||||
@@ -115,6 +115,10 @@ gui::CursorStyle cursor_for_edge(gui::ResizeEdge edge);
|
|||||||
// panel.cpp
|
// panel.cpp
|
||||||
void desktop_draw_app_menu(gui::DesktopState* ds);
|
void desktop_draw_app_menu(gui::DesktopState* ds);
|
||||||
void desktop_draw_net_popup(gui::DesktopState* ds);
|
void desktop_draw_net_popup(gui::DesktopState* ds);
|
||||||
|
void desktop_draw_vol_popup(gui::DesktopState* ds);
|
||||||
|
|
||||||
|
// compose.cpp
|
||||||
|
void desktop_draw_lock_screen(gui::DesktopState* ds);
|
||||||
|
|
||||||
// main.cpp
|
// main.cpp
|
||||||
void desktop_scan_apps(gui::DesktopState* ds);
|
void desktop_scan_apps(gui::DesktopState* ds);
|
||||||
|
|||||||
+247
-11
@@ -5,8 +5,133 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "desktop_internal.hpp"
|
#include "desktop_internal.hpp"
|
||||||
|
#include <montauk/user.h>
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Lock Screen Input
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void lock_screen(DesktopState* ds) {
|
||||||
|
ds->screen_locked = true;
|
||||||
|
ds->lock_password[0] = '\0';
|
||||||
|
ds->lock_password_len = 0;
|
||||||
|
ds->lock_error[0] = '\0';
|
||||||
|
ds->lock_show_error = false;
|
||||||
|
ds->app_menu_open = false;
|
||||||
|
ds->ctx_menu_open = false;
|
||||||
|
ds->net_popup_open = false;
|
||||||
|
ds->vol_popup_open = false;
|
||||||
|
|
||||||
|
// Cache display name for lock screen rendering
|
||||||
|
montauk::strncpy(ds->lock_display_name, ds->current_user, sizeof(ds->lock_display_name));
|
||||||
|
montauk::user::UserInfo users[16];
|
||||||
|
int count = montauk::user::load_users(users, 16);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (montauk::streq(users[i].username, ds->current_user)) {
|
||||||
|
if (users[i].display_name[0])
|
||||||
|
montauk::strncpy(ds->lock_display_name, users[i].display_name, sizeof(ds->lock_display_name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool try_unlock(DesktopState* ds) {
|
||||||
|
ds->lock_show_error = false;
|
||||||
|
|
||||||
|
if (montauk::user::authenticate(ds->current_user, ds->lock_password)) {
|
||||||
|
ds->screen_locked = false;
|
||||||
|
ds->lock_password[0] = '\0';
|
||||||
|
ds->lock_password_len = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
montauk::strcpy(ds->lock_error, "Incorrect password");
|
||||||
|
ds->lock_show_error = true;
|
||||||
|
ds->lock_password[0] = '\0';
|
||||||
|
ds->lock_password_len = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_lock_mouse(DesktopState* ds) {
|
||||||
|
int mx = ds->mouse.x;
|
||||||
|
int my = ds->mouse.y;
|
||||||
|
uint8_t buttons = ds->mouse.buttons;
|
||||||
|
uint8_t prev = ds->prev_buttons;
|
||||||
|
bool left_pressed = (buttons & 0x01) && !(prev & 0x01);
|
||||||
|
|
||||||
|
if (!left_pressed) return;
|
||||||
|
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int card_w = 360;
|
||||||
|
int content_w = card_w - 48;
|
||||||
|
int field_h = 36;
|
||||||
|
int btn_h = 40;
|
||||||
|
|
||||||
|
// Calculate card layout to find button position
|
||||||
|
int error_h = ds->lock_show_error ? sfh + 8 : 0;
|
||||||
|
int card_h = 20 + sfh + 16 + sfh + 12 + sfh + 4 + field_h + 16 + btn_h + error_h + 20;
|
||||||
|
int card_x = (ds->screen_w - card_w) / 2;
|
||||||
|
int card_y = (ds->screen_h - card_h) / 2;
|
||||||
|
int x = card_x + 24;
|
||||||
|
|
||||||
|
// Walk through the layout to find the Unlock button y position
|
||||||
|
int y = card_y + 20;
|
||||||
|
y += sfh + 16; // title
|
||||||
|
y += sfh + 12; // username
|
||||||
|
y += sfh + 4; // "Password" label
|
||||||
|
y += field_h + 16; // field + gap
|
||||||
|
|
||||||
|
// Check Unlock button
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + btn_h) {
|
||||||
|
try_unlock(ds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check password field click (just keep focus, nothing else to switch to)
|
||||||
|
int field_y = y - field_h - 16;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= field_y && my < field_y + field_h) {
|
||||||
|
ds->lock_show_error = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_lock_keyboard(DesktopState* ds, const Montauk::KeyEvent& key) {
|
||||||
|
if (!key.pressed) return;
|
||||||
|
|
||||||
|
// Enter submits
|
||||||
|
if (key.ascii == '\n' || key.ascii == '\r') {
|
||||||
|
try_unlock(ds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backspace
|
||||||
|
if (key.ascii == '\b' || key.scancode == 0x0E) {
|
||||||
|
if (ds->lock_password_len > 0) {
|
||||||
|
ds->lock_password_len--;
|
||||||
|
ds->lock_password[ds->lock_password_len] = '\0';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printable characters
|
||||||
|
if (key.ascii >= 0x20 && key.ascii < 0x7F) {
|
||||||
|
if (ds->lock_password_len < 63) {
|
||||||
|
ds->lock_password[ds->lock_password_len] = key.ascii;
|
||||||
|
ds->lock_password_len++;
|
||||||
|
ds->lock_password[ds->lock_password_len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Desktop Mouse Handling
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
void gui::desktop_handle_mouse(DesktopState* ds) {
|
void gui::desktop_handle_mouse(DesktopState* ds) {
|
||||||
|
if (ds->screen_locked) {
|
||||||
|
handle_lock_mouse(ds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int mx = ds->mouse.x;
|
int mx = ds->mouse.x;
|
||||||
int my = ds->mouse.y;
|
int my = ds->mouse.y;
|
||||||
uint8_t buttons = ds->mouse.buttons;
|
uint8_t buttons = ds->mouse.buttons;
|
||||||
@@ -213,8 +338,8 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
menu_cat_expanded[cur_cat] = !menu_cat_expanded[cur_cat];
|
menu_cat_expanded[cur_cat] = !menu_cat_expanded[cur_cat];
|
||||||
} else if (!row.is_category) {
|
} else if (!row.is_category) {
|
||||||
if (row.external) {
|
if (row.external) {
|
||||||
// Launch external app from manifest
|
// Launch external app with user's home dir
|
||||||
montauk::spawn(row.binary_path);
|
montauk::spawn(row.binary_path, ds->home_dir);
|
||||||
} else {
|
} else {
|
||||||
// Dispatch embedded app
|
// Dispatch embedded app
|
||||||
switch (row.app_id) {
|
switch (row.app_id) {
|
||||||
@@ -230,6 +355,8 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
case 12: open_reboot_dialog(ds); break;
|
case 12: open_reboot_dialog(ds); break;
|
||||||
case 14: open_shutdown_dialog(ds); break;
|
case 14: open_shutdown_dialog(ds); break;
|
||||||
case 15: open_wordprocessor(ds); break;
|
case 15: open_wordprocessor(ds); break;
|
||||||
|
case 16: montauk::exit(0); break; // Log Out
|
||||||
|
case 17: lock_screen(ds); break; // Lock Screen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ds->app_menu_open = false;
|
ds->app_menu_open = false;
|
||||||
@@ -244,10 +371,104 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle volume popup interaction
|
||||||
|
if (ds->vol_popup_open) {
|
||||||
|
int popup_x = ds->vol_icon_rect.x + ds->vol_icon_rect.w - 200;
|
||||||
|
int popup_y = PANEL_HEIGHT + 2;
|
||||||
|
if (popup_x < 4) popup_x = 4;
|
||||||
|
Rect vol_rect = {popup_x, popup_y, 200, 120};
|
||||||
|
|
||||||
|
// Handle drag continuity
|
||||||
|
if (ds->vol_dragging) {
|
||||||
|
if (left_held) {
|
||||||
|
int slider_abs_x = popup_x + 16;
|
||||||
|
int v = ((mx - slider_abs_x) * 100) / (200 - 32);
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
if (v > 100) v = 100;
|
||||||
|
ds->vol_muted = false;
|
||||||
|
ds->vol_level = v;
|
||||||
|
montauk::audio_set_volume(0, v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (left_released) {
|
||||||
|
ds->vol_dragging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left_pressed) {
|
||||||
|
if (vol_rect.contains(mx, my)) {
|
||||||
|
// Slider area (y = popup_y + 56, height = 8, with generous hit zone)
|
||||||
|
int slider_abs_x = popup_x + 16;
|
||||||
|
int slider_abs_y = popup_y + 56;
|
||||||
|
int slider_w = 200 - 32;
|
||||||
|
if (my >= slider_abs_y - 10 && my <= slider_abs_y + 8 + 10 &&
|
||||||
|
mx >= slider_abs_x - 8 && mx <= slider_abs_x + slider_w + 8) {
|
||||||
|
int v = ((mx - slider_abs_x) * 100) / slider_w;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
if (v > 100) v = 100;
|
||||||
|
ds->vol_muted = false;
|
||||||
|
ds->vol_level = v;
|
||||||
|
montauk::audio_set_volume(0, v);
|
||||||
|
ds->vol_dragging = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons (y = popup_y + 78, h = 24)
|
||||||
|
int btn_h = 24;
|
||||||
|
int btn_y = popup_y + 78;
|
||||||
|
int minus_w = 36, plus_w = 36, mute_w = 50, gap = 8;
|
||||||
|
int total_w = minus_w + plus_w + mute_w + gap * 2;
|
||||||
|
int bx = popup_x + (200 - total_w) / 2;
|
||||||
|
|
||||||
|
if (my >= btn_y && my < btn_y + btn_h) {
|
||||||
|
// [-]
|
||||||
|
if (mx >= bx && mx < bx + minus_w) {
|
||||||
|
ds->vol_muted = false;
|
||||||
|
int v = ds->vol_level - 5;
|
||||||
|
if (v < 0) v = 0;
|
||||||
|
ds->vol_level = v;
|
||||||
|
montauk::audio_set_volume(0, v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bx += minus_w + gap;
|
||||||
|
// [+]
|
||||||
|
if (mx >= bx && mx < bx + plus_w) {
|
||||||
|
ds->vol_muted = false;
|
||||||
|
int v = ds->vol_level + 5;
|
||||||
|
if (v > 100) v = 100;
|
||||||
|
ds->vol_level = v;
|
||||||
|
montauk::audio_set_volume(0, v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bx += plus_w + gap;
|
||||||
|
// [Mute]
|
||||||
|
if (mx >= bx && mx < bx + mute_w) {
|
||||||
|
if (ds->vol_muted) {
|
||||||
|
ds->vol_muted = false;
|
||||||
|
montauk::audio_set_volume(0, ds->vol_pre_mute);
|
||||||
|
ds->vol_level = ds->vol_pre_mute;
|
||||||
|
} else {
|
||||||
|
ds->vol_pre_mute = ds->vol_level;
|
||||||
|
ds->vol_muted = true;
|
||||||
|
montauk::audio_set_volume(0, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return; // click inside popup but not on any control
|
||||||
|
} else if (!ds->vol_icon_rect.contains(mx, my)) {
|
||||||
|
ds->vol_popup_open = false;
|
||||||
|
ds->vol_dragging = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle net popup clicks
|
// Handle net popup clicks
|
||||||
if (ds->net_popup_open && left_pressed) {
|
if (ds->net_popup_open && left_pressed) {
|
||||||
int popup_w = 220;
|
int popup_w = 220;
|
||||||
int popup_h = 130;
|
int fh_net = system_font_height();
|
||||||
|
int row_h_net = fh_net + 8;
|
||||||
|
int popup_h = (row_h_net + 8) + row_h_net * 5 + 12;
|
||||||
int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w;
|
int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w;
|
||||||
int popup_y = PANEL_HEIGHT + 2;
|
int popup_y = PANEL_HEIGHT + 2;
|
||||||
if (popup_x < 4) popup_x = 4;
|
if (popup_x < 4) popup_x = 4;
|
||||||
@@ -266,6 +487,17 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
if (mx < 36) {
|
if (mx < 36) {
|
||||||
ds->app_menu_open = !ds->app_menu_open;
|
ds->app_menu_open = !ds->app_menu_open;
|
||||||
ds->net_popup_open = false;
|
ds->net_popup_open = false;
|
||||||
|
ds->vol_popup_open = false;
|
||||||
|
ds->ctx_menu_open = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Volume icon
|
||||||
|
if (ds->vol_icon_rect.w > 0 && ds->vol_icon_rect.contains(mx, my)) {
|
||||||
|
ds->vol_popup_open = !ds->vol_popup_open;
|
||||||
|
ds->vol_dragging = false;
|
||||||
|
ds->app_menu_open = false;
|
||||||
|
ds->net_popup_open = false;
|
||||||
ds->ctx_menu_open = false;
|
ds->ctx_menu_open = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -274,6 +506,7 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
if (ds->net_icon_rect.w > 0 && ds->net_icon_rect.contains(mx, my)) {
|
if (ds->net_icon_rect.w > 0 && ds->net_icon_rect.contains(mx, my)) {
|
||||||
ds->net_popup_open = !ds->net_popup_open;
|
ds->net_popup_open = !ds->net_popup_open;
|
||||||
ds->app_menu_open = false;
|
ds->app_menu_open = false;
|
||||||
|
ds->vol_popup_open = false;
|
||||||
ds->ctx_menu_open = false;
|
ds->ctx_menu_open = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -369,11 +602,6 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
if (win->state != WIN_MAXIMIZED) {
|
if (win->state != WIN_MAXIMIZED) {
|
||||||
ResizeEdge edge = hit_test_resize_edge(win->frame, mx, my);
|
ResizeEdge edge = hit_test_resize_edge(win->frame, mx, my);
|
||||||
if (edge != RESIZE_NONE) {
|
if (edge != RESIZE_NONE) {
|
||||||
win->resizing = true;
|
|
||||||
win->resize_edge = edge;
|
|
||||||
win->resize_start_frame = win->frame;
|
|
||||||
win->resize_start_mx = mx;
|
|
||||||
win->resize_start_my = my;
|
|
||||||
desktop_raise_window(ds, i);
|
desktop_raise_window(ds, i);
|
||||||
int new_idx = ds->window_count - 1;
|
int new_idx = ds->window_count - 1;
|
||||||
ds->windows[new_idx].resizing = true;
|
ds->windows[new_idx].resizing = true;
|
||||||
@@ -388,9 +616,6 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
// Check titlebar (start drag)
|
// Check titlebar (start drag)
|
||||||
Rect tb = win->titlebar_rect();
|
Rect tb = win->titlebar_rect();
|
||||||
if (tb.contains(mx, my)) {
|
if (tb.contains(mx, my)) {
|
||||||
win->dragging = true;
|
|
||||||
win->drag_offset_x = mx - win->frame.x;
|
|
||||||
win->drag_offset_y = my - win->frame.y;
|
|
||||||
desktop_raise_window(ds, i);
|
desktop_raise_window(ds, i);
|
||||||
int new_idx = ds->window_count - 1;
|
int new_idx = ds->window_count - 1;
|
||||||
ds->windows[new_idx].dragging = true;
|
ds->windows[new_idx].dragging = true;
|
||||||
@@ -433,6 +658,7 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
|
|
||||||
ds->app_menu_open = false;
|
ds->app_menu_open = false;
|
||||||
ds->ctx_menu_open = false;
|
ds->ctx_menu_open = false;
|
||||||
|
ds->vol_popup_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward continuous mouse events to focused window (hover, drag, release)
|
// Forward continuous mouse events to focused window (hover, drag, release)
|
||||||
@@ -499,13 +725,23 @@ void gui::desktop_handle_mouse(DesktopState* ds) {
|
|||||||
ds->ctx_menu_y = my;
|
ds->ctx_menu_y = my;
|
||||||
ds->app_menu_open = false;
|
ds->app_menu_open = false;
|
||||||
ds->net_popup_open = false;
|
ds->net_popup_open = false;
|
||||||
|
ds->vol_popup_open = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gui::desktop_handle_keyboard(DesktopState* ds, const Montauk::KeyEvent& key) {
|
void gui::desktop_handle_keyboard(DesktopState* ds, const Montauk::KeyEvent& key) {
|
||||||
|
if (ds->screen_locked) {
|
||||||
|
handle_lock_keyboard(ds, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Global shortcuts (only on key press)
|
// Global shortcuts (only on key press)
|
||||||
if (key.pressed && key.ctrl && key.alt) {
|
if (key.pressed && key.ctrl && key.alt) {
|
||||||
|
if (key.ascii == 'l' || key.ascii == 'L') {
|
||||||
|
lock_screen(ds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (key.ascii == 't' || key.ascii == 'T') {
|
if (key.ascii == 't' || key.ascii == 'T') {
|
||||||
open_terminal(ds);
|
open_terminal(ds);
|
||||||
return;
|
return;
|
||||||
|
|||||||
+117
-16
@@ -5,6 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "desktop_internal.hpp"
|
#include "desktop_internal.hpp"
|
||||||
|
#include <montauk/config.h>
|
||||||
|
#include <montauk/user.h>
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// App Manifest Scanning
|
// App Manifest Scanning
|
||||||
@@ -168,9 +170,11 @@ void desktop_build_menu(DesktopState* ds) {
|
|||||||
|
|
||||||
// Divider + always-visible entries
|
// Divider + always-visible entries
|
||||||
menu_add_category(""); // divider (cat 4, always expanded)
|
menu_add_category(""); // divider (cat 4, always expanded)
|
||||||
menu_add_embedded("Settings", 11, &ds->icon_settings);
|
menu_add_embedded("Settings", 11, &ds->icon_settings);
|
||||||
menu_add_embedded("Reboot", 12, &ds->icon_reboot);
|
menu_add_embedded("Lock Screen", 17, &ds->icon_lock);
|
||||||
menu_add_embedded("Shutdown", 14, &ds->icon_shutdown);
|
menu_add_embedded("Log Out", 16, &ds->icon_logout);
|
||||||
|
menu_add_embedded("Reboot", 12, &ds->icon_reboot);
|
||||||
|
menu_add_embedded("Shutdown", 14, &ds->icon_shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -224,9 +228,12 @@ void gui::desktop_init(DesktopState* ds) {
|
|||||||
ds->icon_settings = svg_load("0:/icons/help-about.svg", 20, 20, defColor);
|
ds->icon_settings = svg_load("0:/icons/help-about.svg", 20, 20, defColor);
|
||||||
ds->icon_reboot = svg_load("0:/icons/system-reboot.svg", 20, 20, defColor);
|
ds->icon_reboot = svg_load("0:/icons/system-reboot.svg", 20, 20, defColor);
|
||||||
ds->icon_shutdown = svg_load("0:/icons/system-shutdown.svg", 20, 20, defColor);
|
ds->icon_shutdown = svg_load("0:/icons/system-shutdown.svg", 20, 20, defColor);
|
||||||
|
ds->icon_logout = svg_load("0:/icons/gnome-logout.svg", 20, 20, defColor);
|
||||||
|
|
||||||
ds->icon_procmgr = svg_load("0:/icons/system-monitor.svg", 20, 20, defColor);
|
ds->icon_procmgr = svg_load("0:/icons/system-monitor.svg", 20, 20, defColor);
|
||||||
ds->icon_mandelbrot = svg_load("0:/icons/applications-science.svg", 20, 20, defColor);
|
ds->icon_mandelbrot = svg_load("0:/icons/applications-science.svg", 20, 20, defColor);
|
||||||
|
ds->icon_volume = svg_load("0:/icons/audio-volume-high-symbolic.svg", 16, 16, colors::PANEL_TEXT);
|
||||||
|
ds->icon_lock = svg_load("0:/icons/lock.svg", 20, 20, defColor);
|
||||||
|
|
||||||
// Scan 0:/apps/ for external app manifests and build the menu
|
// Scan 0:/apps/ for external app manifests and build the menu
|
||||||
desktop_scan_apps(ds);
|
desktop_scan_apps(ds);
|
||||||
@@ -248,10 +255,61 @@ void gui::desktop_init(DesktopState* ds) {
|
|||||||
ds->settings.clock_24h = true;
|
ds->settings.clock_24h = true;
|
||||||
ds->settings.ui_scale = 1;
|
ds->settings.ui_scale = 1;
|
||||||
|
|
||||||
// Try to load default wallpaper
|
// Load per-user desktop settings
|
||||||
wallpaper_load(&ds->settings, "0:/home/lucas-alexander-2dJn8XoIKCg-unsplash.jpg",
|
{
|
||||||
ds->screen_w, ds->screen_h);
|
auto doc = montauk::config::load_user(ds->current_user, "desktop");
|
||||||
montauk::win_setscale(1);
|
|
||||||
|
const char* wp = doc.get_string("wallpaper.path", "");
|
||||||
|
if (wp[0] != '\0') {
|
||||||
|
wallpaper_load(&ds->settings, wp, ds->screen_w, ds->screen_h);
|
||||||
|
} else {
|
||||||
|
// Fall back to system-wide default wallpaper from 0:/config/desktop.toml
|
||||||
|
auto sys = montauk::config::load("desktop");
|
||||||
|
const char* def_wp = sys.get_string("wallpaper.path", "");
|
||||||
|
if (def_wp[0] != '\0') {
|
||||||
|
wallpaper_load(&ds->settings, def_wp, ds->screen_w, ds->screen_h);
|
||||||
|
}
|
||||||
|
sys.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore other settings from user config
|
||||||
|
const char* bg_mode = doc.get_string("background.mode", "");
|
||||||
|
if (montauk::streq(bg_mode, "solid")) {
|
||||||
|
ds->settings.bg_gradient = false;
|
||||||
|
ds->settings.bg_image = false;
|
||||||
|
} else if (montauk::streq(bg_mode, "gradient")) {
|
||||||
|
ds->settings.bg_gradient = true;
|
||||||
|
ds->settings.bg_image = false;
|
||||||
|
}
|
||||||
|
// (image mode is set by wallpaper_load above)
|
||||||
|
|
||||||
|
// Background colors
|
||||||
|
int64_t solid = doc.get_int("background.solid_color", -1);
|
||||||
|
if (solid >= 0) ds->settings.bg_solid = Color::from_rgb(
|
||||||
|
(uint8_t)((solid >> 16) & 0xFF), (uint8_t)((solid >> 8) & 0xFF), (uint8_t)(solid & 0xFF));
|
||||||
|
int64_t gtop = doc.get_int("background.grad_top", -1);
|
||||||
|
if (gtop >= 0) ds->settings.bg_grad_top = Color::from_rgb(
|
||||||
|
(uint8_t)((gtop >> 16) & 0xFF), (uint8_t)((gtop >> 8) & 0xFF), (uint8_t)(gtop & 0xFF));
|
||||||
|
int64_t gbot = doc.get_int("background.grad_bottom", -1);
|
||||||
|
if (gbot >= 0) ds->settings.bg_grad_bottom = Color::from_rgb(
|
||||||
|
(uint8_t)((gbot >> 16) & 0xFF), (uint8_t)((gbot >> 8) & 0xFF), (uint8_t)(gbot & 0xFF));
|
||||||
|
|
||||||
|
// Appearance colors
|
||||||
|
int64_t panel = doc.get_int("appearance.panel_color", -1);
|
||||||
|
if (panel >= 0) ds->settings.panel_color = Color::from_rgb(
|
||||||
|
(uint8_t)((panel >> 16) & 0xFF), (uint8_t)((panel >> 8) & 0xFF), (uint8_t)(panel & 0xFF));
|
||||||
|
int64_t accent = doc.get_int("appearance.accent_color", -1);
|
||||||
|
if (accent >= 0) ds->settings.accent_color = Color::from_rgb(
|
||||||
|
(uint8_t)((accent >> 16) & 0xFF), (uint8_t)((accent >> 8) & 0xFF), (uint8_t)(accent & 0xFF));
|
||||||
|
|
||||||
|
int64_t scale = doc.get_int("display.ui_scale", 1);
|
||||||
|
ds->settings.ui_scale = (int)scale;
|
||||||
|
ds->settings.clock_24h = doc.get_bool("display.clock_24h", true);
|
||||||
|
ds->settings.show_shadows = doc.get_bool("display.show_shadows", true);
|
||||||
|
|
||||||
|
doc.destroy();
|
||||||
|
}
|
||||||
|
montauk::win_setscale(ds->settings.ui_scale);
|
||||||
|
|
||||||
ds->ctx_menu_open = false;
|
ds->ctx_menu_open = false;
|
||||||
ds->ctx_menu_x = 0;
|
ds->ctx_menu_x = 0;
|
||||||
@@ -262,8 +320,22 @@ void gui::desktop_init(DesktopState* ds) {
|
|||||||
ds->net_cfg_last_poll = montauk::get_milliseconds();
|
ds->net_cfg_last_poll = montauk::get_milliseconds();
|
||||||
ds->net_icon_rect = {0, 0, 0, 0};
|
ds->net_icon_rect = {0, 0, 0, 0};
|
||||||
|
|
||||||
|
ds->vol_popup_open = false;
|
||||||
|
ds->vol_icon_rect = {0, 0, 0, 0};
|
||||||
|
int vol = montauk::audio_get_volume(0);
|
||||||
|
ds->vol_level = vol >= 0 ? vol : 80;
|
||||||
|
ds->vol_muted = false;
|
||||||
|
ds->vol_pre_mute = ds->vol_level;
|
||||||
|
ds->vol_dragging = false;
|
||||||
|
ds->vol_last_poll = montauk::get_milliseconds();
|
||||||
|
|
||||||
ds->closing_ext_count = 0;
|
ds->closing_ext_count = 0;
|
||||||
|
|
||||||
|
ds->screen_locked = false;
|
||||||
|
ds->lock_password[0] = '\0';
|
||||||
|
ds->lock_password_len = 0;
|
||||||
|
ds->lock_error[0] = '\0';
|
||||||
|
ds->lock_show_error = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -412,21 +484,25 @@ void gui::desktop_run(DesktopState* ds) {
|
|||||||
// Poll external windows (discover new, remove dead, update dirty)
|
// Poll external windows (discover new, remove dead, update dirty)
|
||||||
desktop_poll_external_windows(ds);
|
desktop_poll_external_windows(ds);
|
||||||
|
|
||||||
// Poll windows that have a poll callback
|
if (!ds->screen_locked) {
|
||||||
for (int i = 0; i < ds->window_count; i++) {
|
// Poll windows that have a poll callback
|
||||||
Window* win = &ds->windows[i];
|
for (int i = 0; i < ds->window_count; i++) {
|
||||||
if (win->state == WIN_CLOSED) continue;
|
Window* win = &ds->windows[i];
|
||||||
if (win->on_poll) {
|
if (win->state == WIN_CLOSED) continue;
|
||||||
win->on_poll(win);
|
if (win->on_poll) {
|
||||||
|
win->on_poll(win);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle mouse events
|
// Handle mouse events
|
||||||
desktop_handle_mouse(ds);
|
desktop_handle_mouse(ds);
|
||||||
|
|
||||||
// Re-poll external windows so that any killed during mouse/key
|
if (!ds->screen_locked) {
|
||||||
// handling are removed before we touch their pixel buffers.
|
// Re-poll external windows so that any killed during mouse/key
|
||||||
desktop_poll_external_windows(ds);
|
// handling are removed before we touch their pixel buffers.
|
||||||
|
desktop_poll_external_windows(ds);
|
||||||
|
}
|
||||||
|
|
||||||
// Compose and present
|
// Compose and present
|
||||||
desktop_compose(ds);
|
desktop_compose(ds);
|
||||||
@@ -450,6 +526,31 @@ extern "C" void _start() {
|
|||||||
// Placement-new the Framebuffer since it has a constructor
|
// Placement-new the Framebuffer since it has a constructor
|
||||||
new (&ds->fb) Framebuffer();
|
new (&ds->fb) Framebuffer();
|
||||||
|
|
||||||
|
// Read username from spawn args
|
||||||
|
char username[32] = {};
|
||||||
|
montauk::getargs(username, 32);
|
||||||
|
if (username[0] == '\0') {
|
||||||
|
montauk::strcpy(username, "default");
|
||||||
|
}
|
||||||
|
montauk::strncpy(ds->current_user, username, 31);
|
||||||
|
|
||||||
|
// Build user paths
|
||||||
|
montauk::user::home_dir(username, ds->home_dir, sizeof(ds->home_dir));
|
||||||
|
montauk::user::config_dir(username, ds->user_config_dir, sizeof(ds->user_config_dir));
|
||||||
|
|
||||||
|
// Check if user is admin
|
||||||
|
ds->is_admin = false;
|
||||||
|
{
|
||||||
|
montauk::user::UserInfo users[16];
|
||||||
|
int count = montauk::user::load_users(users, 16);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (montauk::streq(users[i].username, username)) {
|
||||||
|
ds->is_admin = montauk::streq(users[i].role, "admin");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_desktop = ds;
|
g_desktop = ds;
|
||||||
|
|
||||||
desktop_init(ds);
|
desktop_init(ds);
|
||||||
|
|||||||
+216
-36
@@ -105,14 +105,42 @@ void gui::desktop_draw_panel(DesktopState* ds) {
|
|||||||
int date_x = clock_x - date_w - 10;
|
int date_x = clock_x - date_w - 10;
|
||||||
draw_text(fb, date_x, clock_y, date_str, colors::PANEL_TEXT);
|
draw_text(fb, date_x, clock_y, date_str, colors::PANEL_TEXT);
|
||||||
|
|
||||||
// Network icon (to the left of the date)
|
// Volume icon (to the left of the date)
|
||||||
uint64_t now = montauk::get_milliseconds();
|
uint64_t now = montauk::get_milliseconds();
|
||||||
|
if (now - ds->vol_last_poll > 5000) {
|
||||||
|
int v = montauk::audio_get_volume(0);
|
||||||
|
if (v >= 0 && !ds->vol_muted) ds->vol_level = v;
|
||||||
|
ds->vol_last_poll = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vol_icon_x = date_x - 16 - 12;
|
||||||
|
int vol_icon_y = (PANEL_HEIGHT - 16) / 2;
|
||||||
|
ds->vol_icon_rect = {vol_icon_x, vol_icon_y, 16, 16};
|
||||||
|
|
||||||
|
if (ds->icon_volume.pixels) {
|
||||||
|
if (ds->vol_muted) {
|
||||||
|
// Tint red-ish when muted
|
||||||
|
uint32_t* src = ds->icon_volume.pixels;
|
||||||
|
int npx = 16 * 16;
|
||||||
|
uint32_t tinted[256];
|
||||||
|
for (int p = 0; p < npx; p++) {
|
||||||
|
uint32_t px = src[p];
|
||||||
|
uint8_t a = (px >> 24) & 0xFF;
|
||||||
|
tinted[p] = ((uint32_t)a << 24) | 0x00CC3333;
|
||||||
|
}
|
||||||
|
fb.blit_alpha(vol_icon_x, vol_icon_y, 16, 16, tinted);
|
||||||
|
} else {
|
||||||
|
fb.blit_alpha(vol_icon_x, vol_icon_y, ds->icon_volume.width, ds->icon_volume.height, ds->icon_volume.pixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network icon (to the left of the volume icon)
|
||||||
if (now - ds->net_cfg_last_poll > 5000) {
|
if (now - ds->net_cfg_last_poll > 5000) {
|
||||||
montauk::get_netcfg(&ds->cached_net_cfg);
|
montauk::get_netcfg(&ds->cached_net_cfg);
|
||||||
ds->net_cfg_last_poll = now;
|
ds->net_cfg_last_poll = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_icon_x = date_x - 16 - 12;
|
int net_icon_x = vol_icon_x - 16 - 10;
|
||||||
int net_icon_y = (PANEL_HEIGHT - 16) / 2;
|
int net_icon_y = (PANEL_HEIGHT - 16) / 2;
|
||||||
ds->net_icon_rect = {net_icon_x, net_icon_y, 16, 16};
|
ds->net_icon_rect = {net_icon_x, net_icon_y, 16, 16};
|
||||||
|
|
||||||
@@ -237,51 +265,203 @@ void desktop_draw_app_menu(DesktopState* ds) {
|
|||||||
|
|
||||||
void desktop_draw_net_popup(DesktopState* ds) {
|
void desktop_draw_net_popup(DesktopState* ds) {
|
||||||
Framebuffer& fb = ds->fb;
|
Framebuffer& fb = ds->fb;
|
||||||
|
Montauk::NetCfg& nc = ds->cached_net_cfg;
|
||||||
|
bool connected = nc.ipAddress != 0;
|
||||||
|
|
||||||
int popup_w = 220;
|
int popup_w = 220;
|
||||||
int popup_h = 130;
|
int fh = system_font_height();
|
||||||
|
int row_h = fh + 8;
|
||||||
|
int header_h = row_h + 8; // title + status row + padding
|
||||||
|
int body_rows = 5; // IP, Subnet, Gateway, DNS, MAC
|
||||||
|
int popup_h = header_h + row_h * body_rows + 12;
|
||||||
int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w;
|
int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w;
|
||||||
int popup_y = PANEL_HEIGHT + 2;
|
int popup_y = PANEL_HEIGHT + 2;
|
||||||
if (popup_x < 4) popup_x = 4;
|
if (popup_x < 4) popup_x = 4;
|
||||||
|
|
||||||
draw_shadow(fb, popup_x, popup_y, popup_w, popup_h, 4, colors::SHADOW);
|
draw_shadow(fb, popup_x, popup_y, popup_w, popup_h, 4, colors::SHADOW);
|
||||||
fb.fill_rect(popup_x, popup_y, popup_w, popup_h, colors::MENU_BG);
|
fill_rounded_rect(fb, popup_x, popup_y, popup_w, popup_h, 8, colors::MENU_BG);
|
||||||
draw_rect(fb, popup_x, popup_y, popup_w, popup_h, colors::BORDER);
|
draw_rect(fb, popup_x, popup_y, popup_w, popup_h, colors::BORDER);
|
||||||
|
|
||||||
int tx = popup_x + 12;
|
int lx = popup_x + 14;
|
||||||
int ty = popup_y + 10;
|
int ty = popup_y + 10;
|
||||||
int line_h = system_font_height() + 6;
|
|
||||||
char line[64];
|
|
||||||
|
|
||||||
Montauk::NetCfg& nc = ds->cached_net_cfg;
|
// Header: "Ethernet" + status dot
|
||||||
|
draw_text(fb, lx, ty, "Ethernet", colors::TEXT_COLOR);
|
||||||
|
|
||||||
if (nc.ipAddress != 0) {
|
// Status dot + label (right-aligned in header)
|
||||||
char ipbuf[20];
|
Color dot_color = connected
|
||||||
format_ip(ipbuf, nc.ipAddress);
|
? Color::from_rgb(0x4C, 0xAF, 0x50) // green
|
||||||
snprintf(line, sizeof(line), "IP: %s", ipbuf);
|
: Color::from_rgb(0xCC, 0x33, 0x33); // red
|
||||||
} else {
|
const char* status_str = connected ? "Connected" : "Disconnected";
|
||||||
snprintf(line, sizeof(line), "IP: Not connected");
|
int sw = text_width(status_str);
|
||||||
|
int dot_r = 4;
|
||||||
|
int status_x = popup_x + popup_w - 14 - sw;
|
||||||
|
int dot_x = status_x - dot_r * 2 - 5;
|
||||||
|
int dot_cy = ty + fh / 2;
|
||||||
|
for (int dy = -dot_r; dy <= dot_r; dy++)
|
||||||
|
for (int dx = -dot_r; dx <= dot_r; dx++)
|
||||||
|
if (dx * dx + dy * dy <= dot_r * dot_r)
|
||||||
|
fb.put_pixel(dot_x + dot_r + dx, dot_cy + dy, dot_color);
|
||||||
|
Color dim = Color::from_rgb(0x66, 0x66, 0x66);
|
||||||
|
draw_text(fb, status_x, ty, status_str, dim);
|
||||||
|
|
||||||
|
ty += row_h + 2;
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
for (int sx = popup_x + 10; sx < popup_x + popup_w - 10; sx++)
|
||||||
|
fb.put_pixel(sx, ty, colors::BORDER);
|
||||||
|
ty += 6;
|
||||||
|
|
||||||
|
// Body rows: label (dim) + value (dark), two-column
|
||||||
|
int val_x = popup_x + 76; // fixed column for values
|
||||||
|
|
||||||
|
struct NetRow { const char* label; char value[24]; };
|
||||||
|
NetRow rows[5];
|
||||||
|
|
||||||
|
rows[0].label = "IP";
|
||||||
|
if (connected) format_ip(rows[0].value, nc.ipAddress);
|
||||||
|
else montauk::strcpy(rows[0].value, "\xE2\x80\x94"); // em dash
|
||||||
|
|
||||||
|
rows[1].label = "Subnet";
|
||||||
|
format_ip(rows[1].value, nc.subnetMask);
|
||||||
|
|
||||||
|
rows[2].label = "Gateway";
|
||||||
|
format_ip(rows[2].value, nc.gateway);
|
||||||
|
|
||||||
|
rows[3].label = "DNS";
|
||||||
|
format_ip(rows[3].value, nc.dnsServer);
|
||||||
|
|
||||||
|
rows[4].label = "MAC";
|
||||||
|
format_mac(rows[4].value, nc.macAddress);
|
||||||
|
|
||||||
|
for (int i = 0; i < body_rows; i++) {
|
||||||
|
draw_text(fb, lx, ty, rows[i].label, dim);
|
||||||
|
draw_text(fb, val_x, ty, rows[i].value, colors::TEXT_COLOR);
|
||||||
|
ty += row_h;
|
||||||
}
|
}
|
||||||
draw_text(fb, tx, ty, line, colors::TEXT_COLOR);
|
}
|
||||||
ty += line_h;
|
|
||||||
|
// ============================================================================
|
||||||
char buf[20];
|
// Volume Popup
|
||||||
format_ip(buf, nc.subnetMask);
|
// ============================================================================
|
||||||
snprintf(line, sizeof(line), "Subnet: %s", buf);
|
|
||||||
draw_text(fb, tx, ty, line, colors::TEXT_COLOR);
|
static constexpr int VOL_POPUP_W = 200;
|
||||||
ty += line_h;
|
static constexpr int VOL_POPUP_H = 120;
|
||||||
|
static constexpr int VOL_SLIDER_X = 16;
|
||||||
format_ip(buf, nc.gateway);
|
static constexpr int VOL_SLIDER_W = VOL_POPUP_W - 32;
|
||||||
snprintf(line, sizeof(line), "Gateway: %s", buf);
|
static constexpr int VOL_SLIDER_H = 8;
|
||||||
draw_text(fb, tx, ty, line, colors::TEXT_COLOR);
|
static constexpr int VOL_KNOB_R = 8;
|
||||||
ty += line_h;
|
|
||||||
|
void desktop_draw_vol_popup(DesktopState* ds) {
|
||||||
format_ip(buf, nc.dnsServer);
|
Framebuffer& fb = ds->fb;
|
||||||
snprintf(line, sizeof(line), "DNS: %s", buf);
|
|
||||||
draw_text(fb, tx, ty, line, colors::TEXT_COLOR);
|
int popup_x = ds->vol_icon_rect.x + ds->vol_icon_rect.w - VOL_POPUP_W;
|
||||||
ty += line_h;
|
int popup_y = PANEL_HEIGHT + 2;
|
||||||
|
if (popup_x < 4) popup_x = 4;
|
||||||
format_mac(buf, nc.macAddress);
|
|
||||||
snprintf(line, sizeof(line), "MAC: %s", buf);
|
draw_shadow(fb, popup_x, popup_y, VOL_POPUP_W, VOL_POPUP_H, 4, colors::SHADOW);
|
||||||
draw_text(fb, tx, ty, line, colors::TEXT_COLOR);
|
fill_rounded_rect(fb, popup_x, popup_y, VOL_POPUP_W, VOL_POPUP_H, 8, colors::MENU_BG);
|
||||||
|
draw_rect(fb, popup_x, popup_y, VOL_POPUP_W, VOL_POPUP_H, colors::BORDER);
|
||||||
|
|
||||||
|
int display_vol = ds->vol_muted ? 0 : ds->vol_level;
|
||||||
|
|
||||||
|
// Volume percentage label
|
||||||
|
char vol_str[8];
|
||||||
|
snprintf(vol_str, sizeof(vol_str), "%d%%", display_vol);
|
||||||
|
int vw = text_width(vol_str);
|
||||||
|
Color vol_color = ds->vol_muted ? Color::from_rgb(0xCC, 0x33, 0x33) : ds->settings.accent_color;
|
||||||
|
draw_text(fb, popup_x + (VOL_POPUP_W - vw) / 2, popup_y + 12, vol_str, vol_color);
|
||||||
|
|
||||||
|
// "Muted" sub-label
|
||||||
|
if (ds->vol_muted) {
|
||||||
|
const char* ml = "Muted";
|
||||||
|
int mw = text_width(ml);
|
||||||
|
draw_text(fb, popup_x + (VOL_POPUP_W - mw) / 2,
|
||||||
|
popup_y + 12 + system_font_height() + 2, ml,
|
||||||
|
Color::from_rgb(0xCC, 0x33, 0x33));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slider track
|
||||||
|
int slider_abs_x = popup_x + VOL_SLIDER_X;
|
||||||
|
int slider_abs_y = popup_y + 56;
|
||||||
|
fill_rounded_rect(fb, slider_abs_x, slider_abs_y, VOL_SLIDER_W, VOL_SLIDER_H, 4,
|
||||||
|
Color::from_rgb(0xDD, 0xDD, 0xDD));
|
||||||
|
|
||||||
|
// Filled portion
|
||||||
|
int fill_w = (display_vol * VOL_SLIDER_W) / 100;
|
||||||
|
if (fill_w > 0)
|
||||||
|
fill_rounded_rect(fb, slider_abs_x, slider_abs_y, fill_w, VOL_SLIDER_H, 4,
|
||||||
|
ds->settings.accent_color);
|
||||||
|
|
||||||
|
// Knob
|
||||||
|
int knob_cx = slider_abs_x + fill_w;
|
||||||
|
int knob_cy = slider_abs_y + VOL_SLIDER_H / 2;
|
||||||
|
// Draw filled circle for knob
|
||||||
|
for (int dy = -VOL_KNOB_R; dy <= VOL_KNOB_R; dy++) {
|
||||||
|
for (int dx = -VOL_KNOB_R; dx <= VOL_KNOB_R; dx++) {
|
||||||
|
if (dx * dx + dy * dy <= VOL_KNOB_R * VOL_KNOB_R) {
|
||||||
|
int px = knob_cx + dx;
|
||||||
|
int py = knob_cy + dy;
|
||||||
|
if (px >= 0 && px < ds->screen_w && py >= 0 && py < ds->screen_h)
|
||||||
|
fb.put_pixel(px, py, ds->settings.accent_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// White center
|
||||||
|
int inner_r = VOL_KNOB_R - 3;
|
||||||
|
for (int dy = -inner_r; dy <= inner_r; dy++) {
|
||||||
|
for (int dx = -inner_r; dx <= inner_r; dx++) {
|
||||||
|
if (dx * dx + dy * dy <= inner_r * inner_r) {
|
||||||
|
int px = knob_cx + dx;
|
||||||
|
int py = knob_cy + dy;
|
||||||
|
if (px >= 0 && px < ds->screen_w && py >= 0 && py < ds->screen_h)
|
||||||
|
fb.put_pixel(px, py, Color::from_rgb(0xFF, 0xFF, 0xFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons: [-] [+] [Mute]
|
||||||
|
int btn_h = 24;
|
||||||
|
int btn_y = popup_y + 78;
|
||||||
|
int btn_rad = 6;
|
||||||
|
|
||||||
|
int minus_w = 36;
|
||||||
|
int plus_w = 36;
|
||||||
|
int mute_w = 50;
|
||||||
|
int gap = 8;
|
||||||
|
int total_w = minus_w + plus_w + mute_w + gap * 2;
|
||||||
|
int bx = popup_x + (VOL_POPUP_W - total_w) / 2;
|
||||||
|
|
||||||
|
int mmx = ds->mouse.x;
|
||||||
|
int mmy = ds->mouse.y;
|
||||||
|
|
||||||
|
// [-] button
|
||||||
|
Color minus_bg = Color::from_rgb(0xE0, 0xE0, 0xE0);
|
||||||
|
Rect minus_r = {bx, btn_y, minus_w, btn_h};
|
||||||
|
if (minus_r.contains(mmx, mmy)) minus_bg = Color::from_rgb(0xD0, 0xD0, 0xD0);
|
||||||
|
fill_rounded_rect(fb, bx, btn_y, minus_w, btn_h, btn_rad, minus_bg);
|
||||||
|
int tw = text_width("-");
|
||||||
|
draw_text(fb, bx + (minus_w - tw) / 2, btn_y + (btn_h - system_font_height()) / 2, "-", colors::TEXT_COLOR);
|
||||||
|
bx += minus_w + gap;
|
||||||
|
|
||||||
|
// [+] button
|
||||||
|
Color plus_bg = Color::from_rgb(0xE0, 0xE0, 0xE0);
|
||||||
|
Rect plus_r = {bx, btn_y, plus_w, btn_h};
|
||||||
|
if (plus_r.contains(mmx, mmy)) plus_bg = Color::from_rgb(0xD0, 0xD0, 0xD0);
|
||||||
|
fill_rounded_rect(fb, bx, btn_y, plus_w, btn_h, btn_rad, plus_bg);
|
||||||
|
tw = text_width("+");
|
||||||
|
draw_text(fb, bx + (plus_w - tw) / 2, btn_y + (btn_h - system_font_height()) / 2, "+", colors::TEXT_COLOR);
|
||||||
|
bx += plus_w + gap;
|
||||||
|
|
||||||
|
// [Mute] button
|
||||||
|
Color mute_bg = ds->vol_muted ? Color::from_rgb(0xCC, 0x33, 0x33) : Color::from_rgb(0xE0, 0xE0, 0xE0);
|
||||||
|
Color mute_fg = ds->vol_muted ? Color::from_rgb(0xFF, 0xFF, 0xFF) : colors::TEXT_COLOR;
|
||||||
|
Rect mute_r = {bx, btn_y, mute_w, btn_h};
|
||||||
|
if (mute_r.contains(mmx, mmy)) {
|
||||||
|
if (ds->vol_muted) mute_bg = Color::from_rgb(0xAA, 0x22, 0x22);
|
||||||
|
else mute_bg = Color::from_rgb(0xD0, 0xD0, 0xD0);
|
||||||
|
}
|
||||||
|
fill_rounded_rect(fb, bx, btn_y, mute_w, btn_h, btn_rad, mute_bg);
|
||||||
|
tw = text_width("Mute");
|
||||||
|
draw_text(fb, bx + (mute_w - tw) / 2, btn_y + (btn_h - system_font_height()) / 2, "Mute", mute_fg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,26 @@ static int generate_index_page(char* buf, int bufSize) {
|
|||||||
(unsigned)hours, (unsigned)mins, (unsigned)secs);
|
(unsigned)hours, (unsigned)mins, (unsigned)secs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTML-escape a string to prevent XSS (escapes <, >, &, ", ')
|
||||||
|
static int html_escape(const char* in, char* out, int outMax) {
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; in[i] && j < outMax - 6; i++) {
|
||||||
|
switch (in[i]) {
|
||||||
|
case '<': out[j++]='&'; out[j++]='l'; out[j++]='t'; out[j++]=';'; break;
|
||||||
|
case '>': out[j++]='&'; out[j++]='g'; out[j++]='t'; out[j++]=';'; break;
|
||||||
|
case '&': out[j++]='&'; out[j++]='a'; out[j++]='m'; out[j++]='p'; out[j++]=';'; break;
|
||||||
|
case '"': out[j++]='&'; out[j++]='q'; out[j++]='u'; out[j++]='o'; out[j++]='t'; out[j++]=';'; break;
|
||||||
|
case '\'': out[j++]='&'; out[j++]='#'; out[j++]='3'; out[j++]='9'; out[j++]=';'; break;
|
||||||
|
default: out[j++] = in[i]; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out[j] = '\0';
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
static int generate_404_page(char* buf, int bufSize, const char* path) {
|
static int generate_404_page(char* buf, int bufSize, const char* path) {
|
||||||
|
char escaped[512];
|
||||||
|
html_escape(path, escaped, sizeof(escaped));
|
||||||
return snprintf(buf, bufSize,
|
return snprintf(buf, bufSize,
|
||||||
"<!DOCTYPE html>\n"
|
"<!DOCTYPE html>\n"
|
||||||
"<html>\n"
|
"<html>\n"
|
||||||
@@ -278,7 +297,7 @@ static int generate_404_page(char* buf, int bufSize, const char* path) {
|
|||||||
"<p><a href=\"/\">Back to home</a></p>\n"
|
"<p><a href=\"/\">Back to home</a></p>\n"
|
||||||
"</body>\n"
|
"</body>\n"
|
||||||
"</html>\n",
|
"</html>\n",
|
||||||
path);
|
escaped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int generate_dir_listing(char* buf, int bufSize, const char* urlPath, const char* vfsDir) {
|
static int generate_dir_listing(char* buf, int bufSize, const char* urlPath, const char* vfsDir) {
|
||||||
@@ -322,10 +341,12 @@ static int generate_dir_listing(char* buf, int bufSize, const char* urlPath, con
|
|||||||
}
|
}
|
||||||
if (*name == '\0') continue;
|
if (*name == '\0') continue;
|
||||||
|
|
||||||
// Build the URL for this entry
|
// Build the URL for this entry (HTML-escape the name)
|
||||||
|
char esc_name[256];
|
||||||
|
html_escape(name, esc_name, sizeof(esc_name));
|
||||||
pos += snprintf(buf + pos, bufSize - pos,
|
pos += snprintf(buf + pos, bufSize - pos,
|
||||||
"<li><a href=\"%s%s\">%s</a></li>\n",
|
"<li><a href=\"%s%s\">%s</a></li>\n",
|
||||||
urlPath, name, name);
|
urlPath, name, esc_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += snprintf(buf + pos, bufSize - pos,
|
pos += snprintf(buf + pos, bufSize - pos,
|
||||||
@@ -415,6 +436,29 @@ static void handle_client(int clientFd) {
|
|||||||
// Serve file or directory from VFS
|
// Serve file or directory from VFS
|
||||||
const char* relPath = path + 7; // skip "/files/"
|
const char* relPath = path + 7; // skip "/files/"
|
||||||
|
|
||||||
|
// Reject path traversal attempts
|
||||||
|
if (starts_with(relPath, "..") || starts_with(relPath, "/")) {
|
||||||
|
static char body[] = "<!DOCTYPE html><html><body><h1>403 Forbidden</h1></body></html>";
|
||||||
|
send_response(clientFd, 403, "Forbidden", "text/html", body, slen(body));
|
||||||
|
log_request("GET", path, 403, slen(body));
|
||||||
|
montauk::closesocket(clientFd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check for /../ or trailing /.. anywhere in the path
|
||||||
|
for (int ci = 0; relPath[ci]; ci++) {
|
||||||
|
if (relPath[ci] == '.' && relPath[ci+1] == '.') {
|
||||||
|
if (ci == 0 || relPath[ci-1] == '/') {
|
||||||
|
if (relPath[ci+2] == '\0' || relPath[ci+2] == '/') {
|
||||||
|
static char body[] = "<!DOCTYPE html><html><body><h1>403 Forbidden</h1></body></html>";
|
||||||
|
send_response(clientFd, 403, "Forbidden", "text/html", body, slen(body));
|
||||||
|
log_request("GET", path, 403, slen(body));
|
||||||
|
montauk::closesocket(clientFd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build VFS path: "0:/<relPath>"
|
// Build VFS path: "0:/<relPath>"
|
||||||
char vfsPath[256];
|
char vfsPath[256];
|
||||||
int pi = 0;
|
int pi = 0;
|
||||||
|
|||||||
@@ -157,10 +157,13 @@ extern "C" void _start() {
|
|||||||
// ---- Stage 1: Network configuration (non-blocking) ----
|
// ---- Stage 1: Network configuration (non-blocking) ----
|
||||||
run_service("0:/os/dhcp.elf", "dhcp", false);
|
run_service("0:/os/dhcp.elf", "dhcp", false);
|
||||||
|
|
||||||
// ---- Stage 2: Desktop environment (falls back to shell) ----
|
// ---- Stage 2: Login screen -> desktop (falls back to desktop, then shell) ----
|
||||||
if (!run_service("0:/os/desktop.elf", "desktop")) {
|
if (!run_service("0:/os/login.elf", "login")) {
|
||||||
log_warn("Desktop failed, falling back to shell");
|
log_warn("Login failed, falling back to desktop");
|
||||||
run_service("0:/os/shell.elf", "shell");
|
if (!run_service("0:/os/desktop.elf", "desktop")) {
|
||||||
|
log_warn("Desktop failed, falling back to shell");
|
||||||
|
run_service("0:/os/shell.elf", "shell");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warn("All services exited");
|
log_warn("All services exited");
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# Makefile for login (graphical login screen) on MontaukOS
|
||||||
|
# Copyright (c) 2026 Daniel Hammer
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
# ---- Toolchain ----
|
||||||
|
|
||||||
|
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||||
|
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||||
|
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||||
|
else
|
||||||
|
CXX := g++
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---- Paths ----
|
||||||
|
|
||||||
|
PROG_INC := ../../include
|
||||||
|
LIBC_LIB := ../../lib/libc
|
||||||
|
JPEG_LIB := ../../lib/libjpeg
|
||||||
|
BEARSSL := ../../lib/bearssl
|
||||||
|
LINK_LD := ../../link.ld
|
||||||
|
BINDIR := ../../bin
|
||||||
|
OBJDIR := obj
|
||||||
|
|
||||||
|
# ---- Compiler flags ----
|
||||||
|
|
||||||
|
CXXFLAGS := \
|
||||||
|
-std=gnu++20 \
|
||||||
|
-g -O2 -pipe \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-nostdinc \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-PIC \
|
||||||
|
-fno-rtti \
|
||||||
|
-fno-exceptions \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-msse \
|
||||||
|
-msse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=small \
|
||||||
|
-I $(PROG_INC) \
|
||||||
|
-isystem $(PROG_INC)/libc \
|
||||||
|
-I $(BEARSSL)/inc \
|
||||||
|
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||||
|
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||||
|
|
||||||
|
# ---- Linker flags ----
|
||||||
|
|
||||||
|
LDFLAGS := \
|
||||||
|
-nostdlib \
|
||||||
|
-static \
|
||||||
|
-Wl,--build-id=none \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-m,elf_x86_64 \
|
||||||
|
-z max-page-size=0x1000 \
|
||||||
|
-T $(LINK_LD)
|
||||||
|
|
||||||
|
# ---- Source files ----
|
||||||
|
|
||||||
|
SRCS := main.cpp stb_truetype_impl.cpp font_data.cpp
|
||||||
|
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||||
|
DEPS := $(OBJS:.o=.d)
|
||||||
|
|
||||||
|
# ---- Target ----
|
||||||
|
|
||||||
|
TARGET := $(BINDIR)/os/login.elf
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
LIBS := $(JPEG_LIB)/libjpeg.a $(BEARSSL)/libbearssl.a $(LIBC_LIB)/liblibc.a
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS) $(LIBS) $(LINK_LD) Makefile
|
||||||
|
mkdir -p $(BINDIR)/os
|
||||||
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp Makefile
|
||||||
|
mkdir -p $(OBJDIR)
|
||||||
|
$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@
|
||||||
|
|
||||||
|
-include $(DEPS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIR) $(TARGET)
|
||||||
@@ -0,0 +1,783 @@
|
|||||||
|
/*
|
||||||
|
* font_data.cpp
|
||||||
|
* Standard VGA 8x16 bitmap font (Code Page 437)
|
||||||
|
* 256 characters, 16 bytes each (8 pixels wide, 1 bit per pixel, MSB left)
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gui/font.hpp"
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
|
||||||
|
const uint8_t font_data[256 * 16] = {
|
||||||
|
// Character 0 (NUL)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 1 (smiley face)
|
||||||
|
0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD,
|
||||||
|
0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 2 (inverse smiley)
|
||||||
|
0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3,
|
||||||
|
0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 3 (heart)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE,
|
||||||
|
0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 4 (diamond)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE,
|
||||||
|
0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 5 (club)
|
||||||
|
0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7,
|
||||||
|
0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 6 (spade)
|
||||||
|
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF,
|
||||||
|
0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 7 (bullet)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C,
|
||||||
|
0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 8 (inverse bullet)
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3,
|
||||||
|
0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
// Character 9 (circle)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42,
|
||||||
|
0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 10 (inverse circle)
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD,
|
||||||
|
0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
// Character 11 (male sign)
|
||||||
|
0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 12 (female sign)
|
||||||
|
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C,
|
||||||
|
0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 13 (note)
|
||||||
|
0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 14 (double note)
|
||||||
|
0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63,
|
||||||
|
0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00,
|
||||||
|
// Character 15 (sun)
|
||||||
|
0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7,
|
||||||
|
0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 16 (right triangle)
|
||||||
|
0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8,
|
||||||
|
0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 17 (left triangle)
|
||||||
|
0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E,
|
||||||
|
0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 18 (up-down arrow)
|
||||||
|
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
|
||||||
|
0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 19 (double exclamation)
|
||||||
|
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 20 (paragraph)
|
||||||
|
0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B,
|
||||||
|
0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 21 (section)
|
||||||
|
0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6,
|
||||||
|
0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00,
|
||||||
|
// Character 22 (thick underscore)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 23 (up-down arrow underlined)
|
||||||
|
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
|
||||||
|
0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 24 (up arrow)
|
||||||
|
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 25 (down arrow)
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 26 (right arrow)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE,
|
||||||
|
0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 27 (left arrow)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE,
|
||||||
|
0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 28 (right angle)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
|
||||||
|
0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 29 (left-right arrow)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF,
|
||||||
|
0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 30 (up triangle)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C,
|
||||||
|
0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 31 (down triangle)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C,
|
||||||
|
0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 32 (space)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 33 '!'
|
||||||
|
0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18,
|
||||||
|
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 34 '"'
|
||||||
|
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 35 '#'
|
||||||
|
0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C,
|
||||||
|
0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 36 '$'
|
||||||
|
0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06,
|
||||||
|
0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00,
|
||||||
|
// Character 37 '%'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18,
|
||||||
|
0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 38 '&'
|
||||||
|
0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 39 '''
|
||||||
|
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 40 '('
|
||||||
|
0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 41 ')'
|
||||||
|
0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||||
|
0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 42 '*'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF,
|
||||||
|
0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 43 '+'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E,
|
||||||
|
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 44 ','
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
|
||||||
|
// Character 45 '-'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 46 '.'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 47 '/'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18,
|
||||||
|
0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 48 '0'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6,
|
||||||
|
0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 49 '1'
|
||||||
|
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 50 '2'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30,
|
||||||
|
0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 51 '3'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06,
|
||||||
|
0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 52 '4'
|
||||||
|
0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE,
|
||||||
|
0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 53 '5'
|
||||||
|
0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06,
|
||||||
|
0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 54 '6'
|
||||||
|
0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 55 '7'
|
||||||
|
0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18,
|
||||||
|
0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 56 '8'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 57 '9'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06,
|
||||||
|
0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 58 ':'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 59 ';'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 60 '<'
|
||||||
|
0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60,
|
||||||
|
0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 61 '='
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00,
|
||||||
|
0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 62 '>'
|
||||||
|
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06,
|
||||||
|
0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 63 '?'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18,
|
||||||
|
0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 64 '@'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xDE, 0xDE,
|
||||||
|
0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 65 'A'
|
||||||
|
0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE,
|
||||||
|
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 66 'B'
|
||||||
|
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 67 'C'
|
||||||
|
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0,
|
||||||
|
0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 68 'D'
|
||||||
|
0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 69 'E'
|
||||||
|
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68,
|
||||||
|
0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 70 'F'
|
||||||
|
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68,
|
||||||
|
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 71 'G'
|
||||||
|
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE,
|
||||||
|
0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 72 'H'
|
||||||
|
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 73 'I'
|
||||||
|
0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 74 'J'
|
||||||
|
0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 75 'K'
|
||||||
|
0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78,
|
||||||
|
0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 76 'L'
|
||||||
|
0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60,
|
||||||
|
0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 77 'M'
|
||||||
|
0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 78 'N'
|
||||||
|
0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE,
|
||||||
|
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 79 'O'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 80 'P'
|
||||||
|
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60,
|
||||||
|
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 81 'Q'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00,
|
||||||
|
// Character 82 'R'
|
||||||
|
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C,
|
||||||
|
0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 83 'S'
|
||||||
|
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C,
|
||||||
|
0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 84 'T'
|
||||||
|
0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 85 'U'
|
||||||
|
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 86 'V'
|
||||||
|
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 87 'W'
|
||||||
|
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6,
|
||||||
|
0xD6, 0xFE, 0xEE, 0x6C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 88 'X'
|
||||||
|
0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38,
|
||||||
|
0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 89 'Y'
|
||||||
|
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 90 'Z'
|
||||||
|
0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30,
|
||||||
|
0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 91 '['
|
||||||
|
0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 92 '\'
|
||||||
|
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38,
|
||||||
|
0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 93 ']'
|
||||||
|
0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
|
||||||
|
0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 94 '^'
|
||||||
|
0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 95 '_'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
|
||||||
|
// Character 96 '`'
|
||||||
|
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 97 'a'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 98 'b'
|
||||||
|
0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 99 'c'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0,
|
||||||
|
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 100 'd'
|
||||||
|
0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 101 'e'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE,
|
||||||
|
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 102 'f'
|
||||||
|
0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60,
|
||||||
|
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 103 'g'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00,
|
||||||
|
// Character 104 'h'
|
||||||
|
0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 105 'i'
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 106 'j'
|
||||||
|
0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00,
|
||||||
|
// Character 107 'k'
|
||||||
|
0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78,
|
||||||
|
0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 108 'l'
|
||||||
|
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 109 'm'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6,
|
||||||
|
0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 110 'n'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 111 'o'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 112 'p'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
|
||||||
|
// Character 113 'q'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00,
|
||||||
|
// Character 114 'r'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66,
|
||||||
|
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 115 's'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60,
|
||||||
|
0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 116 't'
|
||||||
|
0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30,
|
||||||
|
0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 117 'u'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 118 'v'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 119 'w'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6,
|
||||||
|
0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 120 'x'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38,
|
||||||
|
0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 121 'y'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00,
|
||||||
|
// Character 122 'z'
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18,
|
||||||
|
0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 123 '{'
|
||||||
|
0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 124 '|'
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 125 '}'
|
||||||
|
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 126 '~'
|
||||||
|
0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 127 (DEL - block)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6,
|
||||||
|
0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 128 (C cedilla)
|
||||||
|
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0,
|
||||||
|
0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00,
|
||||||
|
// Character 129 (u umlaut)
|
||||||
|
0x00, 0x00, 0xCC, 0x00, 0x00, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 130 (e acute)
|
||||||
|
0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE,
|
||||||
|
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 131 (a circumflex)
|
||||||
|
0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 132 (a umlaut)
|
||||||
|
0x00, 0x00, 0xCC, 0x00, 0x00, 0x78, 0x0C, 0x7C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 133 (a grave)
|
||||||
|
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 134 (a ring)
|
||||||
|
0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 135 (c cedilla)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0,
|
||||||
|
0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, 0x00, 0x00,
|
||||||
|
// Character 136 (e circumflex)
|
||||||
|
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE,
|
||||||
|
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 137 (e umlaut)
|
||||||
|
0x00, 0x00, 0xC6, 0x00, 0x00, 0x7C, 0xC6, 0xFE,
|
||||||
|
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 138 (e grave)
|
||||||
|
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE,
|
||||||
|
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 139 (i umlaut)
|
||||||
|
0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 140 (i circumflex)
|
||||||
|
0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 141 (i grave)
|
||||||
|
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 142 (A umlaut)
|
||||||
|
0x00, 0xC6, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6,
|
||||||
|
0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 143 (A ring)
|
||||||
|
0x38, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0xC6, 0xC6,
|
||||||
|
0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 144 (E acute)
|
||||||
|
0x0C, 0x18, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78,
|
||||||
|
0x68, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 145 (ae)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x3B, 0x1B,
|
||||||
|
0x7E, 0xD8, 0xDC, 0x77, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 146 (AE)
|
||||||
|
0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 147 (o circumflex)
|
||||||
|
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 148 (o umlaut)
|
||||||
|
0x00, 0x00, 0xC6, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 149 (o grave)
|
||||||
|
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 150 (u circumflex)
|
||||||
|
0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 151 (u grave)
|
||||||
|
0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 152 (y umlaut)
|
||||||
|
0x00, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00,
|
||||||
|
// Character 153 (O umlaut)
|
||||||
|
0x00, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 154 (U umlaut)
|
||||||
|
0x00, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 155 (cent)
|
||||||
|
0x00, 0x18, 0x18, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0,
|
||||||
|
0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 156 (pound)
|
||||||
|
0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60,
|
||||||
|
0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 157 (yen)
|
||||||
|
0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0xFE, 0x38,
|
||||||
|
0xFE, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 158 (Pt)
|
||||||
|
0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE,
|
||||||
|
0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 159 (f hook)
|
||||||
|
0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18,
|
||||||
|
0x18, 0x18, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 160 (a acute)
|
||||||
|
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 161 (i acute)
|
||||||
|
0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 162 (o acute)
|
||||||
|
0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 163 (u acute)
|
||||||
|
0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC,
|
||||||
|
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 164 (n tilde)
|
||||||
|
0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 165 (N tilde)
|
||||||
|
0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE,
|
||||||
|
0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 166 (feminine ordinal)
|
||||||
|
0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 167 (masculine ordinal)
|
||||||
|
0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 168 (inverted question)
|
||||||
|
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60,
|
||||||
|
0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 169 (not left)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0,
|
||||||
|
0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 170 (not right)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06,
|
||||||
|
0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 171 (fraction 1/2)
|
||||||
|
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30,
|
||||||
|
0x60, 0xDC, 0x86, 0x0C, 0x18, 0x3E, 0x00, 0x00,
|
||||||
|
// Character 172 (fraction 1/4)
|
||||||
|
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30,
|
||||||
|
0x66, 0xCE, 0x9E, 0x3E, 0x06, 0x06, 0x00, 0x00,
|
||||||
|
// Character 173 (inverted exclamation)
|
||||||
|
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18,
|
||||||
|
0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 174 (double left angle)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6C, 0xD8,
|
||||||
|
0x6C, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 175 (double right angle)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x6C, 0x36,
|
||||||
|
0x6C, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 176 (light shade)
|
||||||
|
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
|
||||||
|
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
|
||||||
|
// Character 177 (medium shade)
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||||
|
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
|
||||||
|
// Character 178 (dark shade)
|
||||||
|
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
|
||||||
|
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
|
||||||
|
// Character 179 (box vertical)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 180 (box vertical-left)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 181 (box double vertical-left single)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 182 (box double vertical-left)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 183 (box double horizontal-down)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 184 (box double vertical-left single)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 185 (box double vertical-left double)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 186 (box double vertical)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 187 (box double down-left)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 188 (box double up-left)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 189 (box double up-right)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 190 (box horizontal-down)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 191 (box down-left)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 192 (box up-right)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 193 (box horizontal-up)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 194 (box horizontal-down)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 195 (box vertical-right)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 196 (box horizontal)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 197 (box cross)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 198 (box single vert-right double)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 199 (box double vert-right)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 200 (box double up-right)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 201 (box double down-right)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 202 (box double horizontal-up)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 203 (box double horizontal-down)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 204 (box double vertical-right)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 205 (box double horizontal)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 206 (box double cross)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 207 (box single horiz-up double)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 208 (box double horizontal-up single)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 209 (box single horiz-down double)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 210 (box double horizontal-down single)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 211 (box double up-right single)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 212 (box single up-right double)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 213 (box single down-right double)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 214 (box double down-right single)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 215 (box double cross single)
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||||
|
// Character 216 (box single cross double)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 217 (box up-left)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 218 (box down-right)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 219 (full block)
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
// Character 220 (bottom half block)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
// Character 221 (left half block)
|
||||||
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||||
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||||
|
// Character 222 (right half block)
|
||||||
|
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||||
|
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||||
|
// Character 223 (top half block)
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 224 (alpha)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8,
|
||||||
|
0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 225 (beta/sharp s)
|
||||||
|
0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0xD8, 0xCC,
|
||||||
|
0xC6, 0xC6, 0xC6, 0xCC, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 226 (gamma)
|
||||||
|
0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0,
|
||||||
|
0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 227 (pi)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C,
|
||||||
|
0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 228 (sigma uppercase)
|
||||||
|
0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18,
|
||||||
|
0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 229 (sigma lowercase)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8,
|
||||||
|
0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 230 (mu)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
|
||||||
|
0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00,
|
||||||
|
// Character 231 (tau)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 232 (phi uppercase)
|
||||||
|
0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66,
|
||||||
|
0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 233 (theta)
|
||||||
|
0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE,
|
||||||
|
0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 234 (omega)
|
||||||
|
0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 235 (delta)
|
||||||
|
0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66,
|
||||||
|
0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 236 (infinity)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDB, 0xDB,
|
||||||
|
0xDB, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 237 (phi lowercase)
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x06, 0x7C, 0xCE, 0xDE,
|
||||||
|
0xF6, 0xE6, 0x7C, 0xC0, 0x80, 0x00, 0x00, 0x00,
|
||||||
|
// Character 238 (epsilon)
|
||||||
|
0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60,
|
||||||
|
0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 239 (intersection)
|
||||||
|
0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6,
|
||||||
|
0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 240 (triple bar)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 241 (plus-minus)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18,
|
||||||
|
0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 242 (greater-equal)
|
||||||
|
0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C,
|
||||||
|
0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 243 (less-equal)
|
||||||
|
0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30,
|
||||||
|
0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 244 (top integral)
|
||||||
|
0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
// Character 245 (bottom integral)
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00,
|
||||||
|
// Character 246 (division)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E,
|
||||||
|
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 247 (approximately equal)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00,
|
||||||
|
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 248 (degree)
|
||||||
|
0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 249 (bullet operator)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 250 (middle dot)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 251 (square root)
|
||||||
|
0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC,
|
||||||
|
0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 252 (superscript n)
|
||||||
|
0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 253 (superscript 2)
|
||||||
|
0x00, 0x70, 0xD8, 0x30, 0x60, 0xC8, 0xF8, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 254 (filled square)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C,
|
||||||
|
0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Character 255 (non-breaking space)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gui
|
||||||
@@ -0,0 +1,790 @@
|
|||||||
|
/*
|
||||||
|
* main.cpp
|
||||||
|
* MontaukOS graphical login screen
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/user.h>
|
||||||
|
#include <montauk/config.h>
|
||||||
|
#include <gui/gui.hpp>
|
||||||
|
#include <gui/framebuffer.hpp>
|
||||||
|
#include <gui/draw.hpp>
|
||||||
|
#include <gui/svg.hpp>
|
||||||
|
#include <gui/font.hpp>
|
||||||
|
|
||||||
|
// Forward-declare stb_image functions (implementation in libjpeg.a).
|
||||||
|
extern "C" {
|
||||||
|
unsigned char* stbi_load_from_memory(const unsigned char* buffer, int len,
|
||||||
|
int* x, int* y, int* channels_in_file,
|
||||||
|
int desired_channels);
|
||||||
|
void stbi_image_free(void* retval_from_stbi_load);
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace gui;
|
||||||
|
|
||||||
|
// Placement new
|
||||||
|
inline void* operator new(unsigned long, void* p) { return p; }
|
||||||
|
|
||||||
|
// ---- Minimal snprintf ----
|
||||||
|
|
||||||
|
using va_list = __builtin_va_list;
|
||||||
|
#define va_start __builtin_va_start
|
||||||
|
#define va_end __builtin_va_end
|
||||||
|
#define va_arg __builtin_va_arg
|
||||||
|
|
||||||
|
struct PfState { char* buf; int pos; int max; };
|
||||||
|
static void pf_putc(PfState* st, char c) {
|
||||||
|
if (st->pos < st->max) st->buf[st->pos] = c;
|
||||||
|
st->pos++;
|
||||||
|
}
|
||||||
|
static void pf_putnum(PfState* st, unsigned long val, int base, int width, char pad, int neg) {
|
||||||
|
char tmp[24]; int i = 0;
|
||||||
|
const char* digits = "0123456789abcdef";
|
||||||
|
if (val == 0) { tmp[i++] = '0'; }
|
||||||
|
else { while (val > 0) { tmp[i++] = digits[val % base]; val /= base; } }
|
||||||
|
int total = (neg ? 1 : 0) + i;
|
||||||
|
if (neg && pad == '0') pf_putc(st, '-');
|
||||||
|
for (int w = total; w < width; w++) pf_putc(st, pad);
|
||||||
|
if (neg && pad != '0') pf_putc(st, '-');
|
||||||
|
while (i > 0) pf_putc(st, tmp[--i]);
|
||||||
|
}
|
||||||
|
static int snprintf(char* buf, int size, const char* fmt, ...) {
|
||||||
|
va_list ap; va_start(ap, fmt);
|
||||||
|
PfState st; st.buf = buf; st.pos = 0; st.max = size > 0 ? size - 1 : 0;
|
||||||
|
while (*fmt) {
|
||||||
|
if (*fmt != '%') { pf_putc(&st, *fmt++); continue; }
|
||||||
|
fmt++;
|
||||||
|
char pad = ' ';
|
||||||
|
if (*fmt == '0') { pad = '0'; fmt++; }
|
||||||
|
int width = 0;
|
||||||
|
while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + (*fmt - '0'); fmt++; }
|
||||||
|
if (*fmt == 'l') fmt++;
|
||||||
|
switch (*fmt) {
|
||||||
|
case 'd': case 'i': {
|
||||||
|
long val = va_arg(ap, int);
|
||||||
|
int neg = 0; unsigned long uval;
|
||||||
|
if (val < 0) { neg = 1; uval = (unsigned long)(-val); } else uval = (unsigned long)val;
|
||||||
|
pf_putnum(&st, uval, 10, width, pad, neg); break;
|
||||||
|
}
|
||||||
|
case 'u': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 10, width, pad, 0); break; }
|
||||||
|
case 'x': { unsigned val = va_arg(ap, unsigned); pf_putnum(&st, val, 16, width, pad, 0); break; }
|
||||||
|
case 's': {
|
||||||
|
const char* s = va_arg(ap, const char*); if (!s) s = "(null)";
|
||||||
|
int slen = 0; while (s[slen]) slen++;
|
||||||
|
for (int w = slen; w < width; w++) pf_putc(&st, ' ');
|
||||||
|
for (int j = 0; j < slen; j++) pf_putc(&st, s[j]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c': { char c = (char)va_arg(ap, int); pf_putc(&st, c); break; }
|
||||||
|
case '%': pf_putc(&st, '%'); break;
|
||||||
|
default: pf_putc(&st, '%'); pf_putc(&st, *fmt); break;
|
||||||
|
}
|
||||||
|
if (*fmt) fmt++;
|
||||||
|
}
|
||||||
|
if (size > 0) { if (st.pos < size) st.buf[st.pos] = '\0'; else st.buf[size - 1] = '\0'; }
|
||||||
|
va_end(ap); return st.pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Login state
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
enum LoginMode {
|
||||||
|
MODE_FIRST_BOOT, // Create admin account
|
||||||
|
MODE_LOGIN, // Normal login
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LoginState {
|
||||||
|
Framebuffer fb;
|
||||||
|
int screen_w, screen_h;
|
||||||
|
|
||||||
|
LoginMode mode;
|
||||||
|
int active_field; // 0=username, 1=password, 2=confirm (first-boot only)
|
||||||
|
|
||||||
|
char username[32];
|
||||||
|
int username_len;
|
||||||
|
char display_name[64];
|
||||||
|
int display_name_len;
|
||||||
|
char password[64];
|
||||||
|
int password_len;
|
||||||
|
char confirm[64];
|
||||||
|
int confirm_len;
|
||||||
|
|
||||||
|
char error_msg[128];
|
||||||
|
bool show_error;
|
||||||
|
|
||||||
|
Montauk::MouseState mouse;
|
||||||
|
uint8_t prev_buttons;
|
||||||
|
|
||||||
|
// Power option icons (loaded once at startup)
|
||||||
|
SvgIcon icon_shutdown;
|
||||||
|
SvgIcon icon_reboot;
|
||||||
|
|
||||||
|
// Background wallpaper (loaded from config)
|
||||||
|
uint32_t* bg_wallpaper;
|
||||||
|
int bg_wallpaper_w, bg_wallpaper_h;
|
||||||
|
bool has_wallpaper;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Wallpaper loading
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static bool load_login_wallpaper(LoginState* ls) {
|
||||||
|
// Load system-wide desktop config and read wallpaper.path
|
||||||
|
auto doc = montauk::config::load("desktop");
|
||||||
|
const char* wp = doc.get_string("wallpaper.path", "");
|
||||||
|
if (wp[0] == '\0') return false;
|
||||||
|
|
||||||
|
// Read JPEG file
|
||||||
|
int fd = montauk::open(wp);
|
||||||
|
if (fd < 0) return false;
|
||||||
|
|
||||||
|
uint64_t size = montauk::getsize(fd);
|
||||||
|
if (size == 0 || size > 16 * 1024 * 1024) {
|
||||||
|
montauk::close(fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* filedata = (uint8_t*)montauk::malloc(size);
|
||||||
|
if (!filedata) { montauk::close(fd); return false; }
|
||||||
|
|
||||||
|
int bytes_read = montauk::read(fd, filedata, 0, size);
|
||||||
|
montauk::close(fd);
|
||||||
|
if (bytes_read <= 0) { montauk::mfree(filedata); return false; }
|
||||||
|
|
||||||
|
// Decode JPEG
|
||||||
|
int img_w, img_h, channels;
|
||||||
|
unsigned char* rgb = stbi_load_from_memory(filedata, bytes_read,
|
||||||
|
&img_w, &img_h, &channels, 3);
|
||||||
|
montauk::mfree(filedata);
|
||||||
|
if (!rgb) return false;
|
||||||
|
|
||||||
|
// Scale to cover screen (same algorithm as desktop wallpaper.hpp)
|
||||||
|
int dst_w = ls->screen_w;
|
||||||
|
int dst_h = ls->screen_h;
|
||||||
|
|
||||||
|
uint32_t* scaled = (uint32_t*)montauk::malloc((uint64_t)dst_w * dst_h * 4);
|
||||||
|
if (!scaled) { stbi_image_free(rgb); return false; }
|
||||||
|
|
||||||
|
int src_crop_w, src_crop_h, src_x0, src_y0;
|
||||||
|
if ((int64_t)img_w * dst_h > (int64_t)img_h * dst_w) {
|
||||||
|
src_crop_h = img_h;
|
||||||
|
src_crop_w = (int)((int64_t)img_h * dst_w / dst_h);
|
||||||
|
src_x0 = (img_w - src_crop_w) / 2;
|
||||||
|
src_y0 = 0;
|
||||||
|
} else {
|
||||||
|
src_crop_w = img_w;
|
||||||
|
src_crop_h = (int)((int64_t)img_w * dst_h / dst_w);
|
||||||
|
src_x0 = 0;
|
||||||
|
src_y0 = (img_h - src_crop_h) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < dst_h; y++) {
|
||||||
|
int sy = src_y0 + (int)((int64_t)y * src_crop_h / dst_h);
|
||||||
|
if (sy < 0) sy = 0;
|
||||||
|
if (sy >= img_h) sy = img_h - 1;
|
||||||
|
for (int x = 0; x < dst_w; x++) {
|
||||||
|
int sx = src_x0 + (int)((int64_t)x * src_crop_w / dst_w);
|
||||||
|
if (sx < 0) sx = 0;
|
||||||
|
if (sx >= img_w) sx = img_w - 1;
|
||||||
|
int si = (sy * img_w + sx) * 3;
|
||||||
|
scaled[y * dst_w + x] = 0xFF000000u
|
||||||
|
| ((uint32_t)rgb[si] << 16)
|
||||||
|
| ((uint32_t)rgb[si + 1] << 8)
|
||||||
|
| (uint32_t)rgb[si + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_image_free(rgb);
|
||||||
|
|
||||||
|
ls->bg_wallpaper = scaled;
|
||||||
|
ls->bg_wallpaper_w = dst_w;
|
||||||
|
ls->bg_wallpaper_h = dst_h;
|
||||||
|
ls->has_wallpaper = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Drawing helpers
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static constexpr Color BG_COLOR = Color::from_rgb(0x2B, 0x3E, 0x50);
|
||||||
|
static constexpr Color CARD_BG = Color::from_rgb(0xFF, 0xFF, 0xFF);
|
||||||
|
static constexpr Color FIELD_BG = Color::from_rgb(0xF5, 0xF5, 0xF5);
|
||||||
|
static constexpr Color FIELD_BORDER = Color::from_rgb(0xCC, 0xCC, 0xCC);
|
||||||
|
static constexpr Color FIELD_ACTIVE = Color::from_rgb(0x36, 0x7B, 0xF0);
|
||||||
|
static constexpr Color BTN_COLOR = Color::from_rgb(0x36, 0x7B, 0xF0);
|
||||||
|
static constexpr Color BTN_TEXT = Color::from_rgb(0xFF, 0xFF, 0xFF);
|
||||||
|
static constexpr Color TEXT_COLOR = Color::from_rgb(0x33, 0x33, 0x33);
|
||||||
|
static constexpr Color LABEL_COLOR = Color::from_rgb(0x66, 0x66, 0x66);
|
||||||
|
static constexpr Color ERROR_COLOR = Color::from_rgb(0xE0, 0x40, 0x40);
|
||||||
|
static constexpr Color TITLE_COLOR = Color::from_rgb(0xFF, 0xFF, 0xFF);
|
||||||
|
|
||||||
|
static constexpr int CARD_W = 360;
|
||||||
|
static constexpr int FIELD_H = 36;
|
||||||
|
static constexpr int FIELD_PAD = 10;
|
||||||
|
static constexpr int BTN_H = 40;
|
||||||
|
static constexpr int LABEL_GAP = 4;
|
||||||
|
static constexpr int POWER_ICON_SZ = 32;
|
||||||
|
static constexpr int POWER_GAP = 48; // horizontal spacing between icon centers
|
||||||
|
static constexpr int POWER_TOP_PAD = 24; // padding below error message area
|
||||||
|
|
||||||
|
static void draw_field(Framebuffer& fb, int x, int y, int w, const char* text,
|
||||||
|
bool is_password, bool active) {
|
||||||
|
// Background
|
||||||
|
fb.fill_rect(x, y, w, FIELD_H, FIELD_BG);
|
||||||
|
|
||||||
|
// Border
|
||||||
|
Color border = active ? FIELD_ACTIVE : FIELD_BORDER;
|
||||||
|
// Top
|
||||||
|
for (int i = 0; i < w; i++) fb.put_pixel(x + i, y, border);
|
||||||
|
// Bottom
|
||||||
|
for (int i = 0; i < w; i++) fb.put_pixel(x + i, y + FIELD_H - 1, border);
|
||||||
|
// Left
|
||||||
|
for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x, y + i, border);
|
||||||
|
// Right
|
||||||
|
for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x + w - 1, y + i, border);
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
// Draw 2px border for active field
|
||||||
|
for (int i = 0; i < w; i++) fb.put_pixel(x + i, y + 1, border);
|
||||||
|
for (int i = 0; i < w; i++) fb.put_pixel(x + i, y + FIELD_H - 2, border);
|
||||||
|
for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x + 1, y + i, border);
|
||||||
|
for (int i = 0; i < FIELD_H; i++) fb.put_pixel(x + w - 2, y + i, border);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text (clipped to field width, showing trailing portion)
|
||||||
|
int ty = y + (FIELD_H - system_font_height()) / 2;
|
||||||
|
int max_text_w = w - FIELD_PAD * 2 - 2; // left pad, right pad, cursor
|
||||||
|
if (is_password) {
|
||||||
|
int len = montauk::slen(text);
|
||||||
|
if (len > 64) len = 64;
|
||||||
|
char full[65];
|
||||||
|
for (int i = 0; i < len; i++) full[i] = '*';
|
||||||
|
full[len] = '\0';
|
||||||
|
// Show only trailing portion that fits
|
||||||
|
int vis = len;
|
||||||
|
while (vis > 0 && text_width(full + (len - vis)) > max_text_w)
|
||||||
|
vis--;
|
||||||
|
char masked[65];
|
||||||
|
for (int i = 0; i < vis; i++) masked[i] = '*';
|
||||||
|
masked[vis] = '\0';
|
||||||
|
draw_text(fb, x + FIELD_PAD, ty, masked, TEXT_COLOR);
|
||||||
|
if (active) {
|
||||||
|
int cx = x + FIELD_PAD + text_width(masked);
|
||||||
|
fb.fill_rect(cx, ty, 2, system_font_height(), FIELD_ACTIVE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int len = montauk::slen(text);
|
||||||
|
// Show only trailing portion that fits
|
||||||
|
int offset = 0;
|
||||||
|
while (text_width(text + offset) > max_text_w && offset < len)
|
||||||
|
offset++;
|
||||||
|
draw_text(fb, x + FIELD_PAD, ty, text + offset, TEXT_COLOR);
|
||||||
|
if (active) {
|
||||||
|
int cx = x + FIELD_PAD + text_width(text + offset);
|
||||||
|
fb.fill_rect(cx, ty, 2, system_font_height(), FIELD_ACTIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_button(Framebuffer& fb, int x, int y, int w, int h,
|
||||||
|
const char* label, Color bg) {
|
||||||
|
fb.fill_rect(x, y, w, h, bg);
|
||||||
|
int tw = text_width(label);
|
||||||
|
int tx = x + (w - tw) / 2;
|
||||||
|
int ty = y + (h - system_font_height()) / 2;
|
||||||
|
draw_text(fb, tx, ty, label, BTN_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Screen drawing
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void draw_login_screen(LoginState* ls) {
|
||||||
|
Framebuffer& fb = ls->fb;
|
||||||
|
|
||||||
|
// Background
|
||||||
|
if (ls->has_wallpaper) {
|
||||||
|
fb.blit(0, 0, ls->bg_wallpaper_w, ls->bg_wallpaper_h, ls->bg_wallpaper);
|
||||||
|
} else {
|
||||||
|
fb.clear(BG_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
int card_h;
|
||||||
|
const char* title;
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int power_section_h = POWER_ICON_SZ + sfh + 6 + 4; // icon + label + gap + padding
|
||||||
|
int error_section_h = ls->show_error ? sfh + 8 : 0; // error text + padding
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
card_h = 420 + error_section_h + power_section_h;
|
||||||
|
title = "Create Administrator Account";
|
||||||
|
} else {
|
||||||
|
card_h = 284 + error_section_h + power_section_h;
|
||||||
|
title = "Log In";
|
||||||
|
}
|
||||||
|
|
||||||
|
int card_x = (ls->screen_w - CARD_W) / 2;
|
||||||
|
int card_y = (ls->screen_h - card_h) / 2;
|
||||||
|
|
||||||
|
// Card background
|
||||||
|
fb.fill_rect(card_x, card_y, CARD_W, card_h, CARD_BG);
|
||||||
|
|
||||||
|
int x = card_x + 24;
|
||||||
|
int content_w = CARD_W - 48;
|
||||||
|
int y = card_y + 20;
|
||||||
|
|
||||||
|
// Card title
|
||||||
|
{
|
||||||
|
int tw = text_width(title);
|
||||||
|
draw_text(fb, card_x + (CARD_W - tw) / 2, y, title, TEXT_COLOR);
|
||||||
|
y += sfh + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
// Username field
|
||||||
|
draw_text(fb, x, y, "Username", LABEL_COLOR);
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
draw_field(fb, x, y, content_w, ls->username, false, ls->active_field == 0);
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Display name field
|
||||||
|
draw_text(fb, x, y, "Display Name", LABEL_COLOR);
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
draw_field(fb, x, y, content_w, ls->display_name, false, ls->active_field == 1);
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Password field
|
||||||
|
draw_text(fb, x, y, "Password", LABEL_COLOR);
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
draw_field(fb, x, y, content_w, ls->password, true, ls->active_field == 2);
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Confirm password field
|
||||||
|
draw_text(fb, x, y, "Confirm Password", LABEL_COLOR);
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
draw_field(fb, x, y, content_w, ls->confirm, true, ls->active_field == 3);
|
||||||
|
y += FIELD_H + 16;
|
||||||
|
|
||||||
|
// Create button
|
||||||
|
draw_button(fb, x, y, content_w, BTN_H, "Create Account", BTN_COLOR);
|
||||||
|
y += BTN_H;
|
||||||
|
} else {
|
||||||
|
// Username field
|
||||||
|
draw_text(fb, x, y, "Username", LABEL_COLOR);
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
draw_field(fb, x, y, content_w, ls->username, false, ls->active_field == 0);
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Password field
|
||||||
|
draw_text(fb, x, y, "Password", LABEL_COLOR);
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
draw_field(fb, x, y, content_w, ls->password, true, ls->active_field == 1);
|
||||||
|
y += FIELD_H + 16;
|
||||||
|
|
||||||
|
// Login button
|
||||||
|
draw_button(fb, x, y, content_w, BTN_H, "Log In", BTN_COLOR);
|
||||||
|
y += BTN_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error message (inside card, between button and separator)
|
||||||
|
if (ls->show_error) {
|
||||||
|
y += 8;
|
||||||
|
int tw = text_width(ls->error_msg);
|
||||||
|
draw_text(fb, card_x + (CARD_W - tw) / 2, y, ls->error_msg, ERROR_COLOR);
|
||||||
|
y += sfh;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator line
|
||||||
|
y += 16;
|
||||||
|
fb.fill_rect(x, y, content_w, 1, FIELD_BORDER);
|
||||||
|
y += 16;
|
||||||
|
|
||||||
|
// Power options (inside card, centered)
|
||||||
|
{
|
||||||
|
int total_w = POWER_ICON_SZ + POWER_GAP + POWER_ICON_SZ;
|
||||||
|
int start_x = card_x + (CARD_W - total_w) / 2;
|
||||||
|
|
||||||
|
// Shutdown icon
|
||||||
|
if (ls->icon_shutdown.pixels) {
|
||||||
|
int ix = start_x;
|
||||||
|
fb.blit_alpha(ix, y, ls->icon_shutdown.width, ls->icon_shutdown.height,
|
||||||
|
ls->icon_shutdown.pixels);
|
||||||
|
const char* lbl = "Shut Down";
|
||||||
|
int lw = text_width(lbl);
|
||||||
|
draw_text(fb, ix + (POWER_ICON_SZ - lw) / 2, y + POWER_ICON_SZ + 6,
|
||||||
|
lbl, LABEL_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reboot icon
|
||||||
|
if (ls->icon_reboot.pixels) {
|
||||||
|
int ix = start_x + POWER_ICON_SZ + POWER_GAP;
|
||||||
|
fb.blit_alpha(ix, y, ls->icon_reboot.width, ls->icon_reboot.height,
|
||||||
|
ls->icon_reboot.pixels);
|
||||||
|
const char* lbl = "Restart";
|
||||||
|
int lw = text_width(lbl);
|
||||||
|
draw_text(fb, ix + (POWER_ICON_SZ - lw) / 2, y + POWER_ICON_SZ + 6,
|
||||||
|
lbl, LABEL_COLOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse cursor (shared with desktop)
|
||||||
|
draw_cursor(fb, ls->mouse.x, ls->mouse.y);
|
||||||
|
|
||||||
|
fb.flip();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Input handling
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void append_char(char* buf, int* len, int max, char c) {
|
||||||
|
if (*len < max - 1) {
|
||||||
|
buf[*len] = c;
|
||||||
|
(*len)++;
|
||||||
|
buf[*len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void backspace(char* buf, int* len) {
|
||||||
|
if (*len > 0) {
|
||||||
|
(*len)--;
|
||||||
|
buf[*len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max_fields(LoginState* ls) {
|
||||||
|
return ls->mode == MODE_FIRST_BOOT ? 4 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool try_first_boot_submit(LoginState* ls) {
|
||||||
|
ls->show_error = false;
|
||||||
|
|
||||||
|
if (ls->username_len == 0) {
|
||||||
|
montauk::strcpy(ls->error_msg, "Username is required");
|
||||||
|
ls->show_error = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ls->password_len == 0) {
|
||||||
|
montauk::strcpy(ls->error_msg, "Password is required");
|
||||||
|
ls->show_error = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!montauk::streq(ls->password, ls->confirm)) {
|
||||||
|
montauk::strcpy(ls->error_msg, "Passwords do not match");
|
||||||
|
ls->show_error = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the users directory
|
||||||
|
montauk::fmkdir("0:/users");
|
||||||
|
|
||||||
|
const char* dname = ls->display_name_len > 0 ? ls->display_name : ls->username;
|
||||||
|
if (!montauk::user::create_user(ls->username, dname, ls->password, "admin")) {
|
||||||
|
montauk::strcpy(ls->error_msg, "Failed to create user");
|
||||||
|
ls->show_error = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool try_login(LoginState* ls) {
|
||||||
|
ls->show_error = false;
|
||||||
|
|
||||||
|
if (ls->username_len == 0) {
|
||||||
|
montauk::strcpy(ls->error_msg, "Username is required");
|
||||||
|
ls->show_error = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!montauk::user::authenticate(ls->username, ls->password)) {
|
||||||
|
montauk::strcpy(ls->error_msg, "Invalid username or password");
|
||||||
|
ls->show_error = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write session so any app can query the current user
|
||||||
|
montauk::user::set_session(ls->username);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_key(LoginState* ls, const Montauk::KeyEvent& key) {
|
||||||
|
if (!key.pressed) return;
|
||||||
|
|
||||||
|
// Tab switches fields
|
||||||
|
if (key.scancode == 0x0F) {
|
||||||
|
int mf = max_fields(ls);
|
||||||
|
if (key.shift) {
|
||||||
|
ls->active_field = (ls->active_field + mf - 1) % mf;
|
||||||
|
} else {
|
||||||
|
ls->active_field = (ls->active_field + 1) % mf;
|
||||||
|
}
|
||||||
|
ls->show_error = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter submits
|
||||||
|
if (key.ascii == '\n' || key.ascii == '\r') {
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
if (try_first_boot_submit(ls)) {
|
||||||
|
// Switch to login mode
|
||||||
|
ls->mode = MODE_LOGIN;
|
||||||
|
ls->active_field = 0;
|
||||||
|
// Keep username, clear password fields
|
||||||
|
ls->password[0] = '\0'; ls->password_len = 0;
|
||||||
|
ls->confirm[0] = '\0'; ls->confirm_len = 0;
|
||||||
|
ls->show_error = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (try_login(ls)) {
|
||||||
|
// Spawn desktop with username
|
||||||
|
int pid = montauk::spawn("0:/os/desktop.elf", ls->username);
|
||||||
|
if (pid >= 0) {
|
||||||
|
montauk::waitpid(pid);
|
||||||
|
}
|
||||||
|
// Desktop exited (logout) — clear session and fields
|
||||||
|
montauk::user::clear_session();
|
||||||
|
ls->password[0] = '\0'; ls->password_len = 0;
|
||||||
|
ls->active_field = 1; // Focus password field
|
||||||
|
ls->show_error = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backspace
|
||||||
|
if (key.ascii == '\b' || key.scancode == 0x0E) {
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
switch (ls->active_field) {
|
||||||
|
case 0: backspace(ls->username, &ls->username_len); break;
|
||||||
|
case 1: backspace(ls->display_name, &ls->display_name_len); break;
|
||||||
|
case 2: backspace(ls->password, &ls->password_len); break;
|
||||||
|
case 3: backspace(ls->confirm, &ls->confirm_len); break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (ls->active_field) {
|
||||||
|
case 0: backspace(ls->username, &ls->username_len); break;
|
||||||
|
case 1: backspace(ls->password, &ls->password_len); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printable characters
|
||||||
|
if (key.ascii >= 0x20 && key.ascii < 0x7F) {
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
switch (ls->active_field) {
|
||||||
|
case 0: append_char(ls->username, &ls->username_len, 31, key.ascii); break;
|
||||||
|
case 1: append_char(ls->display_name, &ls->display_name_len, 63, key.ascii); break;
|
||||||
|
case 2: append_char(ls->password, &ls->password_len, 63, key.ascii); break;
|
||||||
|
case 3: append_char(ls->confirm, &ls->confirm_len, 63, key.ascii); break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (ls->active_field) {
|
||||||
|
case 0: append_char(ls->username, &ls->username_len, 31, key.ascii); break;
|
||||||
|
case 1: append_char(ls->password, &ls->password_len, 63, key.ascii); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_mouse(LoginState* ls) {
|
||||||
|
int mx = ls->mouse.x;
|
||||||
|
int my = ls->mouse.y;
|
||||||
|
uint8_t buttons = ls->mouse.buttons;
|
||||||
|
uint8_t prev = ls->prev_buttons;
|
||||||
|
bool left_pressed = (buttons & 0x01) && !(prev & 0x01);
|
||||||
|
|
||||||
|
if (!left_pressed) return;
|
||||||
|
|
||||||
|
int sfh = system_font_height();
|
||||||
|
int power_section_h = POWER_ICON_SZ + sfh + 6 + 8;
|
||||||
|
int error_section_h = ls->show_error ? sfh + 8 : 0;
|
||||||
|
int card_h;
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
card_h = 420 + error_section_h + power_section_h;
|
||||||
|
} else {
|
||||||
|
card_h = 284 + error_section_h + power_section_h;
|
||||||
|
}
|
||||||
|
int card_x = (ls->screen_w - CARD_W) / 2;
|
||||||
|
int card_y = (ls->screen_h - card_h) / 2;
|
||||||
|
int x = card_x + 24;
|
||||||
|
int content_w = CARD_W - 48;
|
||||||
|
int y = card_y + 20;
|
||||||
|
|
||||||
|
// Skip title
|
||||||
|
y += sfh + 16;
|
||||||
|
|
||||||
|
if (ls->mode == MODE_FIRST_BOOT) {
|
||||||
|
// Username label + field
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) {
|
||||||
|
ls->active_field = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Display name label + field
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) {
|
||||||
|
ls->active_field = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Password label + field
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) {
|
||||||
|
ls->active_field = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Confirm label + field
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) {
|
||||||
|
ls->active_field = 3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += FIELD_H + 16;
|
||||||
|
|
||||||
|
// Create button
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + BTN_H) {
|
||||||
|
if (try_first_boot_submit(ls)) {
|
||||||
|
ls->mode = MODE_LOGIN;
|
||||||
|
ls->active_field = 0;
|
||||||
|
ls->password[0] = '\0'; ls->password_len = 0;
|
||||||
|
ls->confirm[0] = '\0'; ls->confirm_len = 0;
|
||||||
|
ls->show_error = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += BTN_H;
|
||||||
|
} else {
|
||||||
|
// Username label + field
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) {
|
||||||
|
ls->active_field = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += FIELD_H + 12;
|
||||||
|
|
||||||
|
// Password label + field
|
||||||
|
y += sfh + LABEL_GAP;
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + FIELD_H) {
|
||||||
|
ls->active_field = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += FIELD_H + 16;
|
||||||
|
|
||||||
|
// Login button
|
||||||
|
if (mx >= x && mx < x + content_w && my >= y && my < y + BTN_H) {
|
||||||
|
if (try_login(ls)) {
|
||||||
|
int pid = montauk::spawn("0:/os/desktop.elf", ls->username);
|
||||||
|
if (pid >= 0) {
|
||||||
|
montauk::waitpid(pid);
|
||||||
|
}
|
||||||
|
montauk::user::clear_session();
|
||||||
|
ls->password[0] = '\0'; ls->password_len = 0;
|
||||||
|
ls->active_field = 1;
|
||||||
|
ls->show_error = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += BTN_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip error section if visible
|
||||||
|
if (ls->show_error) y += error_section_h;
|
||||||
|
|
||||||
|
// Power options (inside card, after separator)
|
||||||
|
y += 16 + 1 + 16; // padding + separator + padding
|
||||||
|
{
|
||||||
|
int total_w = POWER_ICON_SZ + POWER_GAP + POWER_ICON_SZ;
|
||||||
|
int start_x = card_x + (CARD_W - total_w) / 2;
|
||||||
|
int hit_h = POWER_ICON_SZ + sfh + 6;
|
||||||
|
|
||||||
|
// Shutdown
|
||||||
|
if (mx >= start_x && mx < start_x + POWER_ICON_SZ &&
|
||||||
|
my >= y && my < y + hit_h) {
|
||||||
|
montauk::shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reboot
|
||||||
|
int rx = start_x + POWER_ICON_SZ + POWER_GAP;
|
||||||
|
if (mx >= rx && mx < rx + POWER_ICON_SZ &&
|
||||||
|
my >= y && my < y + hit_h) {
|
||||||
|
montauk::reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Entry point
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
extern "C" void _start() {
|
||||||
|
LoginState* ls = (LoginState*)montauk::malloc(sizeof(LoginState));
|
||||||
|
montauk::memset(ls, 0, sizeof(LoginState));
|
||||||
|
|
||||||
|
new (&ls->fb) Framebuffer();
|
||||||
|
ls->screen_w = ls->fb.width();
|
||||||
|
ls->screen_h = ls->fb.height();
|
||||||
|
|
||||||
|
// Load TrueType fonts
|
||||||
|
fonts::init();
|
||||||
|
|
||||||
|
// Set mouse bounds
|
||||||
|
montauk::set_mouse_bounds(ls->screen_w - 1, ls->screen_h - 1);
|
||||||
|
|
||||||
|
// Load power option icons
|
||||||
|
Color icon_color = Color::from_rgb(0x66, 0x66, 0x66);
|
||||||
|
ls->icon_shutdown = svg_load("0:/icons/system-shutdown.svg", POWER_ICON_SZ, POWER_ICON_SZ, icon_color);
|
||||||
|
ls->icon_reboot = svg_load("0:/icons/system-reboot.svg", POWER_ICON_SZ, POWER_ICON_SZ, icon_color);
|
||||||
|
|
||||||
|
// Load wallpaper from system desktop config
|
||||||
|
load_login_wallpaper(ls);
|
||||||
|
|
||||||
|
// Check if users.toml exists (first boot detection)
|
||||||
|
int fh = montauk::open("0:/config/users.toml");
|
||||||
|
if (fh < 0) {
|
||||||
|
ls->mode = MODE_FIRST_BOOT;
|
||||||
|
ls->active_field = 0;
|
||||||
|
// Pre-fill username with "admin"
|
||||||
|
montauk::strcpy(ls->username, "admin");
|
||||||
|
ls->username_len = 5;
|
||||||
|
} else {
|
||||||
|
montauk::close(fh);
|
||||||
|
ls->mode = MODE_LOGIN;
|
||||||
|
ls->active_field = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
for (;;) {
|
||||||
|
// Poll mouse
|
||||||
|
ls->prev_buttons = ls->mouse.buttons;
|
||||||
|
montauk::mouse_state(&ls->mouse);
|
||||||
|
|
||||||
|
// Poll keyboard
|
||||||
|
while (montauk::is_key_available()) {
|
||||||
|
Montauk::KeyEvent key;
|
||||||
|
montauk::getkey(&key);
|
||||||
|
handle_key(ls, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle mouse
|
||||||
|
handle_mouse(ls);
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
draw_login_screen(ls);
|
||||||
|
|
||||||
|
// ~30fps (login doesn't need 60)
|
||||||
|
montauk::sleep_ms(33);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* stb_truetype_impl.cpp
|
||||||
|
* Single compilation unit for stb_truetype in MontaukOS freestanding environment
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <gui/stb_math.h>
|
||||||
|
|
||||||
|
// Override all stb_truetype dependencies before including the implementation
|
||||||
|
|
||||||
|
#define STBTT_ifloor(x) ((int) stb_floor(x))
|
||||||
|
#define STBTT_iceil(x) ((int) stb_ceil(x))
|
||||||
|
#define STBTT_sqrt(x) stb_sqrt(x)
|
||||||
|
#define STBTT_pow(x,y) stb_pow(x,y)
|
||||||
|
#define STBTT_fmod(x,y) stb_fmod(x,y)
|
||||||
|
#define STBTT_cos(x) stb_cos(x)
|
||||||
|
#define STBTT_acos(x) stb_acos(x)
|
||||||
|
#define STBTT_fabs(x) stb_fabs(x)
|
||||||
|
|
||||||
|
#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x))
|
||||||
|
#define STBTT_free(x,u) ((void)(u), montauk::mfree(x))
|
||||||
|
|
||||||
|
#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n)
|
||||||
|
#define STBTT_memset(d,v,n) montauk::memset(d,v,n)
|
||||||
|
|
||||||
|
#define STBTT_strlen(x) montauk::slen(x)
|
||||||
|
|
||||||
|
#define STBTT_assert(x) ((void)(x))
|
||||||
|
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#include <gui/stb_truetype.h>
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <montauk/syscall.h>
|
#include <montauk/syscall.h>
|
||||||
#include <montauk/string.h>
|
#include <montauk/string.h>
|
||||||
#include <montauk/heap.h>
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/config.h>
|
||||||
#include <gui/gui.hpp>
|
#include <gui/gui.hpp>
|
||||||
#include <gui/truetype.hpp>
|
#include <gui/truetype.hpp>
|
||||||
#include <gui/svg.hpp>
|
#include <gui/svg.hpp>
|
||||||
@@ -922,6 +923,22 @@ extern "C" void _start() {
|
|||||||
g.hovered_item = -1;
|
g.hovered_item = -1;
|
||||||
|
|
||||||
// Parse arguments: accept a directory path or a file path
|
// Parse arguments: accept a directory path or a file path
|
||||||
|
// Helper: set dir_path to current user's home via session config
|
||||||
|
auto set_user_home = [&]() {
|
||||||
|
auto doc = montauk::config::load("session");
|
||||||
|
const char* name = doc.get_string("session.username", "");
|
||||||
|
if (name[0]) {
|
||||||
|
int p = 0;
|
||||||
|
const char* pfx = "0:/users/";
|
||||||
|
while (*pfx && p < (int)sizeof(g.dir_path) - 1) g.dir_path[p++] = *pfx++;
|
||||||
|
while (*name && p < (int)sizeof(g.dir_path) - 1) g.dir_path[p++] = *name++;
|
||||||
|
g.dir_path[p] = '\0';
|
||||||
|
} else {
|
||||||
|
memcpy(g.dir_path, "0:/home", 8);
|
||||||
|
}
|
||||||
|
doc.destroy();
|
||||||
|
};
|
||||||
|
|
||||||
char arg_file[128] = {};
|
char arg_file[128] = {};
|
||||||
{
|
{
|
||||||
char args[256];
|
char args[256];
|
||||||
@@ -943,7 +960,7 @@ extern "C" void _start() {
|
|||||||
arg_file[flen] = '\0';
|
arg_file[flen] = '\0';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(g.dir_path, "0:/home", 8);
|
set_user_home();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int len = montauk::slen(args);
|
int len = montauk::slen(args);
|
||||||
@@ -952,7 +969,7 @@ extern "C" void _start() {
|
|||||||
g.dir_path[len] = '\0';
|
g.dir_path[len] = '\0';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
memcpy(g.dir_path, "0:/home", 8);
|
set_user_home();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Makefile for shell (interactive shell) on MontaukOS
|
||||||
|
# Copyright (c) 2025-2026 Daniel Hammer
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
# ---- Toolchain ----
|
||||||
|
|
||||||
|
TOOLCHAIN_PREFIX := $(shell cd ../../.. && pwd)/toolchain/local/bin/x86_64-elf-
|
||||||
|
ifneq ($(wildcard $(TOOLCHAIN_PREFIX)gcc),)
|
||||||
|
CXX := $(TOOLCHAIN_PREFIX)g++
|
||||||
|
else
|
||||||
|
CXX := g++
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---- Paths ----
|
||||||
|
|
||||||
|
PROG_INC := ../../include
|
||||||
|
LINK_LD := ../../link.ld
|
||||||
|
BINDIR := ../../bin
|
||||||
|
OBJDIR := obj
|
||||||
|
|
||||||
|
# ---- C++ compiler flags ----
|
||||||
|
|
||||||
|
CXXFLAGS := \
|
||||||
|
-std=gnu++20 \
|
||||||
|
-g -O2 -pipe \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
-nostdinc \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-PIC \
|
||||||
|
-fno-rtti \
|
||||||
|
-fno-exceptions \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-mno-80387 \
|
||||||
|
-mno-mmx \
|
||||||
|
-mno-sse \
|
||||||
|
-mno-sse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=small \
|
||||||
|
-MMD -MP \
|
||||||
|
-I . \
|
||||||
|
-I $(PROG_INC) \
|
||||||
|
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||||
|
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||||
|
|
||||||
|
# ---- Linker flags ----
|
||||||
|
|
||||||
|
LDFLAGS := \
|
||||||
|
-nostdlib \
|
||||||
|
-static \
|
||||||
|
-Wl,--build-id=none \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-m,elf_x86_64 \
|
||||||
|
-z max-page-size=0x1000 \
|
||||||
|
-T $(LINK_LD)
|
||||||
|
|
||||||
|
# ---- Source files ----
|
||||||
|
|
||||||
|
SRCS := main.cpp vars.cpp builtins.cpp exec.cpp
|
||||||
|
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||||
|
|
||||||
|
# ---- Target ----
|
||||||
|
|
||||||
|
TARGET := $(BINDIR)/os/shell.elf
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
||||||
|
mkdir -p $(BINDIR)/os
|
||||||
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp shell.h Makefile
|
||||||
|
mkdir -p $(OBJDIR)
|
||||||
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
-include $(OBJS:.o=.d)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIR) $(TARGET)
|
||||||
@@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
* builtins.cpp
|
||||||
|
* Shell builtin commands: help, ls, cd, man
|
||||||
|
* Copyright (c) 2025-2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
// ---- help ----
|
||||||
|
|
||||||
|
void cmd_help() {
|
||||||
|
montauk::print("Shell builtins:\n");
|
||||||
|
montauk::print(" help Show this help message\n");
|
||||||
|
montauk::print(" ls [dir] List files in directory\n");
|
||||||
|
montauk::print(" cd [dir] Change working directory\n");
|
||||||
|
montauk::print(" pwd Print working directory\n");
|
||||||
|
montauk::print(" echo [-n] ... Print arguments\n");
|
||||||
|
montauk::print(" set [VAR=val] Show or set shell variables\n");
|
||||||
|
montauk::print(" unset VAR Remove a shell variable\n");
|
||||||
|
montauk::print(" true / false Return success / failure\n");
|
||||||
|
montauk::print(" N: Switch to drive N (e.g. 1:)\n");
|
||||||
|
montauk::print(" exit Exit the shell\n");
|
||||||
|
montauk::print("\n");
|
||||||
|
montauk::print("Syntax:\n");
|
||||||
|
montauk::print(" VAR=value Set a shell variable\n");
|
||||||
|
montauk::print(" $VAR ${VAR} Variable expansion\n");
|
||||||
|
montauk::print(" ~ Expands to home directory\n");
|
||||||
|
montauk::print(" cmd1 ; cmd2 Run commands sequentially\n");
|
||||||
|
montauk::print(" cmd1 && cmd2 Run cmd2 if cmd1 succeeds\n");
|
||||||
|
montauk::print(" cmd1 || cmd2 Run cmd2 if cmd1 fails\n");
|
||||||
|
montauk::print(" # comment Comment (ignored)\n");
|
||||||
|
montauk::print("\n");
|
||||||
|
montauk::print("Built-in variables:\n");
|
||||||
|
montauk::print(" $USER $HOME $PWD $?\n");
|
||||||
|
montauk::print("\n");
|
||||||
|
montauk::print("System commands:\n");
|
||||||
|
montauk::print(" man <topic> View manual pages\n");
|
||||||
|
montauk::print(" cat <file> Display file contents\n");
|
||||||
|
montauk::print(" edit [file] Text editor\n");
|
||||||
|
montauk::print(" whoami Print current username\n");
|
||||||
|
montauk::print(" info Show system information\n");
|
||||||
|
montauk::print(" date Show current date and time\n");
|
||||||
|
montauk::print(" uptime Show uptime\n");
|
||||||
|
montauk::print(" clear Clear the screen\n");
|
||||||
|
montauk::print(" fontscale [n] Set terminal font scale (1-8)\n");
|
||||||
|
montauk::print(" reset Reboot the system\n");
|
||||||
|
montauk::print(" shutdown Shut down the system\n");
|
||||||
|
montauk::print("\n");
|
||||||
|
montauk::print("Network commands:\n");
|
||||||
|
montauk::print(" ping <ip> Send ICMP echo requests\n");
|
||||||
|
montauk::print(" nslookup DNS lookup\n");
|
||||||
|
montauk::print(" ifconfig Show/set network configuration\n");
|
||||||
|
montauk::print(" tcpconnect Connect to a TCP server\n");
|
||||||
|
montauk::print(" irc IRC client\n");
|
||||||
|
montauk::print(" dhcp DHCP client\n");
|
||||||
|
montauk::print(" fetch <url> HTTP client\n");
|
||||||
|
montauk::print(" httpd HTTP server\n");
|
||||||
|
montauk::print("\n");
|
||||||
|
montauk::print("Games:\n");
|
||||||
|
montauk::print(" doom DOOM\n");
|
||||||
|
montauk::print("\n");
|
||||||
|
montauk::print("Any .elf on the ramdisk is executable.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- ls ----
|
||||||
|
|
||||||
|
void cmd_ls(const char* arg) {
|
||||||
|
arg = skip_spaces(arg);
|
||||||
|
|
||||||
|
char dir[128];
|
||||||
|
int drive = current_drive;
|
||||||
|
if (*arg) {
|
||||||
|
if (has_drive_prefix(arg)) {
|
||||||
|
drive = parse_drive_prefix(arg);
|
||||||
|
int plen = drive_prefix_len(arg);
|
||||||
|
scopy(dir, arg + plen + 1, sizeof(dir));
|
||||||
|
} else if (arg[0] == '/') {
|
||||||
|
scopy(dir, arg + 1, sizeof(dir));
|
||||||
|
} else if (cwd[0]) {
|
||||||
|
scopy(dir, cwd, sizeof(dir));
|
||||||
|
scat(dir, "/", sizeof(dir));
|
||||||
|
scat(dir, arg, sizeof(dir));
|
||||||
|
} else {
|
||||||
|
scopy(dir, arg, sizeof(dir));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scopy(dir, cwd, sizeof(dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[128];
|
||||||
|
build_drive_path(drive, dir, path, sizeof(path));
|
||||||
|
|
||||||
|
const char* entries[64];
|
||||||
|
int count = montauk::readdir(path, entries, 64);
|
||||||
|
if (count <= 0) {
|
||||||
|
montauk::print("(empty)\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prefixLen = 0;
|
||||||
|
if (dir[0]) prefixLen = slen(dir) + 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
montauk::print(" ");
|
||||||
|
if (prefixLen > 0 && starts_with(entries[i], dir)) {
|
||||||
|
montauk::print(entries[i] + prefixLen);
|
||||||
|
} else {
|
||||||
|
montauk::print(entries[i]);
|
||||||
|
}
|
||||||
|
montauk::putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- cd ----
|
||||||
|
|
||||||
|
bool switch_drive(int drive) {
|
||||||
|
char path[8];
|
||||||
|
build_drive_path(drive, "", path, sizeof(path));
|
||||||
|
const char* entries[1];
|
||||||
|
if (montauk::readdir(path, entries, 1) < 0) return false;
|
||||||
|
current_drive = drive;
|
||||||
|
cwd[0] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_cd(const char* arg) {
|
||||||
|
arg = skip_spaces(arg);
|
||||||
|
|
||||||
|
// cd with no argument -> go to home directory (or root if no session)
|
||||||
|
if (*arg == '\0') {
|
||||||
|
if (session_home[0] && has_drive_prefix(session_home)) {
|
||||||
|
int drive = parse_drive_prefix(session_home);
|
||||||
|
int plen = drive_prefix_len(session_home);
|
||||||
|
const char* rel = session_home + plen;
|
||||||
|
if (*rel == '/') rel++;
|
||||||
|
current_drive = drive;
|
||||||
|
if (*rel) scopy(cwd, rel, sizeof(cwd));
|
||||||
|
else cwd[0] = '\0';
|
||||||
|
} else {
|
||||||
|
cwd[0] = '\0';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cd / -> go to root
|
||||||
|
if (streq(arg, "/")) {
|
||||||
|
cwd[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip trailing slashes from argument
|
||||||
|
static char argBuf[128];
|
||||||
|
int aLen = 0;
|
||||||
|
while (arg[aLen] && aLen < 127) { argBuf[aLen] = arg[aLen]; aLen++; }
|
||||||
|
argBuf[aLen] = '\0';
|
||||||
|
while (aLen > 0 && argBuf[aLen - 1] == '/') argBuf[--aLen] = '\0';
|
||||||
|
arg = argBuf;
|
||||||
|
|
||||||
|
if (*arg == '\0') {
|
||||||
|
cwd[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cd .. -> go up one level
|
||||||
|
if (streq(arg, "..")) {
|
||||||
|
int len = slen(cwd);
|
||||||
|
int last = -1;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (cwd[i] == '/') last = i;
|
||||||
|
}
|
||||||
|
if (last >= 0) {
|
||||||
|
cwd[last] = '\0';
|
||||||
|
} else {
|
||||||
|
cwd[0] = '\0';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cd /path -> absolute path from root
|
||||||
|
if (arg[0] == '/') {
|
||||||
|
arg++;
|
||||||
|
if (*arg == '\0') { cwd[0] = '\0'; return 0; }
|
||||||
|
char path[128];
|
||||||
|
build_dir_path(arg, path, sizeof(path));
|
||||||
|
const char* entries[1];
|
||||||
|
if (montauk::readdir(path, entries, 1) < 0) {
|
||||||
|
montauk::print("cd: no such directory: ");
|
||||||
|
montauk::print(arg);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
scopy(cwd, arg, sizeof(cwd));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cd N:/ or cd N:/path -> switch drive
|
||||||
|
if (has_drive_prefix(arg)) {
|
||||||
|
int drive = parse_drive_prefix(arg);
|
||||||
|
int plen = drive_prefix_len(arg);
|
||||||
|
const char* rel = arg + plen;
|
||||||
|
if (*rel == '/') rel++;
|
||||||
|
|
||||||
|
char rootPath[8];
|
||||||
|
build_drive_path(drive, "", rootPath, sizeof(rootPath));
|
||||||
|
const char* rootEntries[1];
|
||||||
|
if (montauk::readdir(rootPath, rootEntries, 1) < 0) {
|
||||||
|
montauk::print("cd: no such drive: ");
|
||||||
|
montauk::print(arg);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*rel != '\0') {
|
||||||
|
char path[128];
|
||||||
|
build_drive_path(drive, rel, path, sizeof(path));
|
||||||
|
const char* entries[1];
|
||||||
|
if (montauk::readdir(path, entries, 1) < 0) {
|
||||||
|
montauk::print("cd: no such directory: ");
|
||||||
|
montauk::print(arg);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
current_drive = drive;
|
||||||
|
scopy(cwd, rel, sizeof(cwd));
|
||||||
|
} else {
|
||||||
|
current_drive = drive;
|
||||||
|
cwd[0] = '\0';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relative path
|
||||||
|
char target[128];
|
||||||
|
if (cwd[0]) {
|
||||||
|
scopy(target, cwd, sizeof(target));
|
||||||
|
scat(target, "/", sizeof(target));
|
||||||
|
scat(target, arg, sizeof(target));
|
||||||
|
} else {
|
||||||
|
scopy(target, arg, sizeof(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[128];
|
||||||
|
build_dir_path(target, path, sizeof(path));
|
||||||
|
const char* entries[1];
|
||||||
|
int count = montauk::readdir(path, entries, 1);
|
||||||
|
if (count < 0) {
|
||||||
|
montauk::print("cd: no such directory: ");
|
||||||
|
montauk::print(arg);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
scopy(cwd, target, sizeof(cwd));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- man ----
|
||||||
|
|
||||||
|
int cmd_man(const char* arg) {
|
||||||
|
arg = skip_spaces(arg);
|
||||||
|
if (*arg == '\0') {
|
||||||
|
montauk::print("Usage: man <topic>\n");
|
||||||
|
montauk::print(" man <section> <topic>\n");
|
||||||
|
montauk::print("Try: man intro\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pid = montauk::spawn("0:/os/man.elf", arg);
|
||||||
|
if (pid < 0) {
|
||||||
|
montauk::print("Error: failed to start man viewer\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
montauk::waitpid(pid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* exec.cpp
|
||||||
|
* External command search and execution
|
||||||
|
* Copyright (c) 2025-2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
// ---- Try to spawn an ELF at the given path ----
|
||||||
|
|
||||||
|
static bool try_exec(const char* path, const char* args) {
|
||||||
|
int h = montauk::open(path);
|
||||||
|
if (h < 0) return false;
|
||||||
|
montauk::close(h);
|
||||||
|
|
||||||
|
int pid = montauk::spawn(path, args);
|
||||||
|
if (pid < 0) return false;
|
||||||
|
montauk::waitpid(pid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Resolve arguments: expand relative file paths against CWD ----
|
||||||
|
|
||||||
|
static void resolve_args(const char* args, char* out, int outMax) {
|
||||||
|
if (!args || !args[0]) { out[0] = '\0'; return; }
|
||||||
|
|
||||||
|
int o = 0;
|
||||||
|
const char* p = args;
|
||||||
|
|
||||||
|
while (*p && o < outMax - 1) {
|
||||||
|
while (*p == ' ' && o < outMax - 1) { out[o++] = *p++; }
|
||||||
|
if (!*p) break;
|
||||||
|
|
||||||
|
const char* tokStart = p;
|
||||||
|
int tokLen = 0;
|
||||||
|
while (p[tokLen] && p[tokLen] != ' ') tokLen++;
|
||||||
|
|
||||||
|
bool resolve = (cwd[0] || current_drive != 0) && !has_drive_prefix(tokStart) && tokStart[0] != '-';
|
||||||
|
|
||||||
|
if (resolve) {
|
||||||
|
char candidate[256];
|
||||||
|
int r = 0;
|
||||||
|
if (current_drive >= 10) candidate[r++] = '0' + current_drive / 10;
|
||||||
|
candidate[r++] = '0' + current_drive % 10;
|
||||||
|
candidate[r++] = ':'; candidate[r++] = '/';
|
||||||
|
int j = 0;
|
||||||
|
while (cwd[j] && r < 255) candidate[r++] = cwd[j++];
|
||||||
|
if (cwd[0] && r < 255) candidate[r++] = '/';
|
||||||
|
for (int k = 0; k < tokLen && r < 255; k++) candidate[r++] = tokStart[k];
|
||||||
|
candidate[r] = '\0';
|
||||||
|
|
||||||
|
int h = montauk::open(candidate);
|
||||||
|
if (h >= 0) {
|
||||||
|
montauk::close(h);
|
||||||
|
for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k];
|
||||||
|
} else {
|
||||||
|
bool looksLikeFile = false;
|
||||||
|
for (int k = 0; k < tokLen; k++) {
|
||||||
|
if (tokStart[k] == '.') { looksLikeFile = true; break; }
|
||||||
|
}
|
||||||
|
if (looksLikeFile) {
|
||||||
|
for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k];
|
||||||
|
} else {
|
||||||
|
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
p = tokStart + tokLen;
|
||||||
|
}
|
||||||
|
out[o] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Search and execute an external command ----
|
||||||
|
|
||||||
|
int exec_external(const char* cmd, const char* args) {
|
||||||
|
char path[256];
|
||||||
|
|
||||||
|
char resolvedArgs[512];
|
||||||
|
resolve_args(args, resolvedArgs, sizeof(resolvedArgs));
|
||||||
|
const char* finalArgs = resolvedArgs[0] ? resolvedArgs : nullptr;
|
||||||
|
|
||||||
|
// 1. Try 0:/os/<cmd>.elf
|
||||||
|
scopy(path, "0:/os/", sizeof(path));
|
||||||
|
scat(path, cmd, sizeof(path));
|
||||||
|
scat(path, ".elf", sizeof(path));
|
||||||
|
if (try_exec(path, finalArgs)) return 0;
|
||||||
|
|
||||||
|
// 2. Try 0:/games/<cmd>.elf
|
||||||
|
scopy(path, "0:/games/", sizeof(path));
|
||||||
|
scat(path, cmd, sizeof(path));
|
||||||
|
scat(path, ".elf", sizeof(path));
|
||||||
|
if (try_exec(path, finalArgs)) return 0;
|
||||||
|
|
||||||
|
// 3. Try N:/<cwd>/<cmd>.elf on current drive
|
||||||
|
if (cwd[0]) {
|
||||||
|
build_drive_path(current_drive, "", path, sizeof(path));
|
||||||
|
scat(path, cwd, sizeof(path));
|
||||||
|
scat(path, "/", sizeof(path));
|
||||||
|
scat(path, cmd, sizeof(path));
|
||||||
|
scat(path, ".elf", sizeof(path));
|
||||||
|
if (try_exec(path, finalArgs)) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Try N:/<cmd>.elf on current drive
|
||||||
|
build_drive_path(current_drive, "", path, sizeof(path));
|
||||||
|
scat(path, cmd, sizeof(path));
|
||||||
|
scat(path, ".elf", sizeof(path));
|
||||||
|
if (try_exec(path, finalArgs)) return 0;
|
||||||
|
|
||||||
|
// 5. If on a non-zero drive, also try 0:/<cmd>.elf
|
||||||
|
if (current_drive != 0) {
|
||||||
|
scopy(path, "0:/", sizeof(path));
|
||||||
|
scat(path, cmd, sizeof(path));
|
||||||
|
scat(path, ".elf", sizeof(path));
|
||||||
|
if (try_exec(path, finalArgs)) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
montauk::print(cmd);
|
||||||
|
montauk::print(": command not found\n");
|
||||||
|
return 127;
|
||||||
|
}
|
||||||
+230
-470
@@ -1,75 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
* main.cpp
|
* main.cpp
|
||||||
* Interactive shell for MontaukOS
|
* Entry point, input loop, command dispatch, and chaining
|
||||||
* Copyright (c) 2025 Daniel Hammer
|
* Copyright (c) 2025-2026 Daniel Hammer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <montauk/syscall.h>
|
#include "shell.h"
|
||||||
#include <montauk/string.h>
|
|
||||||
|
|
||||||
using montauk::slen;
|
// ---- Shared state definitions ----
|
||||||
using montauk::streq;
|
|
||||||
using montauk::starts_with;
|
|
||||||
using montauk::skip_spaces;
|
|
||||||
|
|
||||||
static void scopy(char* dst, const char* src, int maxLen) {
|
char cwd[128] = "";
|
||||||
int i = 0;
|
int current_drive = 0;
|
||||||
while (src[i] && i < maxLen - 1) { dst[i] = src[i]; i++; }
|
int last_exit = 0;
|
||||||
dst[i] = '\0';
|
char session_user[32] = "";
|
||||||
}
|
char session_home[64] = "";
|
||||||
|
|
||||||
static void scat(char* dst, const char* src, int maxLen) {
|
// ---- Session info (read once at startup) ----
|
||||||
int dLen = slen(dst);
|
|
||||||
int i = 0;
|
void read_session() {
|
||||||
while (src[i] && dLen + i < maxLen - 1) {
|
auto doc = montauk::config::load("session");
|
||||||
dst[dLen + i] = src[i];
|
const char* name = doc.get_string("session.username", "");
|
||||||
i++;
|
if (name[0]) {
|
||||||
|
scopy(session_user, name, sizeof(session_user));
|
||||||
|
scopy(session_home, "0:/users/", sizeof(session_home));
|
||||||
|
scat(session_home, session_user, sizeof(session_home));
|
||||||
}
|
}
|
||||||
dst[dLen + i] = '\0';
|
doc.destroy();
|
||||||
}
|
|
||||||
|
|
||||||
// Current working directory (relative to N:/).
|
|
||||||
// "" = root, "man" = 0:/man, "man/sub" = 0:/man/sub
|
|
||||||
static char cwd[128] = "";
|
|
||||||
static int current_drive = 0;
|
|
||||||
|
|
||||||
// Build VFS path with explicit drive number
|
|
||||||
static void build_drive_path(int drive, const char* dir, char* out, int outMax) {
|
|
||||||
int i = 0;
|
|
||||||
if (drive >= 10) { out[i++] = '0' + drive / 10; }
|
|
||||||
out[i++] = '0' + drive % 10;
|
|
||||||
out[i++] = ':'; out[i++] = '/';
|
|
||||||
if (dir && dir[0]) {
|
|
||||||
int j = 0;
|
|
||||||
while (dir[j] && i < outMax - 1) out[i++] = dir[j++];
|
|
||||||
}
|
|
||||||
out[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build VFS directory path: "N:/" or "N:/<dir>" using current_drive
|
|
||||||
static void build_dir_path(const char* dir, char* out, int outMax) {
|
|
||||||
build_drive_path(current_drive, dir, out, outMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse drive number from a drive prefix like "0:" or "12:". Returns -1 if invalid.
|
|
||||||
static int parse_drive_prefix(const char* s) {
|
|
||||||
if (s[0] < '0' || s[0] > '9') return -1;
|
|
||||||
int n = s[0] - '0';
|
|
||||||
if (s[1] >= '0' && s[1] <= '9') {
|
|
||||||
n = n * 10 + (s[1] - '0');
|
|
||||||
if (s[2] != ':') return -1;
|
|
||||||
} else if (s[1] == ':') {
|
|
||||||
// single digit drive
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Length of drive prefix ("0:" = 2, "12:" = 3). Assumes valid prefix.
|
|
||||||
static int drive_prefix_len(const char* s) {
|
|
||||||
if (s[1] >= '0' && s[1] <= '9') return 3; // e.g. "12:"
|
|
||||||
return 2; // e.g. "0:"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Command history ----
|
// ---- Command history ----
|
||||||
@@ -77,11 +32,10 @@ static int drive_prefix_len(const char* s) {
|
|||||||
static constexpr int HISTORY_MAX = 32;
|
static constexpr int HISTORY_MAX = 32;
|
||||||
static char history[HISTORY_MAX][256];
|
static char history[HISTORY_MAX][256];
|
||||||
static int history_count = 0;
|
static int history_count = 0;
|
||||||
static int history_next = 0; // ring-buffer write index
|
static int history_next = 0;
|
||||||
|
|
||||||
static void history_add(const char* line) {
|
static void history_add(const char* line) {
|
||||||
if (line[0] == '\0') return;
|
if (line[0] == '\0') return;
|
||||||
// Don't add duplicate of last entry
|
|
||||||
if (history_count > 0) {
|
if (history_count > 0) {
|
||||||
int prev = (history_next + HISTORY_MAX - 1) % HISTORY_MAX;
|
int prev = (history_next + HISTORY_MAX - 1) % HISTORY_MAX;
|
||||||
if (streq(history[prev], line)) return;
|
if (streq(history[prev], line)) return;
|
||||||
@@ -91,7 +45,6 @@ static void history_add(const char* line) {
|
|||||||
if (history_count < HISTORY_MAX) history_count++;
|
if (history_count < HISTORY_MAX) history_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get history entry by index (0 = most recent, 1 = one before that, ...)
|
|
||||||
static const char* history_get(int idx) {
|
static const char* history_get(int idx) {
|
||||||
if (idx < 0 || idx >= history_count) return nullptr;
|
if (idx < 0 || idx >= history_count) return nullptr;
|
||||||
int pos = (history_next + HISTORY_MAX - 1 - idx) % HISTORY_MAX;
|
int pos = (history_next + HISTORY_MAX - 1 - idx) % HISTORY_MAX;
|
||||||
@@ -116,17 +69,14 @@ static void prompt() {
|
|||||||
montauk::print("> ");
|
montauk::print("> ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Erase current input line on screen ----
|
// ---- Line editing ----
|
||||||
|
|
||||||
static void erase_input(int len) {
|
static void erase_input(int len) {
|
||||||
// Move cursor to start of input and overwrite with spaces
|
|
||||||
for (int i = 0; i < len; i++) montauk::putchar('\b');
|
for (int i = 0; i < len; i++) montauk::putchar('\b');
|
||||||
for (int i = 0; i < len; i++) montauk::putchar(' ');
|
for (int i = 0; i < len; i++) montauk::putchar(' ');
|
||||||
for (int i = 0; i < len; i++) montauk::putchar('\b');
|
for (int i = 0; i < len; i++) montauk::putchar('\b');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Replace visible line with new content ----
|
|
||||||
|
|
||||||
static void replace_line(char* line, int* pos, const char* newContent) {
|
static void replace_line(char* line, int* pos, const char* newContent) {
|
||||||
int oldLen = *pos;
|
int oldLen = *pos;
|
||||||
erase_input(oldLen);
|
erase_input(oldLen);
|
||||||
@@ -140,386 +90,43 @@ static void replace_line(char* line, int* pos, const char* newContent) {
|
|||||||
*pos = newLen;
|
*pos = newLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Builtin: help ----
|
// ---- Command dispatch (single command, already expanded) ----
|
||||||
|
|
||||||
static void cmd_help() {
|
static int process_command(const char* line) {
|
||||||
montauk::print("Shell builtins:\n");
|
|
||||||
montauk::print(" help Show this help message\n");
|
|
||||||
montauk::print(" ls [dir] List files in directory\n");
|
|
||||||
montauk::print(" cd [dir] Change working directory\n");
|
|
||||||
montauk::print(" N: Switch to drive N (e.g. 1:)\n");
|
|
||||||
montauk::print(" exit Exit the shell\n");
|
|
||||||
montauk::print("\n");
|
|
||||||
montauk::print("System commands:\n");
|
|
||||||
montauk::print(" man <topic> View manual pages\n");
|
|
||||||
montauk::print(" cat <file> Display file contents\n");
|
|
||||||
montauk::print(" edit [file] Text editor\n");
|
|
||||||
montauk::print(" info Show system information\n");
|
|
||||||
montauk::print(" date Show current date and time\n");
|
|
||||||
montauk::print(" uptime Show uptime\n");
|
|
||||||
montauk::print(" clear Clear the screen\n");
|
|
||||||
montauk::print(" fontscale [n] Set terminal font scale (1-8)\n");
|
|
||||||
montauk::print(" reset Reboot the system\n");
|
|
||||||
montauk::print(" shutdown Shut down the system\n");
|
|
||||||
montauk::print("\n");
|
|
||||||
montauk::print("Network commands:\n");
|
|
||||||
montauk::print(" ping <ip> Send ICMP echo requests\n");
|
|
||||||
montauk::print(" nslookup DNS lookup\n");
|
|
||||||
montauk::print(" ifconfig Show/set network configuration\n");
|
|
||||||
montauk::print(" tcpconnect Connect to a TCP server\n");
|
|
||||||
montauk::print(" irc IRC client\n");
|
|
||||||
montauk::print(" dhcp DHCP client\n");
|
|
||||||
montauk::print(" fetch <url> HTTP client\n");
|
|
||||||
montauk::print(" httpd HTTP server\n");
|
|
||||||
montauk::print("\n");
|
|
||||||
montauk::print("Games:\n");
|
|
||||||
montauk::print(" doom DOOM\n");
|
|
||||||
montauk::print("\n");
|
|
||||||
montauk::print("Any .elf on the ramdisk is executable.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if a string already has a VFS drive prefix (e.g. "0:/" or "12:/")
|
|
||||||
static bool has_drive_prefix(const char* s) {
|
|
||||||
return parse_drive_prefix(s) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Builtin: ls ----
|
|
||||||
|
|
||||||
static void cmd_ls(const char* arg) {
|
|
||||||
arg = skip_spaces(arg);
|
|
||||||
|
|
||||||
// Build the target directory (relative path from root)
|
|
||||||
char dir[128];
|
|
||||||
int drive = current_drive;
|
|
||||||
if (*arg) {
|
|
||||||
if (has_drive_prefix(arg)) {
|
|
||||||
// Absolute VFS path: "N:/something"
|
|
||||||
drive = parse_drive_prefix(arg);
|
|
||||||
int plen = drive_prefix_len(arg);
|
|
||||||
scopy(dir, arg + plen + 1, sizeof(dir)); // skip "N:/"
|
|
||||||
} else if (arg[0] == '/') {
|
|
||||||
// Absolute path from root: "/something"
|
|
||||||
scopy(dir, arg + 1, sizeof(dir));
|
|
||||||
} else if (cwd[0]) {
|
|
||||||
// Relative path with CWD
|
|
||||||
scopy(dir, cwd, sizeof(dir));
|
|
||||||
scat(dir, "/", sizeof(dir));
|
|
||||||
scat(dir, arg, sizeof(dir));
|
|
||||||
} else {
|
|
||||||
// Relative path at root
|
|
||||||
scopy(dir, arg, sizeof(dir));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// ls with no arg -- use cwd
|
|
||||||
scopy(dir, cwd, sizeof(dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
char path[128];
|
|
||||||
build_drive_path(drive, dir, path, sizeof(path));
|
|
||||||
|
|
||||||
const char* entries[64];
|
|
||||||
int count = montauk::readdir(path, entries, 64);
|
|
||||||
if (count <= 0) {
|
|
||||||
montauk::print("(empty)\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefix to strip: "dir/" (if dir is non-empty)
|
|
||||||
int prefixLen = 0;
|
|
||||||
if (dir[0]) prefixLen = slen(dir) + 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
montauk::print(" ");
|
|
||||||
if (prefixLen > 0 && starts_with(entries[i], dir)) {
|
|
||||||
montauk::print(entries[i] + prefixLen);
|
|
||||||
} else {
|
|
||||||
montauk::print(entries[i]);
|
|
||||||
}
|
|
||||||
montauk::putchar('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Builtin: cd ----
|
|
||||||
|
|
||||||
// Switch to a drive. Returns true if valid.
|
|
||||||
static bool switch_drive(int drive) {
|
|
||||||
// Validate drive exists by trying to readdir its root
|
|
||||||
char path[8];
|
|
||||||
build_drive_path(drive, "", path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
if (montauk::readdir(path, entries, 1) < 0) return false;
|
|
||||||
current_drive = drive;
|
|
||||||
cwd[0] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cmd_cd(const char* arg) {
|
|
||||||
arg = skip_spaces(arg);
|
|
||||||
|
|
||||||
// Strip trailing slashes from argument (ls shows dirs as "www/", user may type that)
|
|
||||||
static char argBuf[128];
|
|
||||||
int aLen = 0;
|
|
||||||
while (arg[aLen] && aLen < 127) { argBuf[aLen] = arg[aLen]; aLen++; }
|
|
||||||
argBuf[aLen] = '\0';
|
|
||||||
while (aLen > 0 && argBuf[aLen - 1] == '/') argBuf[--aLen] = '\0';
|
|
||||||
arg = argBuf;
|
|
||||||
|
|
||||||
// cd or cd / -> go to root
|
|
||||||
if (*arg == '\0' || streq(arg, "/")) {
|
|
||||||
cwd[0] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd .. -> go up one level
|
|
||||||
if (streq(arg, "..")) {
|
|
||||||
int len = slen(cwd);
|
|
||||||
int last = -1;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
if (cwd[i] == '/') last = i;
|
|
||||||
}
|
|
||||||
if (last >= 0) {
|
|
||||||
cwd[last] = '\0';
|
|
||||||
} else {
|
|
||||||
cwd[0] = '\0';
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd /path -> absolute path from root
|
|
||||||
if (arg[0] == '/') {
|
|
||||||
arg++;
|
|
||||||
if (*arg == '\0') { cwd[0] = '\0'; return; }
|
|
||||||
char path[128];
|
|
||||||
build_dir_path(arg, path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
if (montauk::readdir(path, entries, 1) < 0) {
|
|
||||||
montauk::print("cd: no such directory: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
scopy(cwd, arg, sizeof(cwd));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cd N:/ or cd N:/path -> switch drive and optionally cd into path
|
|
||||||
if (has_drive_prefix(arg)) {
|
|
||||||
int drive = parse_drive_prefix(arg);
|
|
||||||
int plen = drive_prefix_len(arg);
|
|
||||||
const char* rel = arg + plen; // points at ":/" or ":"
|
|
||||||
if (*rel == '/') rel++; // skip the '/'
|
|
||||||
|
|
||||||
// Validate drive exists
|
|
||||||
char rootPath[8];
|
|
||||||
build_drive_path(drive, "", rootPath, sizeof(rootPath));
|
|
||||||
const char* rootEntries[1];
|
|
||||||
if (montauk::readdir(rootPath, rootEntries, 1) < 0) {
|
|
||||||
montauk::print("cd: no such drive: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's a path after the drive, validate it
|
|
||||||
if (*rel != '\0') {
|
|
||||||
char path[128];
|
|
||||||
build_drive_path(drive, rel, path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
if (montauk::readdir(path, entries, 1) < 0) {
|
|
||||||
montauk::print("cd: no such directory: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
current_drive = drive;
|
|
||||||
scopy(cwd, rel, sizeof(cwd));
|
|
||||||
} else {
|
|
||||||
current_drive = drive;
|
|
||||||
cwd[0] = '\0';
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build target directory path (relative to CWD)
|
|
||||||
char target[128];
|
|
||||||
if (cwd[0]) {
|
|
||||||
scopy(target, cwd, sizeof(target));
|
|
||||||
scat(target, "/", sizeof(target));
|
|
||||||
scat(target, arg, sizeof(target));
|
|
||||||
} else {
|
|
||||||
scopy(target, arg, sizeof(target));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate: try readdir on the target
|
|
||||||
char path[128];
|
|
||||||
build_dir_path(target, path, sizeof(path));
|
|
||||||
const char* entries[1];
|
|
||||||
int count = montauk::readdir(path, entries, 1);
|
|
||||||
if (count < 0) {
|
|
||||||
montauk::print("cd: no such directory: ");
|
|
||||||
montauk::print(arg);
|
|
||||||
montauk::putchar('\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set cwd
|
|
||||||
scopy(cwd, target, sizeof(cwd));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Builtin: man ----
|
|
||||||
|
|
||||||
static void cmd_man(const char* arg) {
|
|
||||||
arg = skip_spaces(arg);
|
|
||||||
if (*arg == '\0') {
|
|
||||||
montauk::print("Usage: man <topic>\n");
|
|
||||||
montauk::print(" man <section> <topic>\n");
|
|
||||||
montauk::print("Try: man intro\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pid = montauk::spawn("0:/os/man.elf", arg);
|
|
||||||
if (pid < 0) {
|
|
||||||
montauk::print("Error: failed to start man viewer\n");
|
|
||||||
} else {
|
|
||||||
montauk::waitpid(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- External command execution ----
|
|
||||||
|
|
||||||
// Try to spawn an ELF at the given path. Returns true on success.
|
|
||||||
static bool try_exec(const char* path, const char* args) {
|
|
||||||
// Check if the file exists before asking the kernel to load it
|
|
||||||
int h = montauk::open(path);
|
|
||||||
if (h < 0) return false;
|
|
||||||
montauk::close(h);
|
|
||||||
|
|
||||||
int pid = montauk::spawn(path, args);
|
|
||||||
if (pid < 0) return false;
|
|
||||||
montauk::waitpid(pid);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve arguments: expand relative file paths against CWD.
|
|
||||||
// Tokens that already have a drive prefix (e.g. "0:/foo") are left as-is.
|
|
||||||
// Everything before the first space-delimited token that looks like a path
|
|
||||||
// option (starts with '-') is also left as-is.
|
|
||||||
static void resolve_args(const char* args, char* out, int outMax) {
|
|
||||||
if (!args || !args[0]) { out[0] = '\0'; return; }
|
|
||||||
|
|
||||||
int o = 0;
|
|
||||||
const char* p = args;
|
|
||||||
|
|
||||||
while (*p && o < outMax - 1) {
|
|
||||||
// Skip spaces, copy them through
|
|
||||||
while (*p == ' ' && o < outMax - 1) { out[o++] = *p++; }
|
|
||||||
if (!*p) break;
|
|
||||||
|
|
||||||
// Extract the token
|
|
||||||
const char* tokStart = p;
|
|
||||||
int tokLen = 0;
|
|
||||||
while (p[tokLen] && p[tokLen] != ' ') tokLen++;
|
|
||||||
|
|
||||||
// Decide whether to resolve this token as a path.
|
|
||||||
// Don't resolve if it already has a drive prefix, or starts with '-'
|
|
||||||
bool resolve = (cwd[0] || current_drive != 0) && !has_drive_prefix(tokStart) && tokStart[0] != '-';
|
|
||||||
|
|
||||||
if (resolve) {
|
|
||||||
// Build candidate resolved path and check if the file exists
|
|
||||||
char candidate[256];
|
|
||||||
int r = 0;
|
|
||||||
if (current_drive >= 10) candidate[r++] = '0' + current_drive / 10;
|
|
||||||
candidate[r++] = '0' + current_drive % 10;
|
|
||||||
candidate[r++] = ':'; candidate[r++] = '/';
|
|
||||||
int j = 0;
|
|
||||||
while (cwd[j] && r < 255) candidate[r++] = cwd[j++];
|
|
||||||
if (cwd[0] && r < 255) candidate[r++] = '/';
|
|
||||||
for (int k = 0; k < tokLen && r < 255; k++) candidate[r++] = tokStart[k];
|
|
||||||
candidate[r] = '\0';
|
|
||||||
|
|
||||||
// Use the resolved path if the file exists. If it doesn't
|
|
||||||
// exist, still use the resolved path when the token looks
|
|
||||||
// like a filename (contains a dot) so that programs creating
|
|
||||||
// new files get the correct drive/directory prefix.
|
|
||||||
int h = montauk::open(candidate);
|
|
||||||
if (h >= 0) {
|
|
||||||
montauk::close(h);
|
|
||||||
for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k];
|
|
||||||
} else {
|
|
||||||
bool looksLikeFile = false;
|
|
||||||
for (int k = 0; k < tokLen; k++) {
|
|
||||||
if (tokStart[k] == '.') { looksLikeFile = true; break; }
|
|
||||||
}
|
|
||||||
if (looksLikeFile) {
|
|
||||||
for (int k = 0; k < r && o < outMax - 1; k++) out[o++] = candidate[k];
|
|
||||||
} else {
|
|
||||||
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int k = 0; k < tokLen && o < outMax - 1; k++) out[o++] = tokStart[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
p = tokStart + tokLen;
|
|
||||||
}
|
|
||||||
out[o] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exec_external(const char* cmd, const char* args) {
|
|
||||||
char path[256];
|
|
||||||
|
|
||||||
// Resolve arguments against CWD so external programs get full VFS paths
|
|
||||||
char resolvedArgs[512];
|
|
||||||
resolve_args(args, resolvedArgs, sizeof(resolvedArgs));
|
|
||||||
const char* finalArgs = resolvedArgs[0] ? resolvedArgs : nullptr;
|
|
||||||
|
|
||||||
// Always search drive 0 for system commands (os/, games/)
|
|
||||||
// 1. Try 0:/os/<cmd>.elf
|
|
||||||
scopy(path, "0:/os/", sizeof(path));
|
|
||||||
scat(path, cmd, sizeof(path));
|
|
||||||
scat(path, ".elf", sizeof(path));
|
|
||||||
if (try_exec(path, finalArgs)) return;
|
|
||||||
|
|
||||||
// 2. Try 0:/games/<cmd>.elf
|
|
||||||
scopy(path, "0:/games/", sizeof(path));
|
|
||||||
scat(path, cmd, sizeof(path));
|
|
||||||
scat(path, ".elf", sizeof(path));
|
|
||||||
if (try_exec(path, finalArgs)) return;
|
|
||||||
|
|
||||||
// 3. Try N:/<cwd>/<cmd>.elf on current drive (if cwd is set)
|
|
||||||
if (cwd[0]) {
|
|
||||||
build_drive_path(current_drive, "", path, sizeof(path));
|
|
||||||
scat(path, cwd, sizeof(path));
|
|
||||||
scat(path, "/", sizeof(path));
|
|
||||||
scat(path, cmd, sizeof(path));
|
|
||||||
scat(path, ".elf", sizeof(path));
|
|
||||||
if (try_exec(path, finalArgs)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Try N:/<cmd>.elf on current drive
|
|
||||||
build_drive_path(current_drive, "", path, sizeof(path));
|
|
||||||
scat(path, cmd, sizeof(path));
|
|
||||||
scat(path, ".elf", sizeof(path));
|
|
||||||
if (try_exec(path, finalArgs)) return;
|
|
||||||
|
|
||||||
// 5. If on a non-zero drive, also try 0:/<cmd>.elf
|
|
||||||
if (current_drive != 0) {
|
|
||||||
scopy(path, "0:/", sizeof(path));
|
|
||||||
scat(path, cmd, sizeof(path));
|
|
||||||
scat(path, ".elf", sizeof(path));
|
|
||||||
if (try_exec(path, finalArgs)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not found
|
|
||||||
montauk::print(cmd);
|
|
||||||
montauk::print(": command not found\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- Command dispatch ----
|
|
||||||
|
|
||||||
static void process_command(const char* line) {
|
|
||||||
line = skip_spaces(line);
|
line = skip_spaces(line);
|
||||||
if (*line == '\0') return;
|
if (*line == '\0') return 0;
|
||||||
|
|
||||||
|
// Variable assignment: NAME=VALUE
|
||||||
|
{
|
||||||
|
int eq = -1;
|
||||||
|
bool valid = (line[0] >= 'A' && line[0] <= 'Z') ||
|
||||||
|
(line[0] >= 'a' && line[0] <= 'z') || line[0] == '_';
|
||||||
|
if (valid) {
|
||||||
|
for (int i = 1; line[i]; i++) {
|
||||||
|
if (line[i] == '=') { eq = i; break; }
|
||||||
|
if (!is_var_char(line[i])) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eq > 0) {
|
||||||
|
char name[32];
|
||||||
|
int nlen = eq < 31 ? eq : 31;
|
||||||
|
for (int i = 0; i < nlen; i++) name[i] = line[i];
|
||||||
|
name[nlen] = '\0';
|
||||||
|
const char* val = line + eq + 1;
|
||||||
|
int vlen = slen(val);
|
||||||
|
char vbuf[128];
|
||||||
|
if (vlen >= 2 && ((val[0] == '"' && val[vlen-1] == '"') ||
|
||||||
|
(val[0] == '\'' && val[vlen-1] == '\''))) {
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 1; i < vlen - 1 && j < 127; i++) vbuf[j++] = val[i];
|
||||||
|
vbuf[j] = '\0';
|
||||||
|
var_set(name, vbuf);
|
||||||
|
} else {
|
||||||
|
var_set(name, val);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse command name and arguments
|
// Parse command name and arguments
|
||||||
char cmd[128];
|
char cmd[128];
|
||||||
@@ -543,26 +150,174 @@ static void process_command(const char* line) {
|
|||||||
montauk::print("No such drive: ");
|
montauk::print("No such drive: ");
|
||||||
montauk::print(cmd);
|
montauk::print(cmd);
|
||||||
montauk::print("/\n");
|
montauk::print("/\n");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builtins
|
// Builtins
|
||||||
if (streq(cmd, "help")) {
|
if (streq(cmd, "help")) { cmd_help(); return 0; }
|
||||||
cmd_help();
|
if (streq(cmd, "ls")) { cmd_ls(args ? args : ""); return 0; }
|
||||||
} else if (streq(cmd, "ls")) {
|
if (streq(cmd, "cd")) { return cmd_cd(args ? args : ""); }
|
||||||
cmd_ls(args ? args : "");
|
if (streq(cmd, "man")) { return cmd_man(args ? args : ""); }
|
||||||
} else if (streq(cmd, "cd")) {
|
if (streq(cmd, "true")) { return 0; }
|
||||||
cmd_cd(args ? args : "");
|
if (streq(cmd, "false")) { return 1; }
|
||||||
} else if (streq(cmd, "man")) {
|
|
||||||
cmd_man(args ? args : "");
|
if (streq(cmd, "pwd")) {
|
||||||
} else if (streq(cmd, "exit")) {
|
char path[128];
|
||||||
montauk::print("Goodbye.\n");
|
build_dir_path(cwd, path, sizeof(path));
|
||||||
montauk::exit(0);
|
montauk::print(path);
|
||||||
} else {
|
montauk::putchar('\n');
|
||||||
// External command -- pass full argument string
|
return 0;
|
||||||
exec_external(cmd, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (streq(cmd, "echo")) {
|
||||||
|
if (!args) {
|
||||||
|
montauk::putchar('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool no_newline = false;
|
||||||
|
if (starts_with(args, "-n ")) {
|
||||||
|
no_newline = true;
|
||||||
|
args = skip_spaces(args + 3);
|
||||||
|
} else if (streq(args, "-n")) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
montauk::print(args);
|
||||||
|
if (!no_newline) montauk::putchar('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(cmd, "set")) {
|
||||||
|
if (!args) {
|
||||||
|
// List all variables
|
||||||
|
if (session_user[0]) {
|
||||||
|
montauk::print("USER=");
|
||||||
|
montauk::print(session_user);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
}
|
||||||
|
if (session_home[0]) {
|
||||||
|
montauk::print("HOME=");
|
||||||
|
montauk::print(session_home);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
}
|
||||||
|
char path[128];
|
||||||
|
build_dir_path(cwd, path, sizeof(path));
|
||||||
|
montauk::print("PWD=");
|
||||||
|
montauk::print(path);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
int vc = var_user_count();
|
||||||
|
for (int j = 0; j < vc; j++) {
|
||||||
|
montauk::print(var_user_name(j));
|
||||||
|
montauk::putchar('=');
|
||||||
|
montauk::print(var_user_value(j));
|
||||||
|
montauk::putchar('\n');
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// set VAR=value
|
||||||
|
int eq = -1;
|
||||||
|
for (int j = 0; args[j]; j++) {
|
||||||
|
if (args[j] == '=') { eq = j; break; }
|
||||||
|
}
|
||||||
|
if (eq > 0) {
|
||||||
|
char name[32];
|
||||||
|
int nlen = eq < 31 ? eq : 31;
|
||||||
|
for (int j = 0; j < nlen; j++) name[j] = args[j];
|
||||||
|
name[nlen] = '\0';
|
||||||
|
var_set(name, args + eq + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// set VAR (show value)
|
||||||
|
const char* val = var_get(args);
|
||||||
|
if (val) {
|
||||||
|
montauk::print(args);
|
||||||
|
montauk::putchar('=');
|
||||||
|
montauk::print(val);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
} else {
|
||||||
|
montauk::print(args);
|
||||||
|
montauk::print(": not set\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(cmd, "unset")) {
|
||||||
|
if (!args) {
|
||||||
|
montauk::print("Usage: unset <variable>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
var_unset(args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(cmd, "exit")) {
|
||||||
|
montauk::print("Goodbye.\n");
|
||||||
|
montauk::exit(last_exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// External command
|
||||||
|
return exec_external(cmd, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Command line execution with chaining ----
|
||||||
|
|
||||||
|
static void execute_line(const char* raw) {
|
||||||
|
// Step 1: expand tilde
|
||||||
|
char texp[512];
|
||||||
|
expand_tilde(raw, texp, sizeof(texp));
|
||||||
|
|
||||||
|
// Step 2: expand variables
|
||||||
|
char expanded[512];
|
||||||
|
expand_vars(texp, expanded, sizeof(expanded));
|
||||||
|
|
||||||
|
// Step 3: strip comments
|
||||||
|
strip_comment(expanded);
|
||||||
|
|
||||||
|
// Step 4: split on ;, &&, || and execute with chaining logic
|
||||||
|
const char* p = expanded;
|
||||||
|
int prev = 0;
|
||||||
|
enum { OP_NONE, OP_SEMI, OP_AND, OP_OR } pending = OP_NONE;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
p = skip_spaces(p);
|
||||||
|
if (!*p) break;
|
||||||
|
|
||||||
|
// Extract next command segment
|
||||||
|
char seg[256];
|
||||||
|
int si = 0;
|
||||||
|
int op = OP_NONE;
|
||||||
|
bool in_sq = false, in_dq = false;
|
||||||
|
|
||||||
|
while (*p && si < 255) {
|
||||||
|
if (*p == '\'' && !in_dq) { in_sq = !in_sq; seg[si++] = *p++; continue; }
|
||||||
|
if (*p == '"' && !in_sq) { in_dq = !in_dq; seg[si++] = *p++; continue; }
|
||||||
|
if (!in_sq && !in_dq) {
|
||||||
|
if (*p == ';') { op = OP_SEMI; p++; break; }
|
||||||
|
if (*p == '&' && p[1] == '&') { op = OP_AND; p += 2; break; }
|
||||||
|
if (*p == '|' && p[1] == '|') { op = OP_OR; p += 2; break; }
|
||||||
|
}
|
||||||
|
seg[si++] = *p++;
|
||||||
|
}
|
||||||
|
seg[si] = '\0';
|
||||||
|
|
||||||
|
// Trim trailing spaces
|
||||||
|
while (si > 0 && seg[si - 1] == ' ') seg[--si] = '\0';
|
||||||
|
|
||||||
|
// Decide whether to run based on pending operator
|
||||||
|
bool run = true;
|
||||||
|
if (pending == OP_AND && prev != 0) run = false;
|
||||||
|
if (pending == OP_OR && prev == 0) run = false;
|
||||||
|
|
||||||
|
if (run && seg[0]) {
|
||||||
|
prev = process_command(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
pending = (decltype(pending))op;
|
||||||
|
if (op == OP_NONE) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_exit = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Arrow key scancodes ----
|
// ---- Arrow key scancodes ----
|
||||||
@@ -575,17 +330,26 @@ static constexpr uint8_t SC_RIGHT = 0x4D;
|
|||||||
// ---- Entry point ----
|
// ---- Entry point ----
|
||||||
|
|
||||||
extern "C" void _start() {
|
extern "C" void _start() {
|
||||||
|
read_session();
|
||||||
|
|
||||||
montauk::print("\n");
|
montauk::print("\n");
|
||||||
montauk::print(" MontaukOS\n");
|
montauk::print(" MontaukOS\n");
|
||||||
montauk::print(" Copyright (c) 2025-2026 Daniel Hammer\n");
|
montauk::print(" Copyright (c) 2025-2026 Daniel Hammer\n");
|
||||||
montauk::print("\n");
|
montauk::print("\n");
|
||||||
|
|
||||||
|
if (session_user[0]) {
|
||||||
|
montauk::print(" Logged in as ");
|
||||||
|
montauk::print(session_user);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
montauk::print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
montauk::print(" Type 'help' for available commands.\n");
|
montauk::print(" Type 'help' for available commands.\n");
|
||||||
montauk::print("\n");
|
montauk::print("\n");
|
||||||
|
|
||||||
char line[256];
|
char line[256];
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int hist_nav = -1; // -1 = not navigating history
|
int hist_nav = -1;
|
||||||
|
|
||||||
prompt();
|
prompt();
|
||||||
|
|
||||||
@@ -603,7 +367,6 @@ extern "C" void _start() {
|
|||||||
// Arrow keys: ascii == 0, check scancode
|
// Arrow keys: ascii == 0, check scancode
|
||||||
if (ev.ascii == 0) {
|
if (ev.ascii == 0) {
|
||||||
if (ev.scancode == SC_UP) {
|
if (ev.scancode == SC_UP) {
|
||||||
// Navigate to older history entry
|
|
||||||
int next = hist_nav + 1;
|
int next = hist_nav + 1;
|
||||||
const char* entry = history_get(next);
|
const char* entry = history_get(next);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
@@ -611,7 +374,6 @@ extern "C" void _start() {
|
|||||||
replace_line(line, &pos, entry);
|
replace_line(line, &pos, entry);
|
||||||
}
|
}
|
||||||
} else if (ev.scancode == SC_DOWN) {
|
} else if (ev.scancode == SC_DOWN) {
|
||||||
// Navigate to newer history entry
|
|
||||||
if (hist_nav > 0) {
|
if (hist_nav > 0) {
|
||||||
hist_nav--;
|
hist_nav--;
|
||||||
const char* entry = history_get(hist_nav);
|
const char* entry = history_get(hist_nav);
|
||||||
@@ -619,14 +381,12 @@ extern "C" void _start() {
|
|||||||
replace_line(line, &pos, entry);
|
replace_line(line, &pos, entry);
|
||||||
}
|
}
|
||||||
} else if (hist_nav == 0) {
|
} else if (hist_nav == 0) {
|
||||||
// Back to empty line
|
|
||||||
hist_nav = -1;
|
hist_nav = -1;
|
||||||
erase_input(pos);
|
erase_input(pos);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
line[0] = '\0';
|
line[0] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Left/Right arrows: ignore for now (no cursor movement within line)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +394,7 @@ extern "C" void _start() {
|
|||||||
montauk::putchar('\n');
|
montauk::putchar('\n');
|
||||||
line[pos] = '\0';
|
line[pos] = '\0';
|
||||||
history_add(line);
|
history_add(line);
|
||||||
process_command(line);
|
execute_line(line);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
hist_nav = -1;
|
hist_nav = -1;
|
||||||
prompt();
|
prompt();
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* shell.h
|
||||||
|
* Shared declarations for the MontaukOS interactive shell
|
||||||
|
* Copyright (c) 2025-2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/config.h>
|
||||||
|
|
||||||
|
using montauk::slen;
|
||||||
|
using montauk::streq;
|
||||||
|
using montauk::starts_with;
|
||||||
|
using montauk::skip_spaces;
|
||||||
|
|
||||||
|
// ---- Inline string helpers ----
|
||||||
|
|
||||||
|
inline void scopy(char* dst, const char* src, int maxLen) {
|
||||||
|
int i = 0;
|
||||||
|
while (src[i] && i < maxLen - 1) { dst[i] = src[i]; i++; }
|
||||||
|
dst[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void scat(char* dst, const char* src, int maxLen) {
|
||||||
|
int dLen = slen(dst);
|
||||||
|
int i = 0;
|
||||||
|
while (src[i] && dLen + i < maxLen - 1) {
|
||||||
|
dst[dLen + i] = src[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
dst[dLen + i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void int_to_str(int n, char* buf, int sz) {
|
||||||
|
if (n == 0) { buf[0] = '0'; buf[1] = '\0'; return; }
|
||||||
|
bool neg = false;
|
||||||
|
unsigned int u;
|
||||||
|
if (n < 0) { neg = true; u = (unsigned)(-n); } else { u = (unsigned)n; }
|
||||||
|
char tmp[12];
|
||||||
|
int i = 0;
|
||||||
|
while (u > 0) { tmp[i++] = '0' + u % 10; u /= 10; }
|
||||||
|
int o = 0;
|
||||||
|
if (neg && o < sz - 1) buf[o++] = '-';
|
||||||
|
while (i > 0 && o < sz - 1) buf[o++] = tmp[--i];
|
||||||
|
buf[o] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Shared state (defined in main.cpp) ----
|
||||||
|
|
||||||
|
extern char cwd[128];
|
||||||
|
extern int current_drive;
|
||||||
|
extern int last_exit;
|
||||||
|
extern char session_user[32];
|
||||||
|
extern char session_home[64];
|
||||||
|
|
||||||
|
// ---- Inline path helpers ----
|
||||||
|
|
||||||
|
inline void build_drive_path(int drive, const char* dir, char* out, int outMax) {
|
||||||
|
int i = 0;
|
||||||
|
if (drive >= 10) { out[i++] = '0' + drive / 10; }
|
||||||
|
out[i++] = '0' + drive % 10;
|
||||||
|
out[i++] = ':'; out[i++] = '/';
|
||||||
|
if (dir && dir[0]) {
|
||||||
|
int j = 0;
|
||||||
|
while (dir[j] && i < outMax - 1) out[i++] = dir[j++];
|
||||||
|
}
|
||||||
|
out[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void build_dir_path(const char* dir, char* out, int outMax) {
|
||||||
|
build_drive_path(current_drive, dir, out, outMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int parse_drive_prefix(const char* s) {
|
||||||
|
if (s[0] < '0' || s[0] > '9') return -1;
|
||||||
|
int n = s[0] - '0';
|
||||||
|
if (s[1] >= '0' && s[1] <= '9') {
|
||||||
|
n = n * 10 + (s[1] - '0');
|
||||||
|
if (s[2] != ':') return -1;
|
||||||
|
} else if (s[1] == ':') {
|
||||||
|
// single digit drive
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int drive_prefix_len(const char* s) {
|
||||||
|
if (s[1] >= '0' && s[1] <= '9') return 3;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool has_drive_prefix(const char* s) {
|
||||||
|
return parse_drive_prefix(s) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Variables (vars.cpp) ----
|
||||||
|
|
||||||
|
void var_set(const char* name, const char* value);
|
||||||
|
void var_unset(const char* name);
|
||||||
|
const char* var_get(const char* name);
|
||||||
|
bool is_var_char(char c);
|
||||||
|
void expand_vars(const char* in, char* out, int outMax);
|
||||||
|
void expand_tilde(const char* in, char* out, int outMax);
|
||||||
|
void strip_comment(char* line);
|
||||||
|
int var_user_count();
|
||||||
|
const char* var_user_name(int idx);
|
||||||
|
const char* var_user_value(int idx);
|
||||||
|
|
||||||
|
// ---- Session (main.cpp) ----
|
||||||
|
|
||||||
|
void read_session();
|
||||||
|
|
||||||
|
// ---- Builtins (builtins.cpp) ----
|
||||||
|
|
||||||
|
void cmd_help();
|
||||||
|
void cmd_ls(const char* arg);
|
||||||
|
int cmd_cd(const char* arg);
|
||||||
|
int cmd_man(const char* arg);
|
||||||
|
bool switch_drive(int drive);
|
||||||
|
|
||||||
|
// ---- External execution (exec.cpp) ----
|
||||||
|
|
||||||
|
int exec_external(const char* cmd, const char* args);
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* vars.cpp
|
||||||
|
* Shell variable storage, expansion, and tilde/comment processing
|
||||||
|
* Copyright (c) 2025-2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
// ---- Storage ----
|
||||||
|
|
||||||
|
static constexpr int MAX_VARS = 32;
|
||||||
|
|
||||||
|
struct ShellVar {
|
||||||
|
char name[32];
|
||||||
|
char value[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
static ShellVar vars[MAX_VARS];
|
||||||
|
static int var_count = 0;
|
||||||
|
|
||||||
|
// ---- Core operations ----
|
||||||
|
|
||||||
|
void var_set(const char* name, const char* value) {
|
||||||
|
for (int i = 0; i < var_count; i++) {
|
||||||
|
if (streq(vars[i].name, name)) {
|
||||||
|
scopy(vars[i].value, value, sizeof(vars[i].value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (var_count < MAX_VARS) {
|
||||||
|
scopy(vars[var_count].name, name, sizeof(vars[var_count].name));
|
||||||
|
scopy(vars[var_count].value, value, sizeof(vars[var_count].value));
|
||||||
|
var_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void var_unset(const char* name) {
|
||||||
|
for (int i = 0; i < var_count; i++) {
|
||||||
|
if (streq(vars[i].name, name)) {
|
||||||
|
for (int j = i; j < var_count - 1; j++) vars[j] = vars[j + 1];
|
||||||
|
var_count--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get variable value. Built-in dynamic vars ($?, $PWD) are synthesized on
|
||||||
|
// demand. Returns nullptr if not found. The returned pointer for dynamic
|
||||||
|
// vars points to a static buffer overwritten on the next call.
|
||||||
|
const char* var_get(const char* name) {
|
||||||
|
// User-defined vars take priority
|
||||||
|
for (int i = 0; i < var_count; i++) {
|
||||||
|
if (streq(vars[i].name, name)) return vars[i].value;
|
||||||
|
}
|
||||||
|
// Synthesize built-in vars
|
||||||
|
static char synth[128];
|
||||||
|
if (streq(name, "?")) {
|
||||||
|
int_to_str(last_exit, synth, sizeof(synth));
|
||||||
|
return synth;
|
||||||
|
}
|
||||||
|
if (streq(name, "USER")) return session_user[0] ? session_user : nullptr;
|
||||||
|
if (streq(name, "HOME")) return session_home[0] ? session_home : nullptr;
|
||||||
|
if (streq(name, "PWD")) {
|
||||||
|
build_dir_path(cwd, synth, sizeof(synth));
|
||||||
|
return synth;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Helpers used by the set builtin (main.cpp) ----
|
||||||
|
|
||||||
|
// The set builtin needs to iterate user-defined vars and show built-in
|
||||||
|
// vars. We expose a small iteration API rather than the raw array.
|
||||||
|
|
||||||
|
int var_user_count() { return var_count; }
|
||||||
|
|
||||||
|
const char* var_user_name(int idx) {
|
||||||
|
return (idx >= 0 && idx < var_count) ? vars[idx].name : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* var_user_value(int idx) {
|
||||||
|
return (idx >= 0 && idx < var_count) ? vars[idx].value : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Character classification ----
|
||||||
|
|
||||||
|
bool is_var_char(char c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||||
|
(c >= '0' && c <= '9') || c == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Variable expansion ----
|
||||||
|
|
||||||
|
void expand_vars(const char* in, char* out, int outMax) {
|
||||||
|
int o = 0;
|
||||||
|
while (*in && o < outMax - 1) {
|
||||||
|
if (*in == '\\' && in[1] == '$') {
|
||||||
|
if (o < outMax - 1) out[o++] = '$';
|
||||||
|
in += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*in == '$') {
|
||||||
|
in++;
|
||||||
|
char name[32];
|
||||||
|
int n = 0;
|
||||||
|
if (*in == '{') {
|
||||||
|
in++;
|
||||||
|
while (*in && *in != '}' && n < 31) name[n++] = *in++;
|
||||||
|
if (*in == '}') in++;
|
||||||
|
} else if (*in == '?') {
|
||||||
|
name[n++] = '?';
|
||||||
|
in++;
|
||||||
|
} else {
|
||||||
|
while (is_var_char(*in) && n < 31) name[n++] = *in++;
|
||||||
|
}
|
||||||
|
name[n] = '\0';
|
||||||
|
if (n > 0) {
|
||||||
|
const char* val = var_get(name);
|
||||||
|
if (val) {
|
||||||
|
while (*val && o < outMax - 1) out[o++] = *val++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (o < outMax - 1) out[o++] = '$';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out[o++] = *in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out[o] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Tilde expansion ----
|
||||||
|
|
||||||
|
void expand_tilde(const char* in, char* out, int outMax) {
|
||||||
|
int o = 0;
|
||||||
|
bool at_start = true;
|
||||||
|
while (*in && o < outMax - 1) {
|
||||||
|
if (at_start && *in == '~' && session_home[0]) {
|
||||||
|
if (in[1] == '\0' || in[1] == '/' || in[1] == ' ') {
|
||||||
|
const char* h = session_home;
|
||||||
|
while (*h && o < outMax - 1) out[o++] = *h++;
|
||||||
|
in++;
|
||||||
|
} else {
|
||||||
|
out[o++] = *in++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
at_start = (*in == ' ');
|
||||||
|
out[o++] = *in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out[o] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Comment stripping ----
|
||||||
|
|
||||||
|
void strip_comment(char* line) {
|
||||||
|
bool in_sq = false, in_dq = false;
|
||||||
|
for (int i = 0; line[i]; i++) {
|
||||||
|
if (line[i] == '\'' && !in_dq) in_sq = !in_sq;
|
||||||
|
else if (line[i] == '"' && !in_sq) in_dq = !in_dq;
|
||||||
|
else if (line[i] == '#' && !in_sq && !in_dq) {
|
||||||
|
line[i] = '\0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* main.cpp
|
||||||
|
* whoami - Print the current username
|
||||||
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/config.h>
|
||||||
|
|
||||||
|
extern "C" void _start() {
|
||||||
|
auto doc = montauk::config::load("session");
|
||||||
|
const char* name = doc.get_string("session.username", "");
|
||||||
|
if (name[0]) {
|
||||||
|
montauk::print(name);
|
||||||
|
montauk::putchar('\n');
|
||||||
|
} else {
|
||||||
|
montauk::print("unknown\n");
|
||||||
|
}
|
||||||
|
doc.destroy();
|
||||||
|
montauk::exit(0);
|
||||||
|
}
|
||||||
@@ -90,12 +90,14 @@ static void px_fill(uint32_t* px, int bw, int x, int y, int w, int h, Color c) {
|
|||||||
int x0 = x < 0 ? 0 : x, y0 = y < 0 ? 0 : y;
|
int x0 = x < 0 ? 0 : x, y0 = y < 0 ? 0 : y;
|
||||||
int x1 = x + w, y1 = y + h;
|
int x1 = x + w, y1 = y + h;
|
||||||
if (x1 > bw) x1 = bw;
|
if (x1 > bw) x1 = bw;
|
||||||
|
if (y1 > g_win_h) y1 = g_win_h;
|
||||||
for (int row = y0; row < y1; row++)
|
for (int row = y0; row < y1; row++)
|
||||||
for (int col = x0; col < x1; col++)
|
for (int col = x0; col < x1; col++)
|
||||||
px[row * bw + col] = v;
|
px[row * bw + col] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void px_hline(uint32_t* px, int bw, int x, int y, int len, Color c) {
|
static void px_hline(uint32_t* px, int bw, int x, int y, int len, Color c) {
|
||||||
|
if (y < 0 || y >= g_win_h) return;
|
||||||
uint32_t v = c.to_pixel();
|
uint32_t v = c.to_pixel();
|
||||||
int x1 = x + len;
|
int x1 = x + len;
|
||||||
if (x < 0) x = 0;
|
if (x < 0) x = 0;
|
||||||
@@ -105,8 +107,12 @@ static void px_hline(uint32_t* px, int bw, int x, int y, int len, Color c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void px_vline(uint32_t* px, int bw, int x, int y, int len, Color c) {
|
static void px_vline(uint32_t* px, int bw, int x, int y, int len, Color c) {
|
||||||
|
if (x < 0 || x >= bw) return;
|
||||||
uint32_t v = c.to_pixel();
|
uint32_t v = c.to_pixel();
|
||||||
for (int row = y; row < y + len; row++)
|
int y1 = y + len;
|
||||||
|
if (y < 0) y = 0;
|
||||||
|
if (y1 > g_win_h) y1 = g_win_h;
|
||||||
|
for (int row = y; row < y1; row++)
|
||||||
px[row * bw + x] = v;
|
px[row * bw + x] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,10 @@ ICONS=(
|
|||||||
"actions/16/media-rewind.svg"
|
"actions/16/media-rewind.svg"
|
||||||
"apps/scalable/multimedia-video-player.svg"
|
"apps/scalable/multimedia-video-player.svg"
|
||||||
"apps/scalable/bluetooth.svg"
|
"apps/scalable/bluetooth.svg"
|
||||||
|
"panel/volume-level-high.svg"
|
||||||
|
"status/symbolic/audio-volume-high-symbolic.svg"
|
||||||
|
"apps/scalable/gnome-logout.svg"
|
||||||
|
"apps/scalable/lock.svg"
|
||||||
)
|
)
|
||||||
|
|
||||||
copied=0
|
copied=0
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# Makefile for standalone MontaukOS app (template)
|
||||||
|
# Usage:
|
||||||
|
# make Build the app
|
||||||
|
# make clean Remove build artifacts
|
||||||
|
# make install Copy ELF to MontaukOS ramdisk bin directory
|
||||||
|
#
|
||||||
|
# Copy this entire directory, rename it, and edit APP_NAME/SRCS below.
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
# ---- App configuration ----
|
||||||
|
# Change these for your app:
|
||||||
|
|
||||||
|
APP_NAME := myapp
|
||||||
|
SRCS := src/main.cpp src/stb_truetype_impl.cpp src/cxxrt.cpp
|
||||||
|
|
||||||
|
# Optional features — set to 1 to enable:
|
||||||
|
# USE_TLS=1 HTTPS/TLS support (libtls + libbearssl)
|
||||||
|
# USE_JPEG=1 JPEG image decoding (libjpeg / stb_image)
|
||||||
|
USE_TLS ?= 0
|
||||||
|
USE_JPEG ?= 0
|
||||||
|
|
||||||
|
# ---- Toolchain ----
|
||||||
|
# Looks for the cross-compiler via MONTAUKOS, then falls back to system g++.
|
||||||
|
|
||||||
|
MONTAUKOS ?= $(HOME)/dev/MontaukOS
|
||||||
|
TOOLCHAIN := $(MONTAUKOS)/toolchain/local/bin/x86_64-elf-
|
||||||
|
ifneq ($(wildcard $(TOOLCHAIN)gcc),)
|
||||||
|
CXX := $(TOOLCHAIN)g++
|
||||||
|
else
|
||||||
|
CXX := g++
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---- Paths ----
|
||||||
|
|
||||||
|
SYSROOT := sysroot
|
||||||
|
OBJDIR := obj
|
||||||
|
BINDIR := bin
|
||||||
|
LINK_LD := link.ld
|
||||||
|
|
||||||
|
# ---- Compiler flags ----
|
||||||
|
|
||||||
|
CXXFLAGS := \
|
||||||
|
-std=gnu++20 \
|
||||||
|
-g -O2 -pipe \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-nostdinc \
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-PIC \
|
||||||
|
-fno-rtti \
|
||||||
|
-fno-exceptions \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-msse \
|
||||||
|
-msse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=small \
|
||||||
|
-I $(SYSROOT)/include \
|
||||||
|
-I src \
|
||||||
|
-isystem $(SYSROOT)/include/libc
|
||||||
|
|
||||||
|
# ---- Linker flags ----
|
||||||
|
|
||||||
|
LDFLAGS := \
|
||||||
|
-nostdlib \
|
||||||
|
-static \
|
||||||
|
-Wl,--build-id=none \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-m,elf_x86_64 \
|
||||||
|
-z max-page-size=0x1000 \
|
||||||
|
-T $(LINK_LD)
|
||||||
|
|
||||||
|
# ---- Libraries ----
|
||||||
|
# Order matters: libtls depends on libbearssl, everything depends on liblibc.
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
ifeq ($(USE_TLS),1)
|
||||||
|
LIBS += $(SYSROOT)/lib/libtls.a $(SYSROOT)/lib/libbearssl.a
|
||||||
|
endif
|
||||||
|
ifeq ($(USE_JPEG),1)
|
||||||
|
LIBS += $(SYSROOT)/lib/libjpeg.a
|
||||||
|
endif
|
||||||
|
LIBS += $(SYSROOT)/lib/liblibc.a
|
||||||
|
|
||||||
|
# ---- Build rules ----
|
||||||
|
|
||||||
|
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||||
|
TARGET := $(BINDIR)/$(APP_NAME).elf
|
||||||
|
|
||||||
|
.PHONY: all clean install
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS) $(LINK_LD) Makefile
|
||||||
|
@mkdir -p $(BINDIR)
|
||||||
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
|
||||||
|
@echo "Built: $@"
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp Makefile
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJDIR) $(BINDIR)
|
||||||
|
|
||||||
|
# Copy the built ELF into the MontaukOS ramdisk tree for testing.
|
||||||
|
install: $(TARGET)
|
||||||
|
@mkdir -p $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)
|
||||||
|
cp $(TARGET) $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)/$(APP_NAME).elf
|
||||||
|
@echo "Installed to $(MONTAUKOS)/programs/bin/apps/$(APP_NAME)/"
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# MontaukOS App Template
|
||||||
|
|
||||||
|
Self-contained development environment for building standalone MontaukOS GUI apps. Copy this entire directory anywhere and start building.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp -r template/ ~/dev/myapp/
|
||||||
|
cd ~/dev/myapp/
|
||||||
|
# Edit APP_NAME and SRCS in Makefile
|
||||||
|
make
|
||||||
|
make install # copy ELF to MontaukOS ramdisk
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make # GUI-only app
|
||||||
|
make USE_TLS=1 # With HTTPS/TLS (libtls + libbearssl)
|
||||||
|
make USE_JPEG=1 # With JPEG decoding (libjpeg)
|
||||||
|
make USE_TLS=1 USE_JPEG=1 # Both
|
||||||
|
make clean # Remove build artifacts
|
||||||
|
make install # Copy ELF to MontaukOS ramdisk
|
||||||
|
```
|
||||||
|
|
||||||
|
If the MontaukOS tree is not at `~/dev/MontaukOS/`, pass the path to the cross-compiler:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make MONTAUKOS=/path/to/MontaukOS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
myapp/
|
||||||
|
├── Makefile Edit APP_NAME and SRCS here
|
||||||
|
├── link.ld Linker script (load at 0x400000)
|
||||||
|
├── src/
|
||||||
|
│ ├── main.cpp Your app (template with window, rendering, input)
|
||||||
|
│ ├── stb_truetype_impl.cpp TrueType font support (keep this)
|
||||||
|
│ └── cxxrt.cpp C++ new/delete runtime (keep this)
|
||||||
|
├── sysroot/
|
||||||
|
│ ├── include/
|
||||||
|
│ │ ├── montauk/ syscall.h, heap.h, string.h, config.h, toml.h, user.h
|
||||||
|
│ │ ├── gui/ gui.hpp, canvas.hpp, truetype.hpp, widgets.hpp, svg.hpp, ...
|
||||||
|
│ │ ├── http/ http.hpp (HTTP GET/POST/etc. wrapper)
|
||||||
|
│ │ ├── tls/ tls.hpp (HTTPS/TLS, for USE_TLS=1)
|
||||||
|
│ │ ├── Api/ Syscall.hpp (low-level syscall numbers)
|
||||||
|
│ │ ├── libc/ stdio.h, stdlib.h, string.h, ...
|
||||||
|
│ │ ├── bearssl*.h BearSSL headers (for USE_TLS=1)
|
||||||
|
│ │ └── (freestanding C/C++ standard headers)
|
||||||
|
│ └── lib/
|
||||||
|
│ ├── liblibc.a C library (always linked)
|
||||||
|
│ ├── libtls.a TLS helper library
|
||||||
|
│ ├── libbearssl.a BearSSL crypto
|
||||||
|
│ └── libjpeg.a JPEG decoding (stb_image)
|
||||||
|
└── docs/
|
||||||
|
├── gui-apps.md GUI programming guide
|
||||||
|
└── syscalls.md Syscall and API reference
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Points
|
||||||
|
|
||||||
|
- Entry point: `extern "C" void _start()` (not `main`)
|
||||||
|
- Memory: `montauk::malloc()` / `montauk::mfree()` (no standard libc)
|
||||||
|
- Window: `win_create()` / `win_poll()` / `win_present()` / `win_destroy()`
|
||||||
|
- Fonts: `TrueTypeFont::init("0:/fonts/Roboto-Medium.ttf")`
|
||||||
|
- HTTP: `#include <http/http.hpp>` with `USE_TLS=1` (see docs/)
|
||||||
|
- No exceptions, no RTTI, 32 KiB user stack
|
||||||
@@ -0,0 +1,916 @@
|
|||||||
|
# Writing GUI Applications for MontaukOS
|
||||||
|
|
||||||
|
This guide covers how to build graphical applications for MontaukOS, from standalone Window Server clients to desktop-integrated apps.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [App Types](#app-types)
|
||||||
|
- [Standalone Window Server Apps](#standalone-window-server-apps)
|
||||||
|
- [Desktop-Integrated Apps](#desktop-integrated-apps)
|
||||||
|
- [Drawing and Rendering](#drawing-and-rendering)
|
||||||
|
- [Text and Fonts](#text-and-fonts)
|
||||||
|
- [Input Handling](#input-handling)
|
||||||
|
- [Widgets](#widgets)
|
||||||
|
- [Colors and Theming](#colors-and-theming)
|
||||||
|
- [Memory Management](#memory-management)
|
||||||
|
- [Networking and HTTPS](#networking-and-https)
|
||||||
|
- [App Manifests](#app-manifests)
|
||||||
|
- [Build System](#build-system)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## App Types
|
||||||
|
|
||||||
|
MontaukOS supports two kinds of GUI applications:
|
||||||
|
|
||||||
|
| | Standalone Apps | Desktop Apps |
|
||||||
|
|---|---|---|
|
||||||
|
| **Location** | `programs/src/<appname>/` | `programs/src/desktop/apps/` |
|
||||||
|
| **Window** | Own process, shared-memory pixel buffer | Embedded in desktop compositor |
|
||||||
|
| **Event loop** | `win_poll()` syscall | Callback-driven (`on_draw`, `on_mouse`, `on_key`) |
|
||||||
|
| **Drawing** | Direct pixel buffer writes | `Canvas` abstraction |
|
||||||
|
| **Examples** | Spreadsheet, Music, Wikipedia | Calculator, File Manager, Terminal |
|
||||||
|
|
||||||
|
**Choose standalone** when you need a separate process (e.g., networking, heavy computation, isolation). **Choose desktop-integrated** for lightweight tools that benefit from tight compositor integration.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Standalone Window Server Apps
|
||||||
|
|
||||||
|
Standalone apps are separate ELF binaries that communicate with the Window Server through syscalls. They get a shared-memory pixel buffer and manage their own event loop.
|
||||||
|
|
||||||
|
### Minimal Example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <gui/gui.hpp>
|
||||||
|
#include <gui/truetype.hpp>
|
||||||
|
|
||||||
|
static TrueTypeFont* g_font;
|
||||||
|
static int g_win_w, g_win_h;
|
||||||
|
|
||||||
|
static void render(uint32_t* pixels) {
|
||||||
|
// Clear background
|
||||||
|
for (int i = 0; i < g_win_w * g_win_h; i++)
|
||||||
|
pixels[i] = Color::from_rgb(0xFF, 0xFF, 0xFF).to_pixel();
|
||||||
|
|
||||||
|
// Draw text
|
||||||
|
if (g_font)
|
||||||
|
g_font->draw_to_buffer(pixels, g_win_w, g_win_h,
|
||||||
|
20, 30, "Hello, MontaukOS!",
|
||||||
|
Color::from_rgb(0x33, 0x33, 0x33), 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void _start() {
|
||||||
|
// Load font
|
||||||
|
g_font = new TrueTypeFont();
|
||||||
|
g_font->init("0:/fonts/Roboto-Medium.ttf");
|
||||||
|
|
||||||
|
// Create window
|
||||||
|
g_win_w = 400;
|
||||||
|
g_win_h = 300;
|
||||||
|
Montauk::WinCreateResult wres;
|
||||||
|
montauk::win_create("My App", g_win_w, g_win_h, &wres);
|
||||||
|
int win_id = wres.id;
|
||||||
|
uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa;
|
||||||
|
|
||||||
|
// Initial render
|
||||||
|
render(pixels);
|
||||||
|
montauk::win_present(win_id);
|
||||||
|
|
||||||
|
// Event loop
|
||||||
|
while (true) {
|
||||||
|
Montauk::WinEvent ev;
|
||||||
|
int r = montauk::win_poll(win_id, &ev);
|
||||||
|
|
||||||
|
if (r < 0) break; // Window destroyed externally
|
||||||
|
if (r == 0) {
|
||||||
|
montauk::sleep_ms(16); // ~60 FPS idle
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type == 3) break; // Close event
|
||||||
|
|
||||||
|
if (ev.type == 2) { // Resize
|
||||||
|
g_win_w = ev.resize.w;
|
||||||
|
g_win_h = ev.resize.h;
|
||||||
|
pixels = (uint32_t*)(uintptr_t)montauk::win_resize(win_id, g_win_w, g_win_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type == 0) { // Keyboard
|
||||||
|
// ev.key.ascii, ev.key.scancode, ev.key.pressed
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type == 1) { // Mouse
|
||||||
|
// ev.mouse.x, ev.mouse.y, ev.mouse.buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
render(pixels);
|
||||||
|
montauk::win_present(win_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
montauk::win_destroy(win_id);
|
||||||
|
montauk::exit(0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Window Lifecycle
|
||||||
|
|
||||||
|
```
|
||||||
|
win_create() Create window, get pixel buffer pointer
|
||||||
|
|
|
||||||
|
v
|
||||||
|
win_present() Push current pixel buffer to screen
|
||||||
|
|
|
||||||
|
v
|
||||||
|
win_poll() Receive events (returns 0 if none, <0 if closed)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
win_resize() Handle resize, get new pixel buffer pointer
|
||||||
|
|
|
||||||
|
v
|
||||||
|
win_destroy() Clean up window
|
||||||
|
```
|
||||||
|
|
||||||
|
### Event Types
|
||||||
|
|
||||||
|
Events are delivered via `win_poll()` into a `WinEvent` struct:
|
||||||
|
|
||||||
|
| `ev.type` | Event | Fields |
|
||||||
|
|---|---|---|
|
||||||
|
| 0 | Keyboard | `ev.key.scancode`, `ev.key.ascii`, `ev.key.pressed`, `ev.key.shift`, `ev.key.ctrl`, `ev.key.alt` |
|
||||||
|
| 1 | Mouse | `ev.mouse.x`, `ev.mouse.y`, `ev.mouse.buttons`, `ev.mouse.prev_buttons`, `ev.mouse.scroll` |
|
||||||
|
| 2 | Resize | `ev.resize.w`, `ev.resize.h` |
|
||||||
|
| 3 | Close | (none) |
|
||||||
|
|
||||||
|
### Drawing Helpers
|
||||||
|
|
||||||
|
Standalone apps typically define local pixel-drawing helpers since they work with raw `uint32_t*` buffers:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static void px_fill(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, int w, int h, uint32_t color) {
|
||||||
|
for (int row = y; row < y + h && row < bh; row++)
|
||||||
|
for (int col = x; col < x + w && col < bw; col++)
|
||||||
|
px[row * bw + col] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void px_hline(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, int w, uint32_t color) {
|
||||||
|
for (int col = x; col < x + w && col < bw; col++)
|
||||||
|
if (y >= 0 && y < bh) px[y * bw + col] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void px_text(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, const char* text, Color c, int size) {
|
||||||
|
if (g_font)
|
||||||
|
g_font->draw_to_buffer(px, bw, bh, x, y, text, c, size);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rounded Rectangles
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static void px_fill_rounded(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, int w, int h, int r, uint32_t color) {
|
||||||
|
for (int row = y; row < y + h && row < bh; row++) {
|
||||||
|
for (int col = x; col < x + w && col < bw; col++) {
|
||||||
|
int dx = 0, dy = 0;
|
||||||
|
if (col < x + r && row < y + r) { dx = x + r - col; dy = y + r - row; }
|
||||||
|
else if (col >= x+w-r && row < y + r) { dx = col - (x+w-r-1); dy = y + r - row; }
|
||||||
|
else if (col < x + r && row >= y+h-r) { dx = x + r - col; dy = row - (y+h-r-1); }
|
||||||
|
else if (col >= x+w-r && row >= y+h-r) { dx = col - (x+w-r-1); dy = row - (y+h-r-1); }
|
||||||
|
if (dx * dx + dy * dy <= r * r)
|
||||||
|
px[row * bw + col] = color;
|
||||||
|
else if (dx == 0 && dy == 0)
|
||||||
|
px[row * bw + col] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Desktop-Integrated Apps
|
||||||
|
|
||||||
|
Desktop apps are compiled into the desktop binary itself. They register callback functions that the compositor calls during its event loop.
|
||||||
|
|
||||||
|
### Creating a Desktop App
|
||||||
|
|
||||||
|
**Step 1: Define your app state**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// In apps/app_myapp.cpp
|
||||||
|
struct MyAppState {
|
||||||
|
int counter;
|
||||||
|
char label[64];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Implement callbacks**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static void myapp_on_draw(Window* win, Framebuffer& fb) {
|
||||||
|
MyAppState* state = (MyAppState*)win->app_data;
|
||||||
|
Canvas c(win);
|
||||||
|
|
||||||
|
c.fill(colors::WINDOW_BG);
|
||||||
|
|
||||||
|
// Draw toolbar
|
||||||
|
c.fill_rect(0, 0, win->content_w, 36, Color::from_rgb(0xF5, 0xF5, 0xF5));
|
||||||
|
c.hline(0, 36, win->content_w, colors::BORDER);
|
||||||
|
|
||||||
|
// Draw content
|
||||||
|
c.text(20, 60, state->label, colors::TEXT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void myapp_on_mouse(Window* win, MouseEvent& ev) {
|
||||||
|
MyAppState* state = (MyAppState*)win->app_data;
|
||||||
|
if (ev.left_pressed()) {
|
||||||
|
state->counter++;
|
||||||
|
win->dirty = true; // Request redraw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void myapp_on_key(Window* win, const Montauk::KeyEvent& key) {
|
||||||
|
if (!key.pressed) return;
|
||||||
|
MyAppState* state = (MyAppState*)win->app_data;
|
||||||
|
// Handle keystrokes...
|
||||||
|
win->dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void myapp_on_close(Window* win) {
|
||||||
|
MyAppState* state = (MyAppState*)win->app_data;
|
||||||
|
montauk::mfree(state);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Write the open function**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void open_myapp(DesktopState* ds) {
|
||||||
|
int idx = desktop_create_window(ds, "My App", 400, 300, 320, 400);
|
||||||
|
if (idx < 0) return;
|
||||||
|
Window* win = &ds->windows[idx];
|
||||||
|
|
||||||
|
MyAppState* state = (MyAppState*)montauk::malloc(sizeof(MyAppState));
|
||||||
|
montauk::memset(state, 0, sizeof(MyAppState));
|
||||||
|
|
||||||
|
win->app_data = state;
|
||||||
|
win->on_draw = myapp_on_draw;
|
||||||
|
win->on_mouse = myapp_on_mouse;
|
||||||
|
win->on_key = myapp_on_key;
|
||||||
|
win->on_close = myapp_on_close;
|
||||||
|
win->dirty = true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Register in the app menu**
|
||||||
|
|
||||||
|
Add an entry in `desktop_init()` (`main.cpp`) to the app menu so users can launch it. Include the `open_myapp` function in `apps_common.hpp` or similar.
|
||||||
|
|
||||||
|
### Callback Reference
|
||||||
|
|
||||||
|
| Callback | Signature | When Called |
|
||||||
|
|---|---|---|
|
||||||
|
| `on_draw` | `void(Window*, Framebuffer&)` | Every frame when `win->dirty` is true |
|
||||||
|
| `on_mouse` | `void(Window*, MouseEvent&)` | Mouse event within window content area |
|
||||||
|
| `on_key` | `void(Window*, const KeyEvent&)` | Keyboard event while window is focused |
|
||||||
|
| `on_close` | `void(Window*)` | Window close button clicked |
|
||||||
|
| `on_poll` | `void(Window*)` | Every frame, for background processing |
|
||||||
|
|
||||||
|
### The `dirty` Flag
|
||||||
|
|
||||||
|
Desktop apps use a `dirty` flag to control redraws. Set `win->dirty = true` after any state change that requires a visual update. The compositor skips `on_draw` for non-dirty windows.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Drawing and Rendering
|
||||||
|
|
||||||
|
### Canvas API (Desktop Apps)
|
||||||
|
|
||||||
|
The `Canvas` wraps a window's pixel buffer with drawing primitives:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Canvas c(win); // Construct from Window*
|
||||||
|
|
||||||
|
// Fills
|
||||||
|
c.fill(Color c); // Entire buffer
|
||||||
|
c.fill_rect(int x, int y, int w, int h, Color c); // Rectangle
|
||||||
|
c.fill_rounded_rect(int x, int y, int w, int h, int r, Color c); // Rounded rect
|
||||||
|
|
||||||
|
// Lines
|
||||||
|
c.hline(int x, int y, int len, Color c); // Horizontal
|
||||||
|
c.vline(int x, int y, int len, Color c); // Vertical
|
||||||
|
c.rect(int x, int y, int w, int h, Color c); // Outline
|
||||||
|
|
||||||
|
// Text
|
||||||
|
c.text(int x, int y, const char* str, Color c); // TrueType or bitmap
|
||||||
|
c.text_2x(int x, int y, const char* str, Color c); // 2x scaled bitmap
|
||||||
|
c.text_mono(int x, int y, const char* str, Color c); // Monospace
|
||||||
|
|
||||||
|
// UI elements
|
||||||
|
c.button(int x, int y, int w, int h, const char* label,
|
||||||
|
Color bg, Color fg, int radius); // Styled button
|
||||||
|
c.icon(int x, int y, const SvgIcon& ic); // SVG icon
|
||||||
|
|
||||||
|
// Layout helpers
|
||||||
|
c.kv_line(int x, int* y, const char* line, Color c, int line_h); // Key-value line
|
||||||
|
c.separator(int x_start, int x_end, int* y, Color c, int spacing); // Horizontal separator
|
||||||
|
```
|
||||||
|
|
||||||
|
### Framebuffer API (Low-Level)
|
||||||
|
|
||||||
|
For direct framebuffer access (used by the compositor itself and fullscreen apps):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Framebuffer fb;
|
||||||
|
fb.put_pixel(x, y, color);
|
||||||
|
fb.put_pixel_alpha(x, y, color); // With alpha blending
|
||||||
|
fb.fill_rect(x, y, w, h, color);
|
||||||
|
fb.fill_rect_alpha(x, y, w, h, color);
|
||||||
|
fb.blit(x, y, w, h, pixels); // Copy pixel region
|
||||||
|
fb.blit_alpha(x, y, w, h, pixels); // With alpha blending
|
||||||
|
fb.clear(color);
|
||||||
|
fb.flip(); // Swap to hardware
|
||||||
|
```
|
||||||
|
|
||||||
|
### Drawing Primitives
|
||||||
|
|
||||||
|
From `gui/draw.hpp`, available for both Framebuffer-based rendering:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
draw_hline(fb, x, y, w, color);
|
||||||
|
draw_vline(fb, x, y, h, color);
|
||||||
|
draw_rect(fb, x, y, w, h, color);
|
||||||
|
fill_rounded_rect(fb, x, y, w, h, radius, color);
|
||||||
|
fill_circle(fb, cx, cy, r, color);
|
||||||
|
draw_circle(fb, cx, cy, r, color);
|
||||||
|
draw_line(fb, x0, y0, x1, y1, color); // Bresenham's
|
||||||
|
draw_shadow(fb, x, y, w, h, offset, color);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Text and Fonts
|
||||||
|
|
||||||
|
### TrueType Fonts (Preferred)
|
||||||
|
|
||||||
|
MontaukOS uses `stb_truetype` for font rendering. Fonts are loaded from the VFS:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
TrueTypeFont* font = new TrueTypeFont();
|
||||||
|
font->init("0:/fonts/Roboto-Medium.ttf");
|
||||||
|
|
||||||
|
// Render text to a pixel buffer
|
||||||
|
font->draw_to_buffer(pixels, buf_w, buf_h, x, y, "Hello", color, 18);
|
||||||
|
|
||||||
|
// Measure text width before drawing
|
||||||
|
int width = font->measure_text("Hello", 18);
|
||||||
|
|
||||||
|
// Get line height for layout
|
||||||
|
int line_h = font->get_line_height(18);
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Fonts
|
||||||
|
|
||||||
|
The desktop initializes a set of global fonts:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
fonts::init(); // Call once at startup
|
||||||
|
|
||||||
|
// Available fonts
|
||||||
|
fonts::system_font // Roboto-Medium.ttf (UI text)
|
||||||
|
fonts::system_bold // Roboto-Bold.ttf (headings)
|
||||||
|
fonts::mono // JetBrainsMono-Regular.ttf (code/terminal)
|
||||||
|
fonts::mono_bold // JetBrainsMono-Bold.ttf
|
||||||
|
|
||||||
|
// Standard sizes
|
||||||
|
fonts::UI_SIZE // 18 (body text)
|
||||||
|
fonts::TITLE_SIZE // 18 (window titles)
|
||||||
|
fonts::LARGE_SIZE // 28 (headings)
|
||||||
|
fonts::TERM_SIZE // 18 (terminal)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Glyph Caching
|
||||||
|
|
||||||
|
TrueType fonts cache rasterized glyphs per pixel size. Up to 4 size caches are maintained per font. Access the cache directly for advanced metrics:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
GlyphCache* cache = font->get_cache(18);
|
||||||
|
// cache->ascent, cache->descent — for line-height calculation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bitmap Font (Fallback)
|
||||||
|
|
||||||
|
An 8x8 bitmap font is always available for basic text rendering when TrueType is not loaded:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
draw_char(fb, x, y, 'A', color);
|
||||||
|
draw_text(fb, x, y, "Hello", color);
|
||||||
|
int w = text_width("Hello");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Input Handling
|
||||||
|
|
||||||
|
### Keyboard
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// In standalone apps (via win_poll)
|
||||||
|
if (ev.type == 0) {
|
||||||
|
Montauk::KeyEvent& key = ev.key;
|
||||||
|
if (!key.pressed) { /* key release */ }
|
||||||
|
|
||||||
|
if (key.ascii >= 0x20 && key.ascii < 0x7F) {
|
||||||
|
// Printable character
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special keys by scancode
|
||||||
|
switch (key.scancode) {
|
||||||
|
case 0x01: /* Escape */ break;
|
||||||
|
case 0x0E: /* Backspace */ break;
|
||||||
|
case 0x1C: /* Enter */ break;
|
||||||
|
case 0x0F: /* Tab */ break;
|
||||||
|
case 0x53: /* Delete */ break;
|
||||||
|
case 0x48: /* Up */ break;
|
||||||
|
case 0x50: /* Down */ break;
|
||||||
|
case 0x4B: /* Left */ break;
|
||||||
|
case 0x4D: /* Right */ break;
|
||||||
|
case 0x47: /* Home */ break;
|
||||||
|
case 0x4F: /* End */ break;
|
||||||
|
case 0x49: /* Page Up */ break;
|
||||||
|
case 0x51: /* Page Down */ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifiers
|
||||||
|
if (key.ctrl) { /* Ctrl held */ }
|
||||||
|
if (key.shift) { /* Shift held */ }
|
||||||
|
if (key.alt) { /* Alt held */ }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mouse
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// In standalone apps (via win_poll)
|
||||||
|
if (ev.type == 1) {
|
||||||
|
int mx = ev.mouse.x;
|
||||||
|
int my = ev.mouse.y;
|
||||||
|
|
||||||
|
// Button state
|
||||||
|
bool left_down = ev.mouse.buttons & 0x01;
|
||||||
|
bool right_down = ev.mouse.buttons & 0x02;
|
||||||
|
|
||||||
|
// Detect clicks (press edge)
|
||||||
|
bool left_pressed = (ev.mouse.buttons & 0x01) && !(ev.mouse.prev_buttons & 0x01);
|
||||||
|
bool left_released = !(ev.mouse.buttons & 0x01) && (ev.mouse.prev_buttons & 0x01);
|
||||||
|
|
||||||
|
// Scroll wheel
|
||||||
|
int scroll = ev.mouse.scroll; // Positive = up, negative = down
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In desktop apps, the `MouseEvent` struct provides convenience methods:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void myapp_on_mouse(Window* win, MouseEvent& ev) {
|
||||||
|
if (ev.left_pressed()) { /* click start */ }
|
||||||
|
if (ev.left_released()) { /* click end */ }
|
||||||
|
if (ev.left_held()) { /* dragging */ }
|
||||||
|
if (ev.right_pressed()) { /* context menu */ }
|
||||||
|
if (ev.scroll != 0) { /* scroll */ }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hit Testing
|
||||||
|
|
||||||
|
A common pattern for clickable UI regions:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct ButtonRect { int x, y, w, h; };
|
||||||
|
|
||||||
|
bool hit_test(ButtonRect& btn, int mx, int my) {
|
||||||
|
return mx >= btn.x && mx < btn.x + btn.w &&
|
||||||
|
my >= btn.y && my < btn.y + btn.h;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Widgets
|
||||||
|
|
||||||
|
MontaukOS provides built-in widget types in `gui/widgets.hpp`:
|
||||||
|
|
||||||
|
### Button
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Button btn;
|
||||||
|
btn.init(x, y, width, height, "Click Me");
|
||||||
|
btn.bg = colors::ACCENT;
|
||||||
|
btn.fg = colors::WHITE;
|
||||||
|
btn.on_click = [](void* data) { /* handle click */ };
|
||||||
|
btn.userdata = my_state;
|
||||||
|
|
||||||
|
// In draw callback
|
||||||
|
btn.draw(fb);
|
||||||
|
|
||||||
|
// In mouse callback
|
||||||
|
btn.handle_mouse(ev);
|
||||||
|
```
|
||||||
|
|
||||||
|
### TextBox
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
TextBox tb;
|
||||||
|
tb.init(x, y, width, height);
|
||||||
|
|
||||||
|
// In draw callback
|
||||||
|
tb.draw(fb);
|
||||||
|
|
||||||
|
// In mouse callback (sets focus)
|
||||||
|
tb.handle_mouse(ev);
|
||||||
|
|
||||||
|
// In key callback (text input)
|
||||||
|
tb.handle_key(key);
|
||||||
|
|
||||||
|
// Read value
|
||||||
|
const char* value = tb.text;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scrollbar
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Scrollbar sb;
|
||||||
|
sb.init(x, y, width, height);
|
||||||
|
sb.content_height = 2000; // Total content height
|
||||||
|
sb.view_height = 400; // Visible area height
|
||||||
|
|
||||||
|
// In draw callback
|
||||||
|
sb.draw(fb);
|
||||||
|
|
||||||
|
// In mouse callback
|
||||||
|
sb.handle_mouse(ev);
|
||||||
|
|
||||||
|
// Use scroll_offset for content positioning
|
||||||
|
int offset = sb.scroll_offset;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Colors and Theming
|
||||||
|
|
||||||
|
### Color Construction
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
Color c1 = Color::from_rgb(0xFF, 0x00, 0x00); // Red
|
||||||
|
Color c2 = Color::from_rgba(0x00, 0x00, 0xFF, 0x80); // Semi-transparent blue
|
||||||
|
Color c3 = Color::from_hex(0x367BF0); // From hex
|
||||||
|
uint32_t pixel = c3.to_pixel(); // ARGB for pixel buffer
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Colors
|
||||||
|
|
||||||
|
Defined in `gui/gui.hpp` under the `colors` namespace:
|
||||||
|
|
||||||
|
| Constant | Hex | Usage |
|
||||||
|
|---|---|---|
|
||||||
|
| `WINDOW_BG` | `#FFFFFF` | Window content background |
|
||||||
|
| `TEXT_COLOR` | `#333333` | Primary text |
|
||||||
|
| `ACCENT` | `#367BF0` | Links, selections, active elements |
|
||||||
|
| `BORDER` | `#D0D0D0` | Window/widget borders |
|
||||||
|
| `PANEL_BG` | `#2B3E50` | Taskbar/panel background |
|
||||||
|
| `PANEL_TEXT` | `#FFFFFF` | Panel text |
|
||||||
|
| `TITLEBAR_BG` | `#F5F5F5` | Window titlebar |
|
||||||
|
| `DESKTOP_BG` | `#E0E0E0` | Desktop background |
|
||||||
|
| `CLOSE_BTN` | `#FF5F57` | Close button (red) |
|
||||||
|
| `MAX_BTN` | `#28CA42` | Maximize button (green) |
|
||||||
|
| `MIN_BTN` | `#FFBD2E` | Minimize button (yellow) |
|
||||||
|
| `TERM_BG` | `#2D2D2D` | Terminal background |
|
||||||
|
| `TERM_FG` | `#CCCCCC` | Terminal text |
|
||||||
|
| `SCROLLBAR_BG` | | Scrollbar track |
|
||||||
|
| `SCROLLBAR_FG` | | Scrollbar thumb |
|
||||||
|
|
||||||
|
### Toolbar Convention
|
||||||
|
|
||||||
|
Standard toolbar pattern used across desktop apps:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 36px tall, light gray background, thin bottom border
|
||||||
|
c.fill_rect(0, 0, win->content_w, 36, Color::from_rgb(0xF5, 0xF5, 0xF5));
|
||||||
|
c.hline(0, 36, win->content_w, colors::BORDER);
|
||||||
|
|
||||||
|
// 24x24 icon buttons centered at y=6
|
||||||
|
c.icon(8, 6, my_icon);
|
||||||
|
|
||||||
|
// Content starts below toolbar
|
||||||
|
int content_y = 37;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Memory Management
|
||||||
|
|
||||||
|
### Userspace Heap
|
||||||
|
|
||||||
|
Use `montauk::malloc`, `montauk::mfree`, and `montauk::realloc` for dynamic allocation:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
|
||||||
|
MyState* state = (MyState*)montauk::malloc(sizeof(MyState));
|
||||||
|
montauk::memset(state, 0, sizeof(MyState));
|
||||||
|
// ... use state ...
|
||||||
|
montauk::mfree(state);
|
||||||
|
|
||||||
|
// Resize
|
||||||
|
char* buf = (char*)montauk::malloc(256);
|
||||||
|
buf = (char*)montauk::realloc(buf, 512);
|
||||||
|
```
|
||||||
|
|
||||||
|
The allocator uses size-class buckets (32 to 4096 bytes) with an overflow list for larger allocations.
|
||||||
|
|
||||||
|
### Kernel Page Allocation
|
||||||
|
|
||||||
|
`montauk::alloc` / `montauk::free` allocate kernel pages. Avoid for temporary buffers; use the heap instead.
|
||||||
|
|
||||||
|
### Important Notes
|
||||||
|
|
||||||
|
- **User stack is 32 KiB** (8 pages). Deep call chains (e.g., TrueType rendering) can approach this limit. Avoid large stack allocations.
|
||||||
|
- Use `inline` (not `static`) for shared globals in headers to avoid per-translation-unit copies and heap corruption.
|
||||||
|
- The libc needs `-fno-tree-loop-distribute-patterns` in CFLAGS to prevent GCC from converting `memcpy`/`memset` into calls to themselves.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Networking and HTTPS
|
||||||
|
|
||||||
|
MontaukOS provides a shared TLS library (`tls/tls.hpp`) backed by BearSSL, and the MontaukAI dev environment adds a higher-level HTTP wrapper (`http/http.hpp`) on top. Build with `USE_TLS=1` to link TLS support.
|
||||||
|
|
||||||
|
### HTTP Wrapper (`http/http.hpp`)
|
||||||
|
|
||||||
|
Header-only library that handles DNS resolution, request building, TLS, response parsing, and cleanup. All functions return an `http::Response` struct.
|
||||||
|
|
||||||
|
#### Setup
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <http/http.hpp>
|
||||||
|
|
||||||
|
// Load CA certificates once at startup (required for HTTPS)
|
||||||
|
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### GET
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto resp = http::get("api.example.com", "/v1/data", tas);
|
||||||
|
if (resp.status == 200) {
|
||||||
|
// resp.body is a pointer to the response body
|
||||||
|
// resp.body_len is its length
|
||||||
|
}
|
||||||
|
http::free_response(&resp);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### POST
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
const char* json = "{\"name\":\"MontaukOS\",\"version\":1}";
|
||||||
|
auto resp = http::post("api.example.com", "/v1/submit",
|
||||||
|
"application/json",
|
||||||
|
json, montauk::slen(json),
|
||||||
|
tas);
|
||||||
|
if (resp.status == 201) {
|
||||||
|
// Created successfully
|
||||||
|
}
|
||||||
|
http::free_response(&resp);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Other Methods (PUT, PATCH, DELETE, ...)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto resp = http::request("PUT", "api.example.com", "/v1/item/42",
|
||||||
|
"application/json",
|
||||||
|
body, bodyLen, tas);
|
||||||
|
http::free_response(&resp);
|
||||||
|
|
||||||
|
// DELETE with no body
|
||||||
|
auto resp2 = http::request("DELETE", "api.example.com", "/v1/item/42",
|
||||||
|
nullptr, nullptr, 0, tas);
|
||||||
|
http::free_response(&resp2);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Plain HTTP (No TLS, Port 80)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto resp = http::get_plain("example.com", "/");
|
||||||
|
if (resp.status == 200) {
|
||||||
|
// resp.body ...
|
||||||
|
}
|
||||||
|
http::free_response(&resp);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reading Response Headers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
char content_type[128];
|
||||||
|
if (http::get_header(&resp, "Content-Type", content_type, sizeof(content_type))) {
|
||||||
|
// content_type is e.g. "application/json; charset=utf-8"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Custom Headers
|
||||||
|
|
||||||
|
Pass extra headers as a string with `\r\n` terminators:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto resp = http::get("api.example.com", "/v1/data", tas,
|
||||||
|
32768, // response buffer size
|
||||||
|
"Authorization: Bearer tok_abc123\r\n"
|
||||||
|
"Accept: application/json\r\n");
|
||||||
|
http::free_response(&resp);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Cancellable Requests
|
||||||
|
|
||||||
|
For GUI apps that need to stay responsive during network I/O:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static bool g_quit = false;
|
||||||
|
static bool check_abort() { return g_quit; }
|
||||||
|
|
||||||
|
auto resp = http::get("api.example.com", "/v1/slow", tas,
|
||||||
|
32768, nullptr, check_abort);
|
||||||
|
http::free_response(&resp);
|
||||||
|
```
|
||||||
|
|
||||||
|
Set `g_quit = true` from your keyboard handler (e.g., on Escape) to cancel mid-request.
|
||||||
|
|
||||||
|
#### Response Struct Reference
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct http::Response {
|
||||||
|
int status; // HTTP status code (200, 404, ...) or -1 on error
|
||||||
|
const char* headers; // Pointer to header block (within raw buffer)
|
||||||
|
int headers_len;
|
||||||
|
const char* body; // Pointer to body (within raw buffer)
|
||||||
|
int body_len;
|
||||||
|
char* raw; // Owned buffer — freed by free_response()
|
||||||
|
int raw_len;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Function Signatures
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// HTTPS GET
|
||||||
|
http::Response http::get(const char* host, const char* path,
|
||||||
|
const tls::TrustAnchors& tas,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr,
|
||||||
|
tls::AbortCheckFn abort_check = nullptr);
|
||||||
|
|
||||||
|
// HTTPS POST
|
||||||
|
http::Response http::post(const char* host, const char* path,
|
||||||
|
const char* content_type,
|
||||||
|
const char* body, int body_len,
|
||||||
|
const tls::TrustAnchors& tas,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr,
|
||||||
|
tls::AbortCheckFn abort_check = nullptr);
|
||||||
|
|
||||||
|
// HTTPS with any method
|
||||||
|
http::Response http::request(const char* method,
|
||||||
|
const char* host, const char* path,
|
||||||
|
const char* content_type,
|
||||||
|
const char* body, int body_len,
|
||||||
|
const tls::TrustAnchors& tas,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr,
|
||||||
|
tls::AbortCheckFn abort_check = nullptr);
|
||||||
|
|
||||||
|
// Plain HTTP GET (port 80, no TLS)
|
||||||
|
http::Response http::get_plain(const char* host, const char* path,
|
||||||
|
int resp_buf_size = 32768,
|
||||||
|
const char* extra_headers = nullptr);
|
||||||
|
|
||||||
|
// Parse raw HTTP response buffer (used internally, available if needed)
|
||||||
|
int http::parse_response(char* buf, int len, http::Response* out);
|
||||||
|
|
||||||
|
// Case-insensitive header lookup
|
||||||
|
bool http::get_header(const http::Response* resp, const char* name,
|
||||||
|
char* out_val, int max_len);
|
||||||
|
|
||||||
|
// Free the response's raw buffer
|
||||||
|
void http::free_response(http::Response* resp);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Low-Level TLS API (`tls/tls.hpp`)
|
||||||
|
|
||||||
|
If you need more control than `http::` provides (e.g., streaming responses, custom BearSSL setup), use the TLS layer directly:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <tls/tls.hpp>
|
||||||
|
|
||||||
|
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||||
|
|
||||||
|
// Build raw HTTP request yourself
|
||||||
|
char req[512];
|
||||||
|
// ... "GET /stream HTTP/1.1\r\nHost: ...\r\n\r\n" ...
|
||||||
|
|
||||||
|
char buf[65536];
|
||||||
|
int n = tls::https_fetch("example.com", ip, 443, req, reqLen, tas, buf, sizeof(buf));
|
||||||
|
```
|
||||||
|
|
||||||
|
See `syscalls.md` for the full `tls::` API reference.
|
||||||
|
|
||||||
|
### Plain TCP/UDP
|
||||||
|
|
||||||
|
For non-TLS networking without the HTTP wrapper, use the raw socket syscalls directly (see `syscalls.md`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int sock = montauk::socket(Montauk::SOCK_TCP); // or SOCK_UDP
|
||||||
|
montauk::connect(sock, ip, port);
|
||||||
|
montauk::send(sock, data, len);
|
||||||
|
int n = montauk::recv(sock, buf, maxLen);
|
||||||
|
montauk::closesocket(sock);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## App Manifests
|
||||||
|
|
||||||
|
External standalone apps can be discovered by the desktop through TOML manifest files placed in `0:/apps/`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[app]
|
||||||
|
name = "My App"
|
||||||
|
binary = "myapp"
|
||||||
|
icon = "myapp_icon.svg"
|
||||||
|
|
||||||
|
[menu]
|
||||||
|
category = "Applications"
|
||||||
|
visible = true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Categories:** `Applications`, `Internet`, `System`, `Games`
|
||||||
|
|
||||||
|
The desktop scans `0:/apps/` at startup and adds matching entries to the application menu. The `binary` field is the executable name (looked up in the system path).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build System
|
||||||
|
|
||||||
|
### Independent Development (MontaukAI)
|
||||||
|
|
||||||
|
The `MontaukAI/` directory provides a self-contained build environment. Edit the top of `Makefile` to configure your app:
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
APP_NAME := myapp
|
||||||
|
SRCS := src/main.cpp src/stb_truetype_impl.cpp src/cxxrt.cpp src/network.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
Build with optional feature flags:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make # GUI-only app
|
||||||
|
make USE_TLS=1 # With HTTPS/TLS (links libtls + libbearssl)
|
||||||
|
make USE_JPEG=1 # With JPEG decoding (links libjpeg)
|
||||||
|
make USE_TLS=1 USE_JPEG=1 # Both
|
||||||
|
make install # Copy ELF to MontaukOS ramdisk
|
||||||
|
```
|
||||||
|
|
||||||
|
The sysroot contains all headers and pre-built libraries:
|
||||||
|
|
||||||
|
```
|
||||||
|
sysroot/
|
||||||
|
├── include/
|
||||||
|
│ ├── montauk/ syscall.h, heap.h, string.h, config.h, toml.h, user.h
|
||||||
|
│ ├── gui/ gui.hpp, canvas.hpp, truetype.hpp, widgets.hpp, svg.hpp, ...
|
||||||
|
│ ├── tls/ tls.hpp (HTTPS/TLS)
|
||||||
|
│ ├── Api/ Syscall.hpp (low-level syscall numbers)
|
||||||
|
│ ├── libc/ stdio.h, stdlib.h, string.h, ... (freestanding libc)
|
||||||
|
│ ├── bearssl*.h BearSSL headers (for USE_TLS=1)
|
||||||
|
│ └── (freestanding C/C++ standard headers)
|
||||||
|
└── lib/
|
||||||
|
├── liblibc.a C library (always linked)
|
||||||
|
├── libtls.a TLS helper library
|
||||||
|
├── libbearssl.a BearSSL crypto
|
||||||
|
└── libjpeg.a JPEG decoding (stb_image)
|
||||||
|
```
|
||||||
|
|
||||||
|
Key build details:
|
||||||
|
- **Toolchain:** `x86_64-elf-g++` cross-compiler (falls back to system g++)
|
||||||
|
- **Standard:** C++20 (`-std=gnu++20`), freestanding, no exceptions/RTTI
|
||||||
|
- **SSE:** Enabled (`-msse -msse2`) for floating-point / TrueType rendering
|
||||||
|
- **Entry point:** `extern "C" void _start()` (not `main`)
|
||||||
|
- **Load address:** `0x400000` (set in `link.ld`)
|
||||||
|
- **Runtime support:** `src/cxxrt.cpp` provides `operator new/delete` via `montauk::malloc/mfree`
|
||||||
|
- **TrueType support:** `src/stb_truetype_impl.cpp` provides the stb_truetype implementation
|
||||||
|
|
||||||
|
### In-Tree Development
|
||||||
|
|
||||||
|
Standalone apps can also live in `MontaukOS/programs/src/<appname>/` with their own `Makefile`. Each app's Makefile sets `SRCS`, `CXXFLAGS`, `LDFLAGS`, and links against libraries in `programs/lib/`.
|
||||||
|
|
||||||
|
Desktop-integrated apps are compiled as part of the desktop binary — add your `.cpp` file to the desktop's source list in `programs/src/desktop/Makefile`.
|
||||||
@@ -0,0 +1,572 @@
|
|||||||
|
# MontaukOS Syscall Reference
|
||||||
|
|
||||||
|
All syscalls are available through `#include <montauk/syscall.h>` in the `montauk` namespace. The syscall layer provides `syscall0()` through `syscall6()` primitives using AMD64 calling conventions. All raw syscalls return `int64_t`.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Process Management](#process-management)
|
||||||
|
- [File System](#file-system)
|
||||||
|
- [Memory](#memory)
|
||||||
|
- [Console I/O](#console-io)
|
||||||
|
- [Keyboard and Mouse](#keyboard-and-mouse)
|
||||||
|
- [Window Server](#window-server)
|
||||||
|
- [Framebuffer](#framebuffer)
|
||||||
|
- [Networking](#networking)
|
||||||
|
- [Audio](#audio)
|
||||||
|
- [Bluetooth](#bluetooth)
|
||||||
|
- [Timekeeping](#timekeeping)
|
||||||
|
- [System Information](#system-information)
|
||||||
|
- [Storage and Disks](#storage-and-disks)
|
||||||
|
- [Terminal](#terminal)
|
||||||
|
- [Process I/O Redirection](#process-io-redirection)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
- [User Management](#user-management)
|
||||||
|
- [Utility Libraries](#utility-libraries)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Process Management
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void exit(int code); // Terminate process (noreturn)
|
||||||
|
void yield(); // Yield CPU to scheduler
|
||||||
|
void sleep_ms(uint64_t ms); // Sleep for milliseconds
|
||||||
|
int getpid(); // Get current process ID
|
||||||
|
int spawn(const char* path, const char* args); // Spawn child process (-1 on error)
|
||||||
|
int waitpid(int pid); // Wait for process to exit
|
||||||
|
int kill(int pid); // Kill a process
|
||||||
|
int proclist(ProcInfo* buf, int max); // List all processes (returns count)
|
||||||
|
```
|
||||||
|
|
||||||
|
**`ProcInfo` struct:**
|
||||||
|
```cpp
|
||||||
|
struct ProcInfo {
|
||||||
|
int pid;
|
||||||
|
char name[32];
|
||||||
|
// ... additional fields
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int getargs(char* buf, uint64_t maxLen); // Get command-line arguments passed to this process
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File System
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int open(const char* path); // Open file (returns fd, negative on error)
|
||||||
|
int close(int handle); // Close file handle
|
||||||
|
int read(int handle, uint8_t* buf, uint64_t off, uint64_t size); // Read bytes at offset (returns bytes read)
|
||||||
|
int fwrite(int handle, const uint8_t* buf, uint64_t off, uint64_t size); // Write bytes at offset
|
||||||
|
uint64_t getsize(int handle); // Get file size
|
||||||
|
int readdir(const char* path, const char** names, int max); // List directory entries (returns count)
|
||||||
|
int fcreate(const char* path); // Create file (returns fd)
|
||||||
|
int fdelete(const char* path); // Delete file (0 on success)
|
||||||
|
int fmkdir(const char* path); // Create directory
|
||||||
|
int drivelist(int* outDrives, int max); // Enumerate mounted drives (returns count)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Path Format
|
||||||
|
|
||||||
|
Paths use the format `<drive>:/<path>`, e.g. `0:/fonts/Roboto-Medium.ttf`. Drive 0 is the boot drive (ramdisk).
|
||||||
|
|
||||||
|
### Example: Reading a File
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int fd = montauk::open("0:/config/settings.toml");
|
||||||
|
if (fd < 0) { /* error */ }
|
||||||
|
|
||||||
|
uint64_t size = montauk::getsize(fd);
|
||||||
|
uint8_t* buf = (uint8_t*)montauk::malloc(size + 1);
|
||||||
|
montauk::read(fd, buf, 0, size);
|
||||||
|
buf[size] = 0; // null-terminate
|
||||||
|
montauk::close(fd);
|
||||||
|
|
||||||
|
// ... use buf ...
|
||||||
|
montauk::mfree(buf);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Memory
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void* alloc(uint64_t size); // Allocate kernel pages (avoid for temp buffers)
|
||||||
|
void free(void* ptr); // Free kernel pages
|
||||||
|
```
|
||||||
|
|
||||||
|
For general-purpose allocation, prefer the userspace heap (`montauk/heap.h`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void* malloc(uint64_t size);
|
||||||
|
void mfree(void* ptr);
|
||||||
|
void* realloc(void* ptr, uint64_t size);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Console I/O
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void print(const char* text); // Write string to kernel console
|
||||||
|
void putchar(char c); // Write single character
|
||||||
|
```
|
||||||
|
|
||||||
|
These write to the kernel's text-mode console, not to a GUI window.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Keyboard and Mouse
|
||||||
|
|
||||||
|
### Keyboard (Direct, Non-Windowed)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool is_key_available(); // Poll for pending keystroke
|
||||||
|
void getkey(Montauk::KeyEvent* out); // Get next keystroke (blocks)
|
||||||
|
char getchar(); // Get single ASCII character (blocks)
|
||||||
|
```
|
||||||
|
|
||||||
|
**`KeyEvent` struct:**
|
||||||
|
```cpp
|
||||||
|
struct KeyEvent {
|
||||||
|
bool pressed; // true = key down, false = key up
|
||||||
|
uint8_t scancode; // PS/2 scancode
|
||||||
|
char ascii; // ASCII value (0 if non-printable)
|
||||||
|
bool shift, ctrl, alt;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Common Scancodes:**
|
||||||
|
|
||||||
|
| Scancode | Key |
|
||||||
|
|---|---|
|
||||||
|
| `0x01` | Escape |
|
||||||
|
| `0x0E` | Backspace |
|
||||||
|
| `0x0F` | Tab |
|
||||||
|
| `0x1C` | Enter |
|
||||||
|
| `0x39` | Space |
|
||||||
|
| `0x53` | Delete |
|
||||||
|
| `0x48` | Up |
|
||||||
|
| `0x50` | Down |
|
||||||
|
| `0x4B` | Left |
|
||||||
|
| `0x4D` | Right |
|
||||||
|
| `0x47` | Home |
|
||||||
|
| `0x4F` | End |
|
||||||
|
| `0x49` | Page Up |
|
||||||
|
| `0x51` | Page Down |
|
||||||
|
|
||||||
|
### Mouse (Direct, Non-Windowed)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void mouse_state(Montauk::MouseState* out); // Get current mouse state
|
||||||
|
void set_mouse_bounds(int32_t maxX, int32_t maxY); // Set mouse boundary
|
||||||
|
```
|
||||||
|
|
||||||
|
**`MouseState` struct:**
|
||||||
|
```cpp
|
||||||
|
struct MouseState {
|
||||||
|
int32_t x, y;
|
||||||
|
uint8_t buttons; // 0x01=Left, 0x02=Right, 0x04=Middle
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
For GUI apps, prefer the windowed event system (`win_poll`) over direct mouse/keyboard syscalls.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Window Server
|
||||||
|
|
||||||
|
These syscalls are for standalone GUI apps that run as separate processes. The desktop compositor manages window frames; your app renders into a shared pixel buffer.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int win_create(const char* title, int w, int h, WinCreateResult* result);
|
||||||
|
void win_destroy(int id);
|
||||||
|
uint64_t win_present(int id); // Mark window dirty, present to screen
|
||||||
|
int win_poll(int id, WinEvent* event); // Poll events (0=none, 1=event, <0=closed)
|
||||||
|
uint64_t win_resize(int id, int w, int h); // Resize, returns new pixel buffer address
|
||||||
|
uint64_t win_map(int id); // Get pixel buffer address
|
||||||
|
int win_enumerate(WinInfo* info, int max); // List all windows
|
||||||
|
int win_sendevent(int id, const WinEvent* event); // Send event to a window
|
||||||
|
int win_setscale(int scale); // Set UI scale factor
|
||||||
|
int win_getscale(); // Get UI scale factor
|
||||||
|
int win_setcursor(int id, int cursor); // Set cursor style
|
||||||
|
```
|
||||||
|
|
||||||
|
**`WinCreateResult` struct:**
|
||||||
|
```cpp
|
||||||
|
struct WinCreateResult {
|
||||||
|
int id; // Window ID for subsequent calls
|
||||||
|
uint64_t pixelVa; // Virtual address of shared pixel buffer (uint32_t* ARGB)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**`WinEvent` struct:**
|
||||||
|
```cpp
|
||||||
|
struct WinEvent {
|
||||||
|
int type; // 0=Key, 1=Mouse, 2=Resize, 3=Close
|
||||||
|
union {
|
||||||
|
struct { uint8_t scancode; char ascii; bool pressed, shift, ctrl, alt; } key;
|
||||||
|
struct { int x, y; uint8_t buttons, prev_buttons; int32_t scroll; } mouse;
|
||||||
|
struct { int w, h; } resize;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Event Loop Pattern
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
while (true) {
|
||||||
|
Montauk::WinEvent ev;
|
||||||
|
int r = montauk::win_poll(win_id, &ev);
|
||||||
|
if (r < 0) break; // Window closed
|
||||||
|
if (r == 0) {
|
||||||
|
montauk::sleep_ms(16); // No events, idle at ~60fps
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (ev.type) {
|
||||||
|
case 0: handle_key(ev.key); break;
|
||||||
|
case 1: handle_mouse(ev.mouse); break;
|
||||||
|
case 2: handle_resize(ev.resize); break;
|
||||||
|
case 3: goto done; // Close
|
||||||
|
}
|
||||||
|
render(pixels);
|
||||||
|
montauk::win_present(win_id);
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
montauk::win_destroy(win_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Framebuffer
|
||||||
|
|
||||||
|
For direct framebuffer access (fullscreen apps, not typical for windowed apps):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void fb_info(FbInfo* info); // Get dimensions and pitch
|
||||||
|
void* fb_map(); // Map framebuffer to user address space
|
||||||
|
```
|
||||||
|
|
||||||
|
**`FbInfo` struct:**
|
||||||
|
```cpp
|
||||||
|
struct FbInfo {
|
||||||
|
uint32_t width, height;
|
||||||
|
uint32_t pitch; // Bytes per row
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Networking
|
||||||
|
|
||||||
|
### DNS and Connectivity
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int32_t ping(uint32_t ip, uint32_t timeoutMs); // Ping, returns RTT in ms (-1 on timeout)
|
||||||
|
uint32_t resolve(const char* hostname); // DNS lookup, returns IPv4 (0 on failure)
|
||||||
|
void get_netcfg(NetCfg* out); // Get network config
|
||||||
|
int set_netcfg(const NetCfg* cfg); // Set network config
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sockets
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int socket(int type); // Create socket (0=TCP, 1=UDP)
|
||||||
|
int connect(int fd, uint32_t ip, uint16_t port); // TCP connect
|
||||||
|
int bind(int fd, uint16_t port); // Bind to port
|
||||||
|
int listen(int fd); // Start listening
|
||||||
|
int accept(int fd); // Accept connection (returns new fd)
|
||||||
|
int send(int fd, const void* data, uint32_t len); // Send data (returns bytes sent)
|
||||||
|
int recv(int fd, void* buf, uint32_t maxLen); // Receive data (returns bytes read)
|
||||||
|
int closesocket(int fd); // Close socket
|
||||||
|
```
|
||||||
|
|
||||||
|
### UDP
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int sendto(int fd, const void* data, uint32_t len,
|
||||||
|
uint32_t destIp, uint16_t destPort);
|
||||||
|
int recvfrom(int fd, void* buf, uint32_t maxLen,
|
||||||
|
uint32_t* srcIp, uint16_t* srcPort);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: Plain HTTP GET (Port 80)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
uint32_t ip = montauk::resolve("example.com");
|
||||||
|
int sock = montauk::socket(0); // TCP
|
||||||
|
montauk::connect(sock, ip, 80);
|
||||||
|
|
||||||
|
const char* req = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n";
|
||||||
|
montauk::send(sock, req, montauk::slen(req));
|
||||||
|
|
||||||
|
char buf[4096];
|
||||||
|
int n = montauk::recv(sock, buf, sizeof(buf) - 1);
|
||||||
|
buf[n] = 0;
|
||||||
|
|
||||||
|
montauk::closesocket(sock);
|
||||||
|
```
|
||||||
|
|
||||||
|
### TLS / HTTPS Library
|
||||||
|
|
||||||
|
Header: `tls/tls.hpp` — requires linking `libtls.a` and `libbearssl.a` (build with `USE_TLS=1`).
|
||||||
|
|
||||||
|
Provides a high-level `tls::https_fetch()` that handles socket creation, BearSSL TLS 1.2 setup, handshake, request/response exchange, and cleanup in a single call.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <tls/tls.hpp>
|
||||||
|
|
||||||
|
// Load CA certificates (from 0:/etc/ca-certificates.crt)
|
||||||
|
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||||
|
|
||||||
|
// Build HTTP request
|
||||||
|
const char* host = "en.wikipedia.org";
|
||||||
|
uint32_t ip = montauk::resolve(host);
|
||||||
|
|
||||||
|
char req[256];
|
||||||
|
// ... build "GET /path HTTP/1.1\r\nHost: ...\r\n\r\n" into req ...
|
||||||
|
int reqLen = montauk::slen(req);
|
||||||
|
|
||||||
|
// Fetch (handles TLS handshake, send, receive, teardown)
|
||||||
|
char resp[32768];
|
||||||
|
int n = tls::https_fetch(host, ip, 443, req, reqLen, tas, resp, sizeof(resp));
|
||||||
|
if (n > 0) {
|
||||||
|
resp[n] = 0;
|
||||||
|
// ... parse HTTP response ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**API reference:**
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace tls {
|
||||||
|
// Load PEM CA bundle from 0:/etc/ca-certificates.crt
|
||||||
|
TrustAnchors load_trust_anchors();
|
||||||
|
|
||||||
|
// High-level: DNS → socket → TLS → exchange → cleanup
|
||||||
|
int https_fetch(const char* host, uint32_t ip, uint16_t port,
|
||||||
|
const char* request, int reqLen,
|
||||||
|
const TrustAnchors& tas,
|
||||||
|
char* respBuf, int respMax,
|
||||||
|
AbortCheckFn abort_check = nullptr);
|
||||||
|
|
||||||
|
// Lower-level: run TLS exchange on an existing socket + BearSSL engine
|
||||||
|
int tls_exchange(int fd, br_ssl_engine_context* eng,
|
||||||
|
const char* request, int reqLen,
|
||||||
|
char* respBuf, int respMax,
|
||||||
|
AbortCheckFn abort_check = nullptr);
|
||||||
|
|
||||||
|
// Helpers for manual BearSSL usage
|
||||||
|
int tls_send_all(int fd, const unsigned char* data, size_t len);
|
||||||
|
int tls_recv_some(int fd, unsigned char* buf, size_t maxlen);
|
||||||
|
void get_bearssl_time(uint32_t* days, uint32_t* seconds);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The optional `AbortCheckFn` callback (e.g., `bool check_quit()`) lets terminal/GUI apps cancel a fetch in progress (return `true` to abort).
|
||||||
|
|
||||||
|
### HTTP Wrapper (`http/http.hpp`)
|
||||||
|
|
||||||
|
The MontaukAI dev environment includes a higher-level HTTP wrapper built on top of `tls::https_fetch()`. It handles DNS, request building, TLS, and response parsing automatically. See the "Networking and HTTPS" section in `gui-apps.md` for full documentation and examples.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <http/http.hpp>
|
||||||
|
|
||||||
|
tls::TrustAnchors tas = tls::load_trust_anchors();
|
||||||
|
|
||||||
|
auto resp = http::get("api.example.com", "/v1/data", tas);
|
||||||
|
if (resp.status == 200) { /* resp.body, resp.body_len */ }
|
||||||
|
http::free_response(&resp);
|
||||||
|
|
||||||
|
auto resp2 = http::post("api.example.com", "/v1/submit",
|
||||||
|
"application/json", json, jsonLen, tas);
|
||||||
|
http::free_response(&resp2);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Audio
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int audio_open(uint32_t sampleRate, uint8_t channels, uint8_t bitsPerSample);
|
||||||
|
int audio_close(int handle);
|
||||||
|
int audio_write(int handle, const void* data, uint32_t size); // Write PCM samples
|
||||||
|
int audio_ctl(int handle, int cmd, int value); // Generic control
|
||||||
|
```
|
||||||
|
|
||||||
|
### Convenience Wrappers
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int audio_set_volume(int handle, int percent); // 0-100
|
||||||
|
int audio_get_volume(int handle);
|
||||||
|
int audio_pause(int handle);
|
||||||
|
int audio_resume(int handle);
|
||||||
|
int audio_get_pos(int handle); // Playback position
|
||||||
|
int audio_get_output(int handle); // Current output device
|
||||||
|
int audio_bt_status(int handle); // Bluetooth audio status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bluetooth
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int bt_scan(BtScanResult* buf, int maxCount, uint32_t timeoutMs); // Scan for devices
|
||||||
|
int bt_connect(const uint8_t* bdAddr); // Connect
|
||||||
|
int bt_disconnect(const uint8_t* bdAddr); // Disconnect
|
||||||
|
int bt_list(BtDevInfo* buf, int maxCount); // List connected devices
|
||||||
|
int bt_info(BtAdapterInfo* buf); // Adapter info
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Timekeeping
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
uint64_t get_ticks(); // CPU tick counter
|
||||||
|
uint64_t get_milliseconds(); // Milliseconds since boot
|
||||||
|
void gettime(Montauk::DateTime* out); // Wall-clock time
|
||||||
|
```
|
||||||
|
|
||||||
|
**`DateTime` struct:**
|
||||||
|
```cpp
|
||||||
|
struct DateTime {
|
||||||
|
uint16_t year;
|
||||||
|
uint8_t month, day, hour, minute, second;
|
||||||
|
uint8_t weekday;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## System Information
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void get_info(SysInfo* info); // CPU, memory, system info
|
||||||
|
void memstats(MemStats* out); // Memory usage statistics
|
||||||
|
int64_t getrandom(void* buf, uint32_t len); // Cryptographic random bytes
|
||||||
|
void reset(); // System reset (noreturn)
|
||||||
|
void shutdown(); // System shutdown (noreturn)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Storage and Disks
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int partlist(PartInfo* buf, int max); // List GPT partitions
|
||||||
|
int disk_read(int blockDev, uint64_t lba, uint32_t sectorCount, void* buf); // Raw sector read
|
||||||
|
int disk_write(int blockDev, uint64_t lba, uint32_t sectorCount, const void* buf); // Raw sector write
|
||||||
|
int gpt_init(int blockDev); // Initialize GPT
|
||||||
|
int gpt_add(const GptAddParams* params); // Add partition
|
||||||
|
int fs_mount(int partIndex, int driveNum); // Mount filesystem
|
||||||
|
int fs_format(const FsFormatParams* params); // Format filesystem
|
||||||
|
int diskinfo(DiskInfo* buf, int port); // Get disk info
|
||||||
|
int devlist(DevInfo* buf, int max); // List block devices
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Terminal
|
||||||
|
|
||||||
|
For terminal-mode (non-GUI) applications:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void termsize(int* cols, int* rows); // Get terminal dimensions
|
||||||
|
void termscale(int scale_x, int scale_y); // Set text scaling
|
||||||
|
void get_termscale(int* scale_x, int* scale_y); // Get text scaling
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Process I/O Redirection
|
||||||
|
|
||||||
|
For launching child processes with redirected I/O (used by the terminal emulator):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int spawn_redir(const char* path, const char* args); // Spawn with I/O pipes
|
||||||
|
int childio_read(int childPid, char* buf, int maxLen); // Read child stdout
|
||||||
|
int childio_write(int childPid, const char* data, int len); // Write to child stdin
|
||||||
|
int childio_writekey(int childPid, const Montauk::KeyEvent* key); // Send keystroke to child
|
||||||
|
int childio_settermsz(int childPid, int cols, int rows); // Set child terminal size
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Header: `montauk/config.h`
|
||||||
|
|
||||||
|
TOML-based configuration stored in `0:/config/`. Provides per-system and per-user config files.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
toml::Doc config::load(const char* name); // Load 0:/config/<name>.toml
|
||||||
|
int config::save(const char* name, toml::Doc* doc); // Save config (0 = success)
|
||||||
|
toml::Doc config::load_user(const char* username, const char* name); // Per-user config
|
||||||
|
int config::save_user(const char* username, const char* name, toml::Doc* doc);
|
||||||
|
|
||||||
|
void config::set_string(toml::Doc* doc, const char* key, const char* val);
|
||||||
|
void config::set_int(toml::Doc* doc, const char* key, int64_t val);
|
||||||
|
void config::set_bool(toml::Doc* doc, const char* key, bool val);
|
||||||
|
bool config::unset(toml::Doc* doc, const char* key);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto doc = montauk::config::load("session");
|
||||||
|
const char* user = doc.get_string("session.username", "guest");
|
||||||
|
|
||||||
|
montauk::config::set_string(&doc, "session.theme", "dark");
|
||||||
|
montauk::config::save("session", &doc);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## User Management
|
||||||
|
|
||||||
|
Header: `montauk/user.h`
|
||||||
|
|
||||||
|
User authentication and session management with SHA-256 password hashing.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
bool user::authenticate(const char* username, const char* password);
|
||||||
|
bool user::create_user(const char* username, const char* display_name,
|
||||||
|
const char* password, const char* role);
|
||||||
|
bool user::delete_user(const char* username);
|
||||||
|
bool user::change_password(const char* username, const char* new_password);
|
||||||
|
|
||||||
|
void user::set_session(const char* username); // Log in
|
||||||
|
void user::clear_session(); // Log out
|
||||||
|
bool user::get_session_username(char* buf, int sz); // Get current user
|
||||||
|
bool user::get_home_dir(char* buf, int sz); // Get user's home directory
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Utility Libraries
|
||||||
|
|
||||||
|
### String Functions (`montauk/string.h`)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
int slen(const char* s);
|
||||||
|
bool streq(const char* a, const char* b);
|
||||||
|
bool starts_with(const char* str, const char* prefix);
|
||||||
|
void memcpy(void* dst, const void* src, uint64_t n);
|
||||||
|
void memmove(void* dst, const void* src, uint64_t n);
|
||||||
|
void memset(void* dst, int val, uint64_t n);
|
||||||
|
void strcpy(char* dst, const char* src);
|
||||||
|
void strncpy(char* dst, const char* src, int max);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Heap (`montauk/heap.h`)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void* malloc(uint64_t size);
|
||||||
|
void mfree(void* ptr);
|
||||||
|
void* realloc(void* ptr, uint64_t size);
|
||||||
|
```
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* link.ld
|
||||||
|
* Linker script for MontaukOS userspace programs
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*
|
||||||
|
* Programs are loaded at a standard user-space address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x400000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4096);
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data .data.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss .bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame*)
|
||||||
|
*(.note .note.*)
|
||||||
|
*(.comment*)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* cxxrt.cpp
|
||||||
|
* Minimal C++ runtime support for freestanding MontaukOS apps.
|
||||||
|
* Provides operator new/delete backed by montauk::malloc/mfree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
|
||||||
|
void* operator new(size_t size) { return montauk::malloc(size); }
|
||||||
|
void* operator new[](size_t size) { return montauk::malloc(size); }
|
||||||
|
void operator delete(void* ptr) noexcept { montauk::mfree(ptr); }
|
||||||
|
void operator delete[](void* ptr) noexcept { montauk::mfree(ptr); }
|
||||||
|
void operator delete(void* ptr, size_t) noexcept { montauk::mfree(ptr); }
|
||||||
|
void operator delete[](void* ptr, size_t) noexcept { montauk::mfree(ptr); }
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* main.cpp
|
||||||
|
* Template standalone GUI app for MontaukOS
|
||||||
|
*
|
||||||
|
* This is a minimal working app that creates a window, renders text,
|
||||||
|
* and handles input events. Use it as a starting point for your app.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <montauk/syscall.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <gui/gui.hpp>
|
||||||
|
#include <gui/truetype.hpp>
|
||||||
|
|
||||||
|
using namespace gui;
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// State
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static TrueTypeFont* g_font;
|
||||||
|
static int g_win_w = 500;
|
||||||
|
static int g_win_h = 400;
|
||||||
|
static int g_click_count = 0;
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Drawing helpers
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void px_fill(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, int w, int h, uint32_t color) {
|
||||||
|
for (int row = y; row < y + h && row < bh; row++)
|
||||||
|
for (int col = x; col < x + w && col < bw; col++)
|
||||||
|
if (row >= 0 && col >= 0)
|
||||||
|
px[row * bw + col] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void px_fill_rounded(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, int w, int h, int r, uint32_t color) {
|
||||||
|
for (int row = y; row < y + h && row < bh; row++) {
|
||||||
|
for (int col = x; col < x + w && col < bw; col++) {
|
||||||
|
if (row < 0 || col < 0) continue;
|
||||||
|
int dx = 0, dy = 0;
|
||||||
|
if (col < x + r && row < y + r) { dx = x + r - col; dy = y + r - row; }
|
||||||
|
else if (col >= x+w-r && row < y + r) { dx = col-(x+w-r-1); dy = y + r - row; }
|
||||||
|
else if (col < x + r && row >= y+h-r) { dx = x + r - col; dy = row-(y+h-r-1); }
|
||||||
|
else if (col >= x+w-r && row >= y+h-r) { dx = col-(x+w-r-1); dy = row-(y+h-r-1); }
|
||||||
|
if (dx * dx + dy * dy <= r * r)
|
||||||
|
px[row * bw + col] = color;
|
||||||
|
else if (dx == 0 && dy == 0)
|
||||||
|
px[row * bw + col] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void px_text(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, const char* text, Color c, int size) {
|
||||||
|
if (g_font)
|
||||||
|
g_font->draw_to_buffer(px, bw, bh, x, y, text, c, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void px_hline(uint32_t* px, int bw, int bh,
|
||||||
|
int x, int y, int w, uint32_t color) {
|
||||||
|
if (y < 0 || y >= bh) return;
|
||||||
|
for (int col = x; col < x + w && col < bw; col++)
|
||||||
|
if (col >= 0) px[y * bw + col] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Rendering
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void render(uint32_t* pixels) {
|
||||||
|
// Background
|
||||||
|
px_fill(pixels, g_win_w, g_win_h, 0, 0, g_win_w, g_win_h,
|
||||||
|
Color::from_rgb(0xFF, 0xFF, 0xFF).to_pixel());
|
||||||
|
|
||||||
|
// Toolbar
|
||||||
|
px_fill(pixels, g_win_w, g_win_h, 0, 0, g_win_w, 36,
|
||||||
|
Color::from_rgb(0xF5, 0xF5, 0xF5).to_pixel());
|
||||||
|
px_hline(pixels, g_win_w, g_win_h, 0, 36, g_win_w,
|
||||||
|
Color::from_rgb(0xD0, 0xD0, 0xD0).to_pixel());
|
||||||
|
|
||||||
|
// Title in toolbar
|
||||||
|
px_text(pixels, g_win_w, g_win_h, 12, 10, "My App",
|
||||||
|
Color::from_rgb(0x33, 0x33, 0x33), 18);
|
||||||
|
|
||||||
|
// Content area
|
||||||
|
px_text(pixels, g_win_w, g_win_h, 20, 60, "Hello from MontaukOS!",
|
||||||
|
Color::from_rgb(0x33, 0x33, 0x33), 18);
|
||||||
|
|
||||||
|
// Click counter
|
||||||
|
char buf[64];
|
||||||
|
const char* prefix = "Clicks: ";
|
||||||
|
int i = 0;
|
||||||
|
while (prefix[i]) { buf[i] = prefix[i]; i++; }
|
||||||
|
int n = g_click_count;
|
||||||
|
if (n == 0) { buf[i++] = '0'; }
|
||||||
|
else {
|
||||||
|
char tmp[16]; int ti = 0;
|
||||||
|
while (n > 0) { tmp[ti++] = '0' + (n % 10); n /= 10; }
|
||||||
|
for (int j = ti - 1; j >= 0; j--) buf[i++] = tmp[j];
|
||||||
|
}
|
||||||
|
buf[i] = 0;
|
||||||
|
|
||||||
|
px_text(pixels, g_win_w, g_win_h, 20, 90, buf,
|
||||||
|
Color::from_rgb(0x66, 0x66, 0x66), 16);
|
||||||
|
|
||||||
|
// A styled button
|
||||||
|
px_fill_rounded(pixels, g_win_w, g_win_h,
|
||||||
|
20, 130, 120, 36, 4,
|
||||||
|
Color::from_rgb(0x36, 0x7B, 0xF0).to_pixel());
|
||||||
|
px_text(pixels, g_win_w, g_win_h, 42, 139, "Click me",
|
||||||
|
Color::from_rgb(0xFF, 0xFF, 0xFF), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Entry point
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
extern "C" void _start() {
|
||||||
|
// Load font
|
||||||
|
g_font = new TrueTypeFont();
|
||||||
|
if (!g_font->init("0:/fonts/Roboto-Medium.ttf"))
|
||||||
|
g_font = nullptr;
|
||||||
|
|
||||||
|
// Create window
|
||||||
|
Montauk::WinCreateResult wres;
|
||||||
|
montauk::win_create("My App", g_win_w, g_win_h, &wres);
|
||||||
|
int win_id = wres.id;
|
||||||
|
uint32_t* pixels = (uint32_t*)(uintptr_t)wres.pixelVa;
|
||||||
|
|
||||||
|
// Initial render
|
||||||
|
render(pixels);
|
||||||
|
montauk::win_present(win_id);
|
||||||
|
|
||||||
|
// Event loop
|
||||||
|
while (true) {
|
||||||
|
Montauk::WinEvent ev;
|
||||||
|
int r = montauk::win_poll(win_id, &ev);
|
||||||
|
|
||||||
|
if (r < 0) break;
|
||||||
|
if (r == 0) {
|
||||||
|
montauk::sleep_ms(16);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ev.type) {
|
||||||
|
case 0: // Keyboard
|
||||||
|
if (ev.key.pressed && ev.key.scancode == 0x01)
|
||||||
|
goto done; // ESC to close
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // Mouse
|
||||||
|
if ((ev.mouse.buttons & 0x01) && !(ev.mouse.prev_buttons & 0x01)) {
|
||||||
|
// Left click — check if inside button
|
||||||
|
int mx = ev.mouse.x, my = ev.mouse.y;
|
||||||
|
if (mx >= 20 && mx < 140 && my >= 130 && my < 166)
|
||||||
|
g_click_count++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Resize
|
||||||
|
g_win_w = ev.resize.w;
|
||||||
|
g_win_h = ev.resize.h;
|
||||||
|
pixels = (uint32_t*)(uintptr_t)montauk::win_resize(win_id, g_win_w, g_win_h);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Close
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(pixels);
|
||||||
|
montauk::win_present(win_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
montauk::win_destroy(win_id);
|
||||||
|
montauk::exit(0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* stb_truetype_impl.cpp
|
||||||
|
* Single compilation unit for stb_truetype in MontaukOS freestanding environment
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <montauk/heap.h>
|
||||||
|
#include <montauk/string.h>
|
||||||
|
#include <gui/stb_math.h>
|
||||||
|
|
||||||
|
#define STBTT_ifloor(x) ((int) stb_floor(x))
|
||||||
|
#define STBTT_iceil(x) ((int) stb_ceil(x))
|
||||||
|
#define STBTT_sqrt(x) stb_sqrt(x)
|
||||||
|
#define STBTT_pow(x,y) stb_pow(x,y)
|
||||||
|
#define STBTT_fmod(x,y) stb_fmod(x,y)
|
||||||
|
#define STBTT_cos(x) stb_cos(x)
|
||||||
|
#define STBTT_acos(x) stb_acos(x)
|
||||||
|
#define STBTT_fabs(x) stb_fabs(x)
|
||||||
|
|
||||||
|
#define STBTT_malloc(x,u) ((void)(u), montauk::malloc(x))
|
||||||
|
#define STBTT_free(x,u) ((void)(u), montauk::mfree(x))
|
||||||
|
|
||||||
|
#define STBTT_memcpy(d,s,n) montauk::memcpy(d,s,n)
|
||||||
|
#define STBTT_memset(d,v,n) montauk::memset(d,v,n)
|
||||||
|
|
||||||
|
#define STBTT_strlen(x) montauk::slen(x)
|
||||||
|
|
||||||
|
#define STBTT_assert(x) ((void)(x))
|
||||||
|
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#include <gui/stb_truetype.h>
|
||||||
@@ -0,0 +1,318 @@
|
|||||||
|
/*
|
||||||
|
* Syscall.hpp
|
||||||
|
* MontaukOS syscall definitions for userspace programs
|
||||||
|
* Copyright (c) 2025 Daniel Hammer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace Montauk {
|
||||||
|
|
||||||
|
// Syscall numbers
|
||||||
|
static constexpr uint64_t SYS_EXIT = 0;
|
||||||
|
static constexpr uint64_t SYS_YIELD = 1;
|
||||||
|
static constexpr uint64_t SYS_SLEEP_MS = 2;
|
||||||
|
static constexpr uint64_t SYS_GETPID = 3;
|
||||||
|
static constexpr uint64_t SYS_PRINT = 4;
|
||||||
|
static constexpr uint64_t SYS_PUTCHAR = 5;
|
||||||
|
static constexpr uint64_t SYS_OPEN = 6;
|
||||||
|
static constexpr uint64_t SYS_READ = 7;
|
||||||
|
static constexpr uint64_t SYS_GETSIZE = 8;
|
||||||
|
static constexpr uint64_t SYS_CLOSE = 9;
|
||||||
|
static constexpr uint64_t SYS_READDIR = 10;
|
||||||
|
static constexpr uint64_t SYS_ALLOC = 11;
|
||||||
|
static constexpr uint64_t SYS_FREE = 12;
|
||||||
|
static constexpr uint64_t SYS_GETTICKS = 13;
|
||||||
|
static constexpr uint64_t SYS_GETMILLISECONDS = 14;
|
||||||
|
static constexpr uint64_t SYS_GETINFO = 15;
|
||||||
|
static constexpr uint64_t SYS_ISKEYAVAILABLE = 16;
|
||||||
|
static constexpr uint64_t SYS_GETKEY = 17;
|
||||||
|
static constexpr uint64_t SYS_GETCHAR = 18;
|
||||||
|
static constexpr uint64_t SYS_PING = 19;
|
||||||
|
static constexpr uint64_t SYS_SPAWN = 20;
|
||||||
|
static constexpr uint64_t SYS_FBINFO = 21;
|
||||||
|
static constexpr uint64_t SYS_FBMAP = 22;
|
||||||
|
static constexpr uint64_t SYS_WAITPID = 23;
|
||||||
|
static constexpr uint64_t SYS_TERMSIZE = 24;
|
||||||
|
static constexpr uint64_t SYS_GETARGS = 25;
|
||||||
|
static constexpr uint64_t SYS_RESET = 26;
|
||||||
|
static constexpr uint64_t SYS_SHUTDOWN = 27;
|
||||||
|
static constexpr uint64_t SYS_GETTIME = 28;
|
||||||
|
static constexpr uint64_t SYS_SOCKET = 29;
|
||||||
|
static constexpr uint64_t SYS_CONNECT = 30;
|
||||||
|
static constexpr uint64_t SYS_BIND = 31;
|
||||||
|
static constexpr uint64_t SYS_LISTEN = 32;
|
||||||
|
static constexpr uint64_t SYS_ACCEPT = 33;
|
||||||
|
static constexpr uint64_t SYS_SEND = 34;
|
||||||
|
static constexpr uint64_t SYS_RECV = 35;
|
||||||
|
static constexpr uint64_t SYS_CLOSESOCK = 36;
|
||||||
|
static constexpr uint64_t SYS_GETNETCFG = 37;
|
||||||
|
static constexpr uint64_t SYS_SETNETCFG = 38;
|
||||||
|
static constexpr uint64_t SYS_SENDTO = 39;
|
||||||
|
static constexpr uint64_t SYS_RECVFROM = 40;
|
||||||
|
static constexpr uint64_t SYS_FWRITE = 41;
|
||||||
|
static constexpr uint64_t SYS_FCREATE = 42;
|
||||||
|
static constexpr uint64_t SYS_FDELETE = 77;
|
||||||
|
static constexpr uint64_t SYS_FMKDIR = 78;
|
||||||
|
static constexpr uint64_t SYS_DRIVELIST = 79;
|
||||||
|
static constexpr uint64_t SYS_TERMSCALE = 43;
|
||||||
|
static constexpr uint64_t SYS_RESOLVE = 44;
|
||||||
|
static constexpr uint64_t SYS_GETRANDOM = 45;
|
||||||
|
static constexpr uint64_t SYS_KLOG = 46;
|
||||||
|
static constexpr uint64_t SYS_MOUSESTATE = 47;
|
||||||
|
static constexpr uint64_t SYS_SETMOUSEBOUNDS = 48;
|
||||||
|
static constexpr uint64_t SYS_SPAWN_REDIR = 49;
|
||||||
|
static constexpr uint64_t SYS_CHILDIO_READ = 50;
|
||||||
|
static constexpr uint64_t SYS_CHILDIO_WRITE = 51;
|
||||||
|
static constexpr uint64_t SYS_CHILDIO_WRITEKEY = 52;
|
||||||
|
static constexpr uint64_t SYS_CHILDIO_SETTERMSZ = 53;
|
||||||
|
|
||||||
|
// Window server syscalls
|
||||||
|
static constexpr uint64_t SYS_WINCREATE = 54;
|
||||||
|
static constexpr uint64_t SYS_WINDESTROY = 55;
|
||||||
|
static constexpr uint64_t SYS_WINPRESENT = 56;
|
||||||
|
static constexpr uint64_t SYS_WINPOLL = 57;
|
||||||
|
static constexpr uint64_t SYS_WINENUM = 58;
|
||||||
|
static constexpr uint64_t SYS_WINMAP = 59;
|
||||||
|
static constexpr uint64_t SYS_WINSENDEVENT = 60;
|
||||||
|
static constexpr uint64_t SYS_WINRESIZE = 64;
|
||||||
|
static constexpr uint64_t SYS_WINSETSCALE = 65;
|
||||||
|
static constexpr uint64_t SYS_WINGETSCALE = 66;
|
||||||
|
static constexpr uint64_t SYS_WINSETCURSOR = 68;
|
||||||
|
|
||||||
|
// Process management syscalls
|
||||||
|
static constexpr uint64_t SYS_PROCLIST = 61;
|
||||||
|
static constexpr uint64_t SYS_KILL = 62;
|
||||||
|
static constexpr uint64_t SYS_DEVLIST = 63;
|
||||||
|
static constexpr uint64_t SYS_DISKINFO = 69;
|
||||||
|
|
||||||
|
// Kernel introspection syscalls
|
||||||
|
static constexpr uint64_t SYS_MEMSTATS = 67;
|
||||||
|
|
||||||
|
// Storage / partition syscalls
|
||||||
|
static constexpr uint64_t SYS_PARTLIST = 70;
|
||||||
|
static constexpr uint64_t SYS_DISKREAD = 71;
|
||||||
|
static constexpr uint64_t SYS_DISKWRITE = 72;
|
||||||
|
static constexpr uint64_t SYS_GPTINIT = 73;
|
||||||
|
static constexpr uint64_t SYS_GPTADD = 74;
|
||||||
|
static constexpr uint64_t SYS_FSMOUNT = 75;
|
||||||
|
static constexpr uint64_t SYS_FSFORMAT = 76;
|
||||||
|
|
||||||
|
// Audio syscalls
|
||||||
|
static constexpr uint64_t SYS_AUDIOOPEN = 80;
|
||||||
|
static constexpr uint64_t SYS_AUDIOCLOSE = 81;
|
||||||
|
static constexpr uint64_t SYS_AUDIOWRITE = 82;
|
||||||
|
static constexpr uint64_t SYS_AUDIOCTL = 83;
|
||||||
|
|
||||||
|
// Bluetooth syscalls
|
||||||
|
static constexpr uint64_t SYS_BTSCAN = 84;
|
||||||
|
static constexpr uint64_t SYS_BTCONNECT = 85;
|
||||||
|
static constexpr uint64_t SYS_BTDISCONNECT = 86;
|
||||||
|
static constexpr uint64_t SYS_BTLIST = 87;
|
||||||
|
static constexpr uint64_t SYS_BTINFO = 88;
|
||||||
|
|
||||||
|
// Audio control commands (for SYS_AUDIOCTL)
|
||||||
|
static constexpr int AUDIO_CTL_SET_VOLUME = 0;
|
||||||
|
static constexpr int AUDIO_CTL_GET_VOLUME = 1;
|
||||||
|
static constexpr int AUDIO_CTL_GET_POS = 2;
|
||||||
|
static constexpr int AUDIO_CTL_PAUSE = 3;
|
||||||
|
static constexpr int AUDIO_CTL_GET_OUTPUT = 4; // 0=HDA, 1=Bluetooth
|
||||||
|
static constexpr int AUDIO_CTL_SET_OUTPUT = 5; // Switch audio output
|
||||||
|
static constexpr int AUDIO_CTL_BT_STATUS = 6; // Get Bluetooth connection status
|
||||||
|
|
||||||
|
static constexpr int SOCK_TCP = 1;
|
||||||
|
static constexpr int SOCK_UDP = 2;
|
||||||
|
|
||||||
|
struct NetCfg {
|
||||||
|
uint32_t ipAddress; // network byte order
|
||||||
|
uint32_t subnetMask; // network byte order
|
||||||
|
uint32_t gateway; // network byte order
|
||||||
|
uint8_t macAddress[6];
|
||||||
|
uint8_t _pad[2];
|
||||||
|
uint32_t dnsServer; // network byte order
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DateTime {
|
||||||
|
uint16_t Year;
|
||||||
|
uint8_t Month;
|
||||||
|
uint8_t Day;
|
||||||
|
uint8_t Hour;
|
||||||
|
uint8_t Minute;
|
||||||
|
uint8_t Second;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FbInfo {
|
||||||
|
uint64_t width;
|
||||||
|
uint64_t height;
|
||||||
|
uint64_t pitch; // bytes per scanline
|
||||||
|
uint64_t bpp; // bits per pixel (32)
|
||||||
|
uint64_t userAddr; // filled by SYS_FBMAP (0 until mapped)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SysInfo {
|
||||||
|
char osName[32];
|
||||||
|
char osVersion[32];
|
||||||
|
uint32_t apiVersion;
|
||||||
|
uint32_t maxProcesses;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyEvent {
|
||||||
|
uint8_t scancode;
|
||||||
|
char ascii;
|
||||||
|
bool pressed;
|
||||||
|
bool shift;
|
||||||
|
bool ctrl;
|
||||||
|
bool alt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MouseState {
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int32_t scrollDelta;
|
||||||
|
uint8_t buttons;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Window server shared types
|
||||||
|
struct WinEvent {
|
||||||
|
uint8_t type; // 0=key, 1=mouse, 2=resize, 3=close, 4=scale
|
||||||
|
uint8_t _pad[3];
|
||||||
|
union {
|
||||||
|
KeyEvent key;
|
||||||
|
struct { int32_t x, y, scroll; uint8_t buttons, prev_buttons; } mouse;
|
||||||
|
struct { int32_t w, h; } resize;
|
||||||
|
struct { int32_t scale; } scale;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WinInfo {
|
||||||
|
int32_t id;
|
||||||
|
int32_t ownerPid;
|
||||||
|
char title[64];
|
||||||
|
int32_t width, height;
|
||||||
|
uint8_t dirty;
|
||||||
|
uint8_t cursor; // 0=arrow, 1=resize_h, 2=resize_v
|
||||||
|
uint8_t _pad2[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WinCreateResult {
|
||||||
|
int32_t id; // -1 on failure
|
||||||
|
uint32_t _pad;
|
||||||
|
uint64_t pixelVa; // VA of pixel buffer in caller's address space
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DevInfo {
|
||||||
|
uint8_t category; // 0=CPU, 1=Interrupt, 2=Timer, 3=Input, 4=USB, 5=Network, 6=Display, 7=Storage, 8=PCI
|
||||||
|
uint8_t _pad[3];
|
||||||
|
char name[48];
|
||||||
|
char detail[48];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DiskInfo {
|
||||||
|
uint8_t port; // block device index
|
||||||
|
uint8_t type; // 0=none, 1=SATA, 2=SATAPI, 3=NVMe
|
||||||
|
uint8_t sataGen; // SATA gen (1/2/3)
|
||||||
|
uint8_t _pad0;
|
||||||
|
uint64_t sectorCount; // Total user-addressable sectors
|
||||||
|
uint16_t sectorSizeLog; // Logical sector size (bytes)
|
||||||
|
uint16_t sectorSizePhys; // Physical sector size (bytes)
|
||||||
|
uint16_t rpm; // 0=unknown, 1=SSD, else RPM
|
||||||
|
uint16_t ncqDepth; // 0 if no NCQ
|
||||||
|
uint8_t supportsLba48;
|
||||||
|
uint8_t supportsNcq;
|
||||||
|
uint8_t supportsTrim;
|
||||||
|
uint8_t supportsSmart;
|
||||||
|
uint8_t supportsWriteCache;
|
||||||
|
uint8_t supportsReadAhead;
|
||||||
|
uint8_t _pad1[2];
|
||||||
|
char model[41];
|
||||||
|
char serial[21];
|
||||||
|
char firmware[9];
|
||||||
|
char _pad2[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PartGuid {
|
||||||
|
uint32_t Data1;
|
||||||
|
uint16_t Data2;
|
||||||
|
uint16_t Data3;
|
||||||
|
uint8_t Data4[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PartInfo {
|
||||||
|
int32_t blockDev; // block device index
|
||||||
|
uint32_t _pad0;
|
||||||
|
uint64_t startLba;
|
||||||
|
uint64_t endLba;
|
||||||
|
uint64_t sectorCount;
|
||||||
|
PartGuid typeGuid;
|
||||||
|
PartGuid uniqueGuid;
|
||||||
|
uint64_t attributes;
|
||||||
|
char name[72]; // ASCII partition name
|
||||||
|
char typeName[24]; // human-readable type name
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GptAddParams {
|
||||||
|
int32_t blockDev;
|
||||||
|
uint32_t _pad0;
|
||||||
|
uint64_t startLba; // 0 = auto (fill largest free region)
|
||||||
|
uint64_t endLba; // 0 = auto
|
||||||
|
PartGuid typeGuid;
|
||||||
|
char name[72];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filesystem type IDs for SYS_FSFORMAT
|
||||||
|
static constexpr int FS_TYPE_FAT32 = 1;
|
||||||
|
static constexpr int FS_TYPE_EXT2 = 2;
|
||||||
|
|
||||||
|
struct FsFormatParams {
|
||||||
|
int32_t partIndex; // global partition index
|
||||||
|
int32_t fsType; // FS_TYPE_FAT32, etc.
|
||||||
|
char label[32]; // volume label
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bluetooth scan result (returned by SYS_BTSCAN)
|
||||||
|
struct BtScanResult {
|
||||||
|
uint8_t bdAddr[6];
|
||||||
|
uint8_t _pad[2];
|
||||||
|
uint32_t classOfDevice;
|
||||||
|
int8_t rssi;
|
||||||
|
uint8_t _pad2[3];
|
||||||
|
char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bluetooth connected device info (returned by SYS_BTLIST)
|
||||||
|
struct BtDevInfo {
|
||||||
|
uint8_t bdAddr[6];
|
||||||
|
uint8_t connected;
|
||||||
|
uint8_t encrypted;
|
||||||
|
uint16_t handle;
|
||||||
|
uint8_t linkType;
|
||||||
|
uint8_t _pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bluetooth adapter info (returned by SYS_BTINFO)
|
||||||
|
struct BtAdapterInfo {
|
||||||
|
uint8_t bdAddr[6];
|
||||||
|
uint8_t initialized;
|
||||||
|
uint8_t scanning;
|
||||||
|
char name[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ProcInfo {
|
||||||
|
int32_t pid;
|
||||||
|
int32_t parentPid;
|
||||||
|
uint8_t state; // 0=Free, 1=Ready, 2=Running, 3=Terminated
|
||||||
|
uint8_t _pad[3];
|
||||||
|
char name[64];
|
||||||
|
uint64_t heapUsed; // heapNext - UserHeapBase (bytes)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemStats {
|
||||||
|
uint64_t totalBytes;
|
||||||
|
uint64_t freeBytes;
|
||||||
|
uint64_t usedBytes;
|
||||||
|
uint64_t pageSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/* Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _X86GPRINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <adxintrin.h> directly; include <x86gprintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _ADXINTRIN_H_INCLUDED
|
||||||
|
#define _ADXINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
extern __inline unsigned char
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_subborrow_u32 (unsigned char __CF, unsigned int __X,
|
||||||
|
unsigned int __Y, unsigned int *__P)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_sbb_u32 (__CF, __X, __Y, __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline unsigned char
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_addcarry_u32 (unsigned char __CF, unsigned int __X,
|
||||||
|
unsigned int __Y, unsigned int *__P)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline unsigned char
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_addcarryx_u32 (unsigned char __CF, unsigned int __X,
|
||||||
|
unsigned int __Y, unsigned int *__P)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
extern __inline unsigned char
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_subborrow_u64 (unsigned char __CF, unsigned long long __X,
|
||||||
|
unsigned long long __Y, unsigned long long *__P)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_sbb_u64 (__CF, __X, __Y, __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline unsigned char
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_addcarry_u64 (unsigned char __CF, unsigned long long __X,
|
||||||
|
unsigned long long __Y, unsigned long long *__P)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline unsigned char
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_addcarryx_u64 (unsigned char __CF, unsigned long long __X,
|
||||||
|
unsigned long long __Y, unsigned long long *__P)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ADXINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// <algorithm> -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
// permissions described in the GCC Runtime Library Exception, version
|
||||||
|
// 3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License and
|
||||||
|
// a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 1994
|
||||||
|
* Hewlett-Packard Company
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute and sell this software
|
||||||
|
* and its documentation for any purpose is hereby granted without fee,
|
||||||
|
* provided that the above copyright notice appear in all copies and
|
||||||
|
* that both that copyright notice and this permission notice appear
|
||||||
|
* in supporting documentation. Hewlett-Packard Company makes no
|
||||||
|
* representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996,1997
|
||||||
|
* Silicon Graphics Computer Systems, Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute and sell this software
|
||||||
|
* and its documentation for any purpose is hereby granted without fee,
|
||||||
|
* provided that the above copyright notice appear in all copies and
|
||||||
|
* that both that copyright notice and this permission notice appear
|
||||||
|
* in supporting documentation. Silicon Graphics makes no
|
||||||
|
* representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file include/algorithm
|
||||||
|
* This is a Standard C++ Library header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GLIBCXX_ALGORITHM
|
||||||
|
#define _GLIBCXX_ALGORITHM 1
|
||||||
|
|
||||||
|
#pragma GCC system_header
|
||||||
|
|
||||||
|
#include <bits/stl_algobase.h>
|
||||||
|
#include <bits/stl_algo.h>
|
||||||
|
#if __cplusplus > 201703L
|
||||||
|
# include <bits/ranges_algo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __glibcxx_want_clamp
|
||||||
|
#define __glibcxx_want_constexpr_algorithms
|
||||||
|
#define __glibcxx_want_freestanding_algorithm
|
||||||
|
#define __glibcxx_want_parallel_algorithm
|
||||||
|
#define __glibcxx_want_ranges_contains
|
||||||
|
#define __glibcxx_want_ranges_find_last
|
||||||
|
#define __glibcxx_want_ranges_fold
|
||||||
|
#define __glibcxx_want_robust_nonmodifying_seq_ops
|
||||||
|
#define __glibcxx_want_sample
|
||||||
|
#define __glibcxx_want_shift
|
||||||
|
#include <bits/version.h>
|
||||||
|
|
||||||
|
#if __cpp_lib_parallel_algorithm // C++ >= 17 && HOSTED
|
||||||
|
// Parallel STL algorithms
|
||||||
|
# if _PSTL_EXECUTION_POLICIES_DEFINED
|
||||||
|
// If <execution> has already been included, pull in implementations
|
||||||
|
# include <pstl/glue_algorithm_impl.h>
|
||||||
|
# else
|
||||||
|
// Otherwise just pull in forward declarations
|
||||||
|
# include <pstl/glue_algorithm_defs.h>
|
||||||
|
# define _PSTL_ALGORITHM_FORWARD_DECLARED 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _GLIBCXX_PARALLEL
|
||||||
|
# include <parallel/algorithm>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _GLIBCXX_ALGORITHM */
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/* Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* Implemented from the specification included in the AMD Programmers
|
||||||
|
Manual Update, version 2.x */
|
||||||
|
|
||||||
|
#ifndef _AMMINTRIN_H_INCLUDED
|
||||||
|
#define _AMMINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
/* We need definitions from the SSE3, SSE2 and SSE header files*/
|
||||||
|
#include <pmmintrin.h>
|
||||||
|
|
||||||
|
#ifndef __SSE4A__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("sse4a")
|
||||||
|
#define __DISABLE_SSE4A__
|
||||||
|
#endif /* __SSE4A__ */
|
||||||
|
|
||||||
|
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_stream_sd (double * __P, __m128d __Y)
|
||||||
|
{
|
||||||
|
__builtin_ia32_movntsd (__P, (__v2df) __Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_stream_ss (float * __P, __m128 __Y)
|
||||||
|
{
|
||||||
|
__builtin_ia32_movntss (__P, (__v4sf) __Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_extract_si64 (__m128i __X, __m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_extrq ((__v2di) __X, (__v16qi) __Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __OPTIMIZE__
|
||||||
|
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_extracti_si64 (__m128i __X, unsigned const int __I, unsigned const int __L)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_extrqi ((__v2di) __X, __I, __L);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define _mm_extracti_si64(X, I, L) \
|
||||||
|
((__m128i) __builtin_ia32_extrqi ((__v2di)(__m128i)(X), \
|
||||||
|
(unsigned int)(I), (unsigned int)(L)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_insert_si64 (__m128i __X,__m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_insertq ((__v2di)__X, (__v2di)__Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __OPTIMIZE__
|
||||||
|
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_inserti_si64(__m128i __X, __m128i __Y, unsigned const int __I, unsigned const int __L)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_insertqi ((__v2di)__X, (__v2di)__Y, __I, __L);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define _mm_inserti_si64(X, Y, I, L) \
|
||||||
|
((__m128i) __builtin_ia32_insertqi ((__v2di)(__m128i)(X), \
|
||||||
|
(__v2di)(__m128i)(Y), \
|
||||||
|
(unsigned int)(I), (unsigned int)(L)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_SSE4A__
|
||||||
|
#undef __DISABLE_SSE4A__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_SSE4A__ */
|
||||||
|
|
||||||
|
#endif /* _AMMINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <amxbf16intrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AMXBF16INTRIN_H_INCLUDED
|
||||||
|
#define _AMXBF16INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AMX_BF16__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("amx-bf16")
|
||||||
|
#define __DISABLE_AMX_BF16__
|
||||||
|
#endif /* __AMX_BF16__ */
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define _tile_dpbf16ps_internal(dst,src1,src2) \
|
||||||
|
__asm__ volatile\
|
||||||
|
("{tdpbf16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpbf16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
|
||||||
|
|
||||||
|
#define _tile_dpbf16ps(dst,src1,src2) \
|
||||||
|
_tile_dpbf16ps_internal (dst, src1, src2)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AMX_BF16__
|
||||||
|
#undef __DISABLE_AMX_BF16__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AMX_BF16__ */
|
||||||
|
|
||||||
|
#endif /* _AMXBF16INTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <amxcomplexintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AMXCOMPLEXINTRIN_H_INCLUDED
|
||||||
|
#define _AMXCOMPLEXINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AMX_COMPLEX__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("amx-complex")
|
||||||
|
#define __DISABLE_AMX_COMPLEX__
|
||||||
|
#endif /* __AMX_COMPLEX__ */
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define _tile_cmmimfp16ps_internal(src1_dst,src2,src3) \
|
||||||
|
__asm__ volatile\
|
||||||
|
("{tcmmimfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmimfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::)
|
||||||
|
|
||||||
|
#define _tile_cmmrlfp16ps_internal(src1_dst,src2,src3) \
|
||||||
|
__asm__ volatile\
|
||||||
|
("{tcmmrlfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmrlfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::)
|
||||||
|
|
||||||
|
#define _tile_cmmimfp16ps(src1_dst,src2,src3) \
|
||||||
|
_tile_cmmimfp16ps_internal (src1_dst, src2, src3)
|
||||||
|
|
||||||
|
#define _tile_cmmrlfp16ps(src1_dst,src2,src3) \
|
||||||
|
_tile_cmmrlfp16ps_internal (src1_dst, src2, src3)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AMX_COMPLEX__
|
||||||
|
#undef __DISABLE_AMX_COMPLEX__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AMX_COMPLEX__ */
|
||||||
|
|
||||||
|
#endif /* _AMXCOMPLEXINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <amxfp16intrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AMXFP16INTRIN_H_INCLUDED
|
||||||
|
#define _AMXFP16INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define _tile_dpfp16ps_internal(dst,src1,src2) \
|
||||||
|
__asm__ volatile \
|
||||||
|
("{tdpfp16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpfp16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
|
||||||
|
|
||||||
|
#define _tile_dpfp16ps(dst,src1,src2) \
|
||||||
|
_tile_dpfp16ps_internal (dst,src1,src2)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AMX_FP16__
|
||||||
|
#undef __DISABLE_AMX_FP16__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AMX_FP16__ */
|
||||||
|
|
||||||
|
#endif /* _AMXFP16INTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <amxint8intrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AMXINT8INTRIN_H_INCLUDED
|
||||||
|
#define _AMXINT8INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AMX_INT8__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("amx-int8")
|
||||||
|
#define __DISABLE_AMX_INT8__
|
||||||
|
#endif /* __AMX_INT8__ */
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
#define _tile_int8_dp_internal(name,dst,src1,src2) \
|
||||||
|
__asm__ volatile \
|
||||||
|
("{"#name"\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|"#name"\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
|
||||||
|
|
||||||
|
#define _tile_dpbssd(dst,src1,src2) \
|
||||||
|
_tile_int8_dp_internal (tdpbssd, dst, src1, src2)
|
||||||
|
|
||||||
|
#define _tile_dpbsud(dst,src1,src2) \
|
||||||
|
_tile_int8_dp_internal (tdpbsud, dst, src1, src2)
|
||||||
|
|
||||||
|
#define _tile_dpbusd(dst,src1,src2) \
|
||||||
|
_tile_int8_dp_internal (tdpbusd, dst, src1, src2)
|
||||||
|
|
||||||
|
#define _tile_dpbuud(dst,src1,src2) \
|
||||||
|
_tile_int8_dp_internal (tdpbuud, dst, src1, src2)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AMX_INT8__
|
||||||
|
#undef __DISABLE_AMX_INT8__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AMX_INT8__ */
|
||||||
|
|
||||||
|
#endif /* _AMXINT8INTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <amxtileintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AMXTILEINTRIN_H_INCLUDED
|
||||||
|
#define _AMXTILEINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AMX_TILE__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("amx-tile")
|
||||||
|
#define __DISABLE_AMX_TILE__
|
||||||
|
#endif /* __AMX_TILE__ */
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_tile_loadconfig (const void *__config)
|
||||||
|
{
|
||||||
|
__builtin_ia32_ldtilecfg (__config);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_tile_storeconfig (void *__config)
|
||||||
|
{
|
||||||
|
__builtin_ia32_sttilecfg (__config);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_tile_release (void)
|
||||||
|
{
|
||||||
|
__asm__ volatile ("tilerelease" ::);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _tile_loadd(dst,base,stride) \
|
||||||
|
_tile_loadd_internal (dst, base, stride)
|
||||||
|
|
||||||
|
#define _tile_loadd_internal(dst,base,stride) \
|
||||||
|
__asm__ volatile \
|
||||||
|
("{tileloadd\t(%0,%1,1), %%tmm"#dst"|tileloadd\t%%tmm"#dst", [%0+%1*1]}" \
|
||||||
|
:: "r" ((const void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)))
|
||||||
|
|
||||||
|
#define _tile_stream_loadd(dst,base,stride) \
|
||||||
|
_tile_stream_loadd_internal (dst, base, stride)
|
||||||
|
|
||||||
|
#define _tile_stream_loadd_internal(dst,base,stride) \
|
||||||
|
__asm__ volatile \
|
||||||
|
("{tileloaddt1\t(%0,%1,1), %%tmm"#dst"|tileloaddt1\t%%tmm"#dst", [%0+%1*1]}" \
|
||||||
|
:: "r" ((const void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)))
|
||||||
|
|
||||||
|
#define _tile_stored(dst,base,stride) \
|
||||||
|
_tile_stored_internal (dst, base, stride)
|
||||||
|
|
||||||
|
#define _tile_stored_internal(src,base,stride) \
|
||||||
|
__asm__ volatile \
|
||||||
|
("{tilestored\t%%tmm"#src", (%0,%1,1)|tilestored\t[%0+%1*1], %%tmm"#src"}" \
|
||||||
|
:: "r" ((void*) (base)), "r" ((__PTRDIFF_TYPE__) (stride)) \
|
||||||
|
: "memory")
|
||||||
|
|
||||||
|
#define _tile_zero(dst) \
|
||||||
|
_tile_zero_internal (dst)
|
||||||
|
|
||||||
|
#define _tile_zero_internal(dst) \
|
||||||
|
__asm__ volatile \
|
||||||
|
("tilezero\t%%tmm"#dst ::)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AMX_TILE__
|
||||||
|
#undef __DISABLE_AMX_TILE__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AMX_TILE__ */
|
||||||
|
|
||||||
|
#endif /* _AMXTILEINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,519 @@
|
|||||||
|
// <array> -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
// permissions described in the GCC Runtime Library Exception, version
|
||||||
|
// 3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License and
|
||||||
|
// a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/** @file include/array
|
||||||
|
* This is a Standard C++ Library header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GLIBCXX_ARRAY
|
||||||
|
#define _GLIBCXX_ARRAY 1
|
||||||
|
|
||||||
|
#pragma GCC system_header
|
||||||
|
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
# include <bits/c++0x_warning.h>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <compare>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <bits/functexcept.h>
|
||||||
|
#include <bits/stl_algobase.h>
|
||||||
|
#include <bits/range_access.h> // std::begin, std::end etc.
|
||||||
|
#include <bits/utility.h> // std::index_sequence, std::tuple_size
|
||||||
|
#include <debug/assertions.h>
|
||||||
|
|
||||||
|
#define __glibcxx_want_array_constexpr
|
||||||
|
#define __glibcxx_want_freestanding_array
|
||||||
|
#define __glibcxx_want_nonmember_container_access
|
||||||
|
#define __glibcxx_want_to_array
|
||||||
|
#include <bits/version.h>
|
||||||
|
|
||||||
|
namespace std _GLIBCXX_VISIBILITY(default)
|
||||||
|
{
|
||||||
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
struct __array_traits
|
||||||
|
{
|
||||||
|
using _Type = _Tp[_Nm];
|
||||||
|
using _Is_swappable = __is_swappable<_Tp>;
|
||||||
|
using _Is_nothrow_swappable = __is_nothrow_swappable<_Tp>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
struct __array_traits<_Tp, 0>
|
||||||
|
{
|
||||||
|
// Empty type used instead of _Tp[0] for std::array<_Tp, 0>.
|
||||||
|
struct _Type
|
||||||
|
{
|
||||||
|
// Indexing is undefined.
|
||||||
|
__attribute__((__always_inline__,__noreturn__))
|
||||||
|
_Tp& operator[](size_t) const noexcept { __builtin_trap(); }
|
||||||
|
|
||||||
|
// Conversion to a pointer produces a null pointer.
|
||||||
|
__attribute__((__always_inline__))
|
||||||
|
constexpr explicit operator _Tp*() const noexcept { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using _Is_swappable = true_type;
|
||||||
|
using _Is_nothrow_swappable = true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A standard container for storing a fixed size sequence of elements.
|
||||||
|
*
|
||||||
|
* @ingroup sequences
|
||||||
|
*
|
||||||
|
* Meets the requirements of a <a href="tables.html#65">container</a>, a
|
||||||
|
* <a href="tables.html#66">reversible container</a>, and a
|
||||||
|
* <a href="tables.html#67">sequence</a>.
|
||||||
|
*
|
||||||
|
* Sets support random access iterators.
|
||||||
|
*
|
||||||
|
* @tparam Tp Type of element. Required to be a complete type.
|
||||||
|
* @tparam Nm Number of elements.
|
||||||
|
*/
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
struct array
|
||||||
|
{
|
||||||
|
typedef _Tp value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef const value_type* const_pointer;
|
||||||
|
typedef value_type& reference;
|
||||||
|
typedef const value_type& const_reference;
|
||||||
|
typedef value_type* iterator;
|
||||||
|
typedef const value_type* const_iterator;
|
||||||
|
typedef std::size_t size_type;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||||
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
|
// Support for zero-sized arrays mandatory.
|
||||||
|
typename __array_traits<_Tp, _Nm>::_Type _M_elems;
|
||||||
|
|
||||||
|
// No explicit construct/copy/destroy for aggregate type.
|
||||||
|
|
||||||
|
// DR 776.
|
||||||
|
_GLIBCXX20_CONSTEXPR void
|
||||||
|
fill(const value_type& __u)
|
||||||
|
{ std::fill_n(begin(), size(), __u); }
|
||||||
|
|
||||||
|
_GLIBCXX20_CONSTEXPR void
|
||||||
|
swap(array& __other)
|
||||||
|
noexcept(__array_traits<_Tp, _Nm>::_Is_nothrow_swappable::value)
|
||||||
|
{ std::swap_ranges(begin(), end(), __other.begin()); }
|
||||||
|
|
||||||
|
// Iterators.
|
||||||
|
[[__gnu__::__const__, __nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR iterator
|
||||||
|
begin() noexcept
|
||||||
|
{ return iterator(data()); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_iterator
|
||||||
|
begin() const noexcept
|
||||||
|
{ return const_iterator(data()); }
|
||||||
|
|
||||||
|
[[__gnu__::__const__, __nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR iterator
|
||||||
|
end() noexcept
|
||||||
|
{ return iterator(data() + _Nm); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_iterator
|
||||||
|
end() const noexcept
|
||||||
|
{ return const_iterator(data() + _Nm); }
|
||||||
|
|
||||||
|
[[__gnu__::__const__, __nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR reverse_iterator
|
||||||
|
rbegin() noexcept
|
||||||
|
{ return reverse_iterator(end()); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||||
|
rbegin() const noexcept
|
||||||
|
{ return const_reverse_iterator(end()); }
|
||||||
|
|
||||||
|
[[__gnu__::__const__, __nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR reverse_iterator
|
||||||
|
rend() noexcept
|
||||||
|
{ return reverse_iterator(begin()); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||||
|
rend() const noexcept
|
||||||
|
{ return const_reverse_iterator(begin()); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_iterator
|
||||||
|
cbegin() const noexcept
|
||||||
|
{ return const_iterator(data()); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_iterator
|
||||||
|
cend() const noexcept
|
||||||
|
{ return const_iterator(data() + _Nm); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||||
|
crbegin() const noexcept
|
||||||
|
{ return const_reverse_iterator(end()); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_reverse_iterator
|
||||||
|
crend() const noexcept
|
||||||
|
{ return const_reverse_iterator(begin()); }
|
||||||
|
|
||||||
|
// Capacity.
|
||||||
|
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||||
|
constexpr size_type
|
||||||
|
size() const noexcept { return _Nm; }
|
||||||
|
|
||||||
|
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||||
|
constexpr size_type
|
||||||
|
max_size() const noexcept { return _Nm; }
|
||||||
|
|
||||||
|
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||||
|
constexpr bool
|
||||||
|
empty() const noexcept { return size() == 0; }
|
||||||
|
|
||||||
|
// Element access.
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR reference
|
||||||
|
operator[](size_type __n) noexcept
|
||||||
|
{
|
||||||
|
__glibcxx_requires_subscript(__n);
|
||||||
|
return _M_elems[__n];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr const_reference
|
||||||
|
operator[](size_type __n) const noexcept
|
||||||
|
{
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
__glibcxx_requires_subscript(__n);
|
||||||
|
#endif
|
||||||
|
return _M_elems[__n];
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLIBCXX17_CONSTEXPR reference
|
||||||
|
at(size_type __n)
|
||||||
|
{
|
||||||
|
if (__n >= _Nm)
|
||||||
|
std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
|
||||||
|
">= _Nm (which is %zu)"),
|
||||||
|
__n, _Nm);
|
||||||
|
return _M_elems[__n];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_reference
|
||||||
|
at(size_type __n) const
|
||||||
|
{
|
||||||
|
// Result of conditional expression must be an lvalue so use
|
||||||
|
// boolean ? lvalue : (throw-expr, lvalue)
|
||||||
|
return __n < _Nm ? _M_elems[__n]
|
||||||
|
: (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
|
||||||
|
">= _Nm (which is %zu)"),
|
||||||
|
__n, _Nm),
|
||||||
|
_M_elems[__n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR reference
|
||||||
|
front() noexcept
|
||||||
|
{
|
||||||
|
__glibcxx_requires_nonempty();
|
||||||
|
return _M_elems[(size_type)0];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr const_reference
|
||||||
|
front() const noexcept
|
||||||
|
{
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
__glibcxx_requires_nonempty();
|
||||||
|
#endif
|
||||||
|
return _M_elems[(size_type)0];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR reference
|
||||||
|
back() noexcept
|
||||||
|
{
|
||||||
|
__glibcxx_requires_nonempty();
|
||||||
|
return _M_elems[_Nm - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr const_reference
|
||||||
|
back() const noexcept
|
||||||
|
{
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
__glibcxx_requires_nonempty();
|
||||||
|
#endif
|
||||||
|
return _M_elems[_Nm - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[__nodiscard__, __gnu__::__const__, __gnu__::__always_inline__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR pointer
|
||||||
|
data() noexcept
|
||||||
|
{ return static_cast<pointer>(_M_elems); }
|
||||||
|
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX17_CONSTEXPR const_pointer
|
||||||
|
data() const noexcept
|
||||||
|
{ return static_cast<const_pointer>(_M_elems); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#if __cpp_deduction_guides >= 201606
|
||||||
|
template<typename _Tp, typename... _Up>
|
||||||
|
array(_Tp, _Up...)
|
||||||
|
-> array<enable_if_t<(is_same_v<_Tp, _Up> && ...), _Tp>,
|
||||||
|
1 + sizeof...(_Up)>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Array comparisons.
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline bool
|
||||||
|
operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||||
|
{ return std::equal(__one.begin(), __one.end(), __two.begin()); }
|
||||||
|
|
||||||
|
#if __cpp_lib_three_way_comparison // C++ >= 20 && lib_concepts
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr __detail::__synth3way_t<_Tp>
|
||||||
|
operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||||
|
{
|
||||||
|
if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value)
|
||||||
|
if (!std::__is_constant_evaluated())
|
||||||
|
{
|
||||||
|
constexpr size_t __n = _Nm * sizeof(_Tp);
|
||||||
|
return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||||
|
{
|
||||||
|
auto __c = __detail::__synth3way(__a[__i], __b[__i]);
|
||||||
|
if (__c != 0)
|
||||||
|
return __c;
|
||||||
|
}
|
||||||
|
return strong_ordering::equal;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline bool
|
||||||
|
operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||||
|
{ return !(__one == __two); }
|
||||||
|
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline bool
|
||||||
|
operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||||
|
{
|
||||||
|
return std::lexicographical_compare(__a.begin(), __a.end(),
|
||||||
|
__b.begin(), __b.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline bool
|
||||||
|
operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||||
|
{ return __two < __one; }
|
||||||
|
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline bool
|
||||||
|
operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||||
|
{ return !(__one > __two); }
|
||||||
|
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline bool
|
||||||
|
operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two)
|
||||||
|
{ return !(__one < __two); }
|
||||||
|
#endif // three_way_comparison && concepts
|
||||||
|
|
||||||
|
// Specialized algorithms.
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
_GLIBCXX20_CONSTEXPR
|
||||||
|
inline
|
||||||
|
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||||
|
// Constrained free swap overload, see p0185r1
|
||||||
|
__enable_if_t<__array_traits<_Tp, _Nm>::_Is_swappable::value>
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
#endif
|
||||||
|
swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
|
||||||
|
noexcept(noexcept(__one.swap(__two)))
|
||||||
|
{ __one.swap(__two); }
|
||||||
|
|
||||||
|
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||||
|
template<typename _Tp, std::size_t _Nm>
|
||||||
|
__enable_if_t<!__array_traits<_Tp, _Nm>::_Is_swappable::value>
|
||||||
|
swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr _Tp&
|
||||||
|
get(array<_Tp, _Nm>& __arr) noexcept
|
||||||
|
{
|
||||||
|
static_assert(_Int < _Nm, "array index is within bounds");
|
||||||
|
return __arr._M_elems[_Int];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr _Tp&&
|
||||||
|
get(array<_Tp, _Nm>&& __arr) noexcept
|
||||||
|
{
|
||||||
|
static_assert(_Int < _Nm, "array index is within bounds");
|
||||||
|
return std::move(std::get<_Int>(__arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr const _Tp&
|
||||||
|
get(const array<_Tp, _Nm>& __arr) noexcept
|
||||||
|
{
|
||||||
|
static_assert(_Int < _Nm, "array index is within bounds");
|
||||||
|
return __arr._M_elems[_Int];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t _Int, typename _Tp, std::size_t _Nm>
|
||||||
|
[[__nodiscard__]]
|
||||||
|
constexpr const _Tp&&
|
||||||
|
get(const array<_Tp, _Nm>&& __arr) noexcept
|
||||||
|
{
|
||||||
|
static_assert(_Int < _Nm, "array index is within bounds");
|
||||||
|
return std::move(std::get<_Int>(__arr));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cpp_lib_to_array // C++ >= 20 && __cpp_generic_lambdas >= 201707L
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr array<remove_cv_t<_Tp>, _Nm>
|
||||||
|
to_array(_Tp (&__a)[_Nm])
|
||||||
|
noexcept(is_nothrow_constructible_v<_Tp, _Tp&>)
|
||||||
|
{
|
||||||
|
static_assert(!is_array_v<_Tp>);
|
||||||
|
static_assert(is_constructible_v<_Tp, _Tp&>);
|
||||||
|
if constexpr (is_constructible_v<_Tp, _Tp&>)
|
||||||
|
{
|
||||||
|
if constexpr (is_trivially_copyable_v<_Tp>
|
||||||
|
&& is_trivially_default_constructible_v<_Tp>
|
||||||
|
&& is_copy_assignable_v<_Tp>)
|
||||||
|
{
|
||||||
|
array<remove_cv_t<_Tp>, _Nm> __arr;
|
||||||
|
if (!__is_constant_evaluated() && _Nm != 0)
|
||||||
|
__builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a));
|
||||||
|
else
|
||||||
|
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||||
|
__arr._M_elems[__i] = __a[__i];
|
||||||
|
return __arr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return [&__a]<size_t... _Idx>(index_sequence<_Idx...>) {
|
||||||
|
return array<remove_cv_t<_Tp>, _Nm>{{ __a[_Idx]... }};
|
||||||
|
}(make_index_sequence<_Nm>{});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
__builtin_unreachable(); // FIXME: see PR c++/91388
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr array<remove_cv_t<_Tp>, _Nm>
|
||||||
|
to_array(_Tp (&&__a)[_Nm])
|
||||||
|
noexcept(is_nothrow_move_constructible_v<_Tp>)
|
||||||
|
{
|
||||||
|
static_assert(!is_array_v<_Tp>);
|
||||||
|
static_assert(is_move_constructible_v<_Tp>);
|
||||||
|
if constexpr (is_move_constructible_v<_Tp>)
|
||||||
|
{
|
||||||
|
if constexpr (is_trivially_copyable_v<_Tp>
|
||||||
|
&& is_trivially_default_constructible_v<_Tp>
|
||||||
|
&& is_copy_assignable_v<_Tp>)
|
||||||
|
{
|
||||||
|
array<remove_cv_t<_Tp>, _Nm> __arr;
|
||||||
|
if (!__is_constant_evaluated() && _Nm != 0)
|
||||||
|
__builtin_memcpy((void*)__arr.data(), (void*)__a, sizeof(__a));
|
||||||
|
else
|
||||||
|
for (size_t __i = 0; __i < _Nm; ++__i)
|
||||||
|
__arr._M_elems[__i] = __a[__i];
|
||||||
|
return __arr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return [&__a]<size_t... _Idx>(index_sequence<_Idx...>) {
|
||||||
|
return array<remove_cv_t<_Tp>, _Nm>{{ std::move(__a[_Idx])... }};
|
||||||
|
}(make_index_sequence<_Nm>{});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
__builtin_unreachable(); // FIXME: see PR c++/91388
|
||||||
|
}
|
||||||
|
#endif // __cpp_lib_to_array
|
||||||
|
|
||||||
|
// Tuple interface to class template array.
|
||||||
|
|
||||||
|
/// Partial specialization for std::array
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
struct tuple_size<array<_Tp, _Nm>>
|
||||||
|
: public integral_constant<size_t, _Nm> { };
|
||||||
|
|
||||||
|
/// Partial specialization for std::array
|
||||||
|
template<size_t _Ind, typename _Tp, size_t _Nm>
|
||||||
|
struct tuple_element<_Ind, array<_Tp, _Nm>>
|
||||||
|
{
|
||||||
|
static_assert(_Ind < _Nm, "array index is in range");
|
||||||
|
using type = _Tp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
inline constexpr size_t tuple_size_v<array<_Tp, _Nm>> = _Nm;
|
||||||
|
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
inline constexpr size_t tuple_size_v<const array<_Tp, _Nm>> = _Nm;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
struct __is_tuple_like_impl<array<_Tp, _Nm>> : true_type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
_GLIBCXX_END_NAMESPACE_VERSION
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
#endif // C++11
|
||||||
|
|
||||||
|
#endif // _GLIBCXX_ARRAY
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,216 @@
|
|||||||
|
/* Copyright (C) 2015-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <avx5124fmapsintrin.h> directly; include <x86intrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX5124FMAPSINTRIN_H_INCLUDED
|
||||||
|
#define _AVX5124FMAPSINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVX5124FMAPS__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx5124fmaps,evex512")
|
||||||
|
#define __DISABLE_AVX5124FMAPS__
|
||||||
|
#endif /* __AVX5124FMAPS__ */
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_4fmadd_ps (__m512 __A, __m512 __B, __m512 __C,
|
||||||
|
__m512 __D, __m512 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_4fmaddps ((__v16sf) __B,
|
||||||
|
(__v16sf) __C,
|
||||||
|
(__v16sf) __D,
|
||||||
|
(__v16sf) __E,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(const __v4sf *) __F);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_4fmadd_ps (__m512 __A, __mmask16 __U, __m512 __B,
|
||||||
|
__m512 __C, __m512 __D, __m512 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_4fmaddps_mask ((__v16sf) __B,
|
||||||
|
(__v16sf) __C,
|
||||||
|
(__v16sf) __D,
|
||||||
|
(__v16sf) __E,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_4fmadd_ps (__mmask16 __U,
|
||||||
|
__m512 __A, __m512 __B, __m512 __C,
|
||||||
|
__m512 __D, __m512 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_4fmaddps_mask ((__v16sf) __B,
|
||||||
|
(__v16sf) __C,
|
||||||
|
(__v16sf) __D,
|
||||||
|
(__v16sf) __E,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v16sf) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_4fmadd_ss (__m128 __A, __m128 __B, __m128 __C,
|
||||||
|
__m128 __D, __m128 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_4fmaddss ((__v4sf) __B,
|
||||||
|
(__v4sf) __C,
|
||||||
|
(__v4sf) __D,
|
||||||
|
(__v4sf) __E,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(const __v4sf *) __F);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_4fmadd_ss (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C,
|
||||||
|
__m128 __D, __m128 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_4fmaddss_mask ((__v4sf) __B,
|
||||||
|
(__v4sf) __C,
|
||||||
|
(__v4sf) __D,
|
||||||
|
(__v4sf) __E,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_4fmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C,
|
||||||
|
__m128 __D, __m128 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_4fmaddss_mask ((__v4sf) __B,
|
||||||
|
(__v4sf) __C,
|
||||||
|
(__v4sf) __D,
|
||||||
|
(__v4sf) __E,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v4sf) _mm_setzero_ps (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_4fnmadd_ps (__m512 __A, __m512 __B, __m512 __C,
|
||||||
|
__m512 __D, __m512 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_4fnmaddps ((__v16sf) __B,
|
||||||
|
(__v16sf) __C,
|
||||||
|
(__v16sf) __D,
|
||||||
|
(__v16sf) __E,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(const __v4sf *) __F);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_4fnmadd_ps (__m512 __A, __mmask16 __U, __m512 __B,
|
||||||
|
__m512 __C, __m512 __D, __m512 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_4fnmaddps_mask ((__v16sf) __B,
|
||||||
|
(__v16sf) __C,
|
||||||
|
(__v16sf) __D,
|
||||||
|
(__v16sf) __E,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_4fnmadd_ps (__mmask16 __U,
|
||||||
|
__m512 __A, __m512 __B, __m512 __C,
|
||||||
|
__m512 __D, __m512 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_4fnmaddps_mask ((__v16sf) __B,
|
||||||
|
(__v16sf) __C,
|
||||||
|
(__v16sf) __D,
|
||||||
|
(__v16sf) __E,
|
||||||
|
(__v16sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v16sf) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_4fnmadd_ss (__m128 __A, __m128 __B, __m128 __C,
|
||||||
|
__m128 __D, __m128 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_4fnmaddss ((__v4sf) __B,
|
||||||
|
(__v4sf) __C,
|
||||||
|
(__v4sf) __D,
|
||||||
|
(__v4sf) __E,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(const __v4sf *) __F);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_4fnmadd_ss (__m128 __A, __mmask8 __U, __m128 __B, __m128 __C,
|
||||||
|
__m128 __D, __m128 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_4fnmaddss_mask ((__v4sf) __B,
|
||||||
|
(__v4sf) __C,
|
||||||
|
(__v4sf) __D,
|
||||||
|
(__v4sf) __E,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_4fnmadd_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C,
|
||||||
|
__m128 __D, __m128 __E, __m128 *__F)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_4fnmaddss_mask ((__v4sf) __B,
|
||||||
|
(__v4sf) __C,
|
||||||
|
(__v4sf) __D,
|
||||||
|
(__v4sf) __E,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(const __v4sf *) __F,
|
||||||
|
(__v4sf) _mm_setzero_ps (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX5124FMAPS__
|
||||||
|
#undef __DISABLE_AVX5124FMAPS__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX5124FMAPS__ */
|
||||||
|
|
||||||
|
#endif /* _AVX5124FMAPSINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/* Copyright (C) 2015-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <avx5124vnniwintrin.h> directly; include <x86intrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX5124VNNIWINTRIN_H_INCLUDED
|
||||||
|
#define _AVX5124VNNIWINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVX5124VNNIW__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx5124vnniw,evex512")
|
||||||
|
#define __DISABLE_AVX5124VNNIW__
|
||||||
|
#endif /* __AVX5124VNNIW__ */
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_4dpwssd_epi32 (__m512i __A, __m512i __B, __m512i __C,
|
||||||
|
__m512i __D, __m512i __E, __m128i *__F)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vp4dpwssd ((__v16si) __B,
|
||||||
|
(__v16si) __C,
|
||||||
|
(__v16si) __D,
|
||||||
|
(__v16si) __E,
|
||||||
|
(__v16si) __A,
|
||||||
|
(const __v4si *) __F);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_4dpwssd_epi32 (__m512i __A, __mmask16 __U, __m512i __B,
|
||||||
|
__m512i __C, __m512i __D, __m512i __E,
|
||||||
|
__m128i *__F)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vp4dpwssd_mask ((__v16si) __B,
|
||||||
|
(__v16si) __C,
|
||||||
|
(__v16si) __D,
|
||||||
|
(__v16si) __E,
|
||||||
|
(__v16si) __A,
|
||||||
|
(const __v4si *) __F,
|
||||||
|
(__v16si) __A,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_4dpwssd_epi32 (__mmask16 __U, __m512i __A, __m512i __B,
|
||||||
|
__m512i __C, __m512i __D, __m512i __E,
|
||||||
|
__m128i *__F)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vp4dpwssd_mask ((__v16si) __B,
|
||||||
|
(__v16si) __C,
|
||||||
|
(__v16si) __D,
|
||||||
|
(__v16si) __E,
|
||||||
|
(__v16si) __A,
|
||||||
|
(const __v4si *) __F,
|
||||||
|
(__v16si) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_4dpwssds_epi32 (__m512i __A, __m512i __B, __m512i __C,
|
||||||
|
__m512i __D, __m512i __E, __m128i *__F)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vp4dpwssds ((__v16si) __B,
|
||||||
|
(__v16si) __C,
|
||||||
|
(__v16si) __D,
|
||||||
|
(__v16si) __E,
|
||||||
|
(__v16si) __A,
|
||||||
|
(const __v4si *) __F);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_4dpwssds_epi32 (__m512i __A, __mmask16 __U, __m512i __B,
|
||||||
|
__m512i __C, __m512i __D, __m512i __E,
|
||||||
|
__m128i *__F)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vp4dpwssds_mask ((__v16si) __B,
|
||||||
|
(__v16si) __C,
|
||||||
|
(__v16si) __D,
|
||||||
|
(__v16si) __E,
|
||||||
|
(__v16si) __A,
|
||||||
|
(const __v4si *) __F,
|
||||||
|
(__v16si) __A,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_4dpwssds_epi32 (__mmask16 __U, __m512i __A, __m512i __B,
|
||||||
|
__m512i __C, __m512i __D, __m512i __E,
|
||||||
|
__m128i *__F)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vp4dpwssds_mask ((__v16si) __B,
|
||||||
|
(__v16si) __C,
|
||||||
|
(__v16si) __D,
|
||||||
|
(__v16si) __E,
|
||||||
|
(__v16si) __A,
|
||||||
|
(const __v4si *) __F,
|
||||||
|
(__v16si) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX5124VNNIW__
|
||||||
|
#undef __DISABLE_AVX5124VNNIW__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX5124VNNIW__ */
|
||||||
|
|
||||||
|
#endif /* _AVX5124VNNIWINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512bf16intrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512BF16INTRIN_H_INCLUDED
|
||||||
|
#define _AVX512BF16INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined (__AVX512BF16__) || defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512bf16,no-evex512")
|
||||||
|
#define __DISABLE_AVX512BF16__
|
||||||
|
#endif /* __AVX512BF16__ */
|
||||||
|
|
||||||
|
/* Convert One BF16 Data to One Single Float Data. */
|
||||||
|
extern __inline float
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtsbh_ss (__bf16 __A)
|
||||||
|
{
|
||||||
|
return __builtin_ia32_cvtbf2sf (__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512BF16__
|
||||||
|
#undef __DISABLE_AVX512BF16__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512BF16__ */
|
||||||
|
|
||||||
|
#if !defined (__AVX512BF16__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512bf16,evex512")
|
||||||
|
#define __DISABLE_AVX512BF16_512__
|
||||||
|
#endif /* __AVX512BF16_512__ */
|
||||||
|
|
||||||
|
/* Internal data types for implementing the intrinsics. */
|
||||||
|
typedef __bf16 __v32bf __attribute__ ((__vector_size__ (64)));
|
||||||
|
|
||||||
|
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||||
|
vector types, and their scalar components. */
|
||||||
|
typedef __bf16 __m512bh __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||||
|
|
||||||
|
/* vcvtne2ps2bf16 */
|
||||||
|
|
||||||
|
extern __inline __m512bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_cvtne2ps_pbh (__m512 __A, __m512 __B)
|
||||||
|
{
|
||||||
|
return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf(__A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_cvtne2ps_pbh (__m512bh __A, __mmask32 __B, __m512 __C, __m512 __D)
|
||||||
|
{
|
||||||
|
return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_mask(__C, __D, __A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_cvtne2ps_pbh (__mmask32 __A, __m512 __B, __m512 __C)
|
||||||
|
{
|
||||||
|
return (__m512bh)__builtin_ia32_cvtne2ps2bf16_v32bf_maskz(__B, __C, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vcvtneps2bf16 */
|
||||||
|
|
||||||
|
extern __inline __m256bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_cvtneps_pbh (__m512 __A)
|
||||||
|
{
|
||||||
|
return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf(__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_cvtneps_pbh (__m256bh __A, __mmask16 __B, __m512 __C)
|
||||||
|
{
|
||||||
|
return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf_mask(__C, __A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_cvtneps_pbh (__mmask16 __A, __m512 __B)
|
||||||
|
{
|
||||||
|
return (__m256bh)__builtin_ia32_cvtneps2bf16_v16sf_maskz(__B, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vdpbf16ps */
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_dpbf16_ps (__m512 __A, __m512bh __B, __m512bh __C)
|
||||||
|
{
|
||||||
|
return (__m512)__builtin_ia32_dpbf16ps_v16sf(__A, __B, __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_dpbf16_ps (__m512 __A, __mmask16 __B, __m512bh __C, __m512bh __D)
|
||||||
|
{
|
||||||
|
return (__m512)__builtin_ia32_dpbf16ps_v16sf_mask(__A, __C, __D, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_dpbf16_ps (__mmask16 __A, __m512 __B, __m512bh __C, __m512bh __D)
|
||||||
|
{
|
||||||
|
return (__m512)__builtin_ia32_dpbf16ps_v16sf_maskz(__B, __C, __D, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_cvtpbh_ps (__m256bh __A)
|
||||||
|
{
|
||||||
|
return (__m512)_mm512_castsi512_ps ((__m512i)_mm512_slli_epi32 (
|
||||||
|
(__m512i)_mm512_cvtepi16_epi32 ((__m256i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_cvtpbh_ps (__mmask16 __U, __m256bh __A)
|
||||||
|
{
|
||||||
|
return (__m512)_mm512_castsi512_ps ((__m512i) _mm512_slli_epi32 (
|
||||||
|
(__m512i)_mm512_maskz_cvtepi16_epi32 (
|
||||||
|
(__mmask16)__U, (__m256i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_cvtpbh_ps (__m512 __S, __mmask16 __U, __m256bh __A)
|
||||||
|
{
|
||||||
|
return (__m512)_mm512_castsi512_ps ((__m512i)(_mm512_mask_slli_epi32 (
|
||||||
|
(__m512i)__S, (__mmask16)__U,
|
||||||
|
(__m512i)_mm512_cvtepi16_epi32 ((__m256i)__A), 16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512BF16_512__
|
||||||
|
#undef __DISABLE_AVX512BF16_512__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512BF16_512__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512BF16INTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512bf16vlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512BF16VLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512BF16VLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VL__) || !defined(__AVX512BF16__) || defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512bf16,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512BF16VL__
|
||||||
|
#endif /* __AVX512BF16__ */
|
||||||
|
|
||||||
|
/* Internal data types for implementing the intrinsics. */
|
||||||
|
typedef __bf16 __v16bf __attribute__ ((__vector_size__ (32)));
|
||||||
|
typedef __bf16 __v8bf __attribute__ ((__vector_size__ (16)));
|
||||||
|
|
||||||
|
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||||
|
vector types, and their scalar components. */
|
||||||
|
typedef __bf16 __m256bh __attribute__ ((__vector_size__ (32), __may_alias__));
|
||||||
|
typedef __bf16 __m128bh __attribute__ ((__vector_size__ (16), __may_alias__));
|
||||||
|
|
||||||
|
typedef __bf16 __bfloat16;
|
||||||
|
|
||||||
|
extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_avx512_castsi128_ps(__m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128) __A;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_avx512_castsi256_ps (__m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256) __A;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_avx512_slli_epi32 (__m128i __A, int __B)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_avx512_slli_epi32 (__m256i __A, int __B)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_pslldi256 ((__v8si)__A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_avx512_cvtepi16_epi32 (__m128i __X)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_pmovsxwd128 ((__v8hi)__X);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_avx512_cvtepi16_epi32 (__m128i __X)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_pmovsxwd256 ((__v8hi)__X);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm256_cvtneps_pbh(A) \
|
||||||
|
(__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (A)
|
||||||
|
#define _mm_cvtneps_pbh(A) \
|
||||||
|
(__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (A)
|
||||||
|
|
||||||
|
/* vcvtne2ps2bf16 */
|
||||||
|
|
||||||
|
extern __inline __m256bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtne2ps_pbh (__m256 __A, __m256 __B)
|
||||||
|
{
|
||||||
|
return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf(__A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_cvtne2ps_pbh (__m256bh __A, __mmask16 __B, __m256 __C, __m256 __D)
|
||||||
|
{
|
||||||
|
return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_mask(__C, __D, __A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_cvtne2ps_pbh (__mmask16 __A, __m256 __B, __m256 __C)
|
||||||
|
{
|
||||||
|
return (__m256bh)__builtin_ia32_cvtne2ps2bf16_v16bf_maskz(__B, __C, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtne2ps_pbh (__m128 __A, __m128 __B)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf(__A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_cvtne2ps_pbh (__m128bh __A, __mmask8 __B, __m128 __C, __m128 __D)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_mask(__C, __D, __A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_cvtne2ps_pbh (__mmask8 __A, __m128 __B, __m128 __C)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtne2ps2bf16_v8bf_maskz(__B, __C, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vcvtneps2bf16 */
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m256 __C)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_mask(__C, __A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_cvtneps_pbh (__mmask8 __A, __m256 __B)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtneps2bf16_v8sf_maskz(__B, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_cvtneps_pbh (__m128bh __A, __mmask8 __B, __m128 __C)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_mask(__C, __A, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_cvtneps_pbh (__mmask8 __A, __m128 __B)
|
||||||
|
{
|
||||||
|
return (__m128bh)__builtin_ia32_cvtneps2bf16_v4sf_maskz(__B, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vdpbf16ps */
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbf16_ps (__m256 __A, __m256bh __B, __m256bh __C)
|
||||||
|
{
|
||||||
|
return (__m256)__builtin_ia32_dpbf16ps_v8sf(__A, __B, __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_dpbf16_ps (__m256 __A, __mmask8 __B, __m256bh __C, __m256bh __D)
|
||||||
|
{
|
||||||
|
return (__m256)__builtin_ia32_dpbf16ps_v8sf_mask(__A, __C, __D, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_dpbf16_ps (__mmask8 __A, __m256 __B, __m256bh __C, __m256bh __D)
|
||||||
|
{
|
||||||
|
return (__m256)__builtin_ia32_dpbf16ps_v8sf_maskz(__B, __C, __D, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbf16_ps (__m128 __A, __m128bh __B, __m128bh __C)
|
||||||
|
{
|
||||||
|
return (__m128)__builtin_ia32_dpbf16ps_v4sf(__A, __B, __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_dpbf16_ps (__m128 __A, __mmask8 __B, __m128bh __C, __m128bh __D)
|
||||||
|
{
|
||||||
|
return (__m128)__builtin_ia32_dpbf16ps_v4sf_mask(__A, __C, __D, __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_dpbf16_ps (__mmask8 __A, __m128 __B, __m128bh __C, __m128bh __D)
|
||||||
|
{
|
||||||
|
return (__m128)__builtin_ia32_dpbf16ps_v4sf_maskz(__B, __C, __D, __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __bf16
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtness_sbh (float __A)
|
||||||
|
{
|
||||||
|
__v4sf __V = {__A, 0, 0, 0};
|
||||||
|
__v8bf __R = __builtin_ia32_cvtneps2bf16_v4sf_mask ((__v4sf)__V,
|
||||||
|
(__v8bf)_mm_avx512_undefined_si128 (), (__mmask8)-1);
|
||||||
|
return __R[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtpbh_ps (__m128bh __A)
|
||||||
|
{
|
||||||
|
return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_avx512_slli_epi32 (
|
||||||
|
(__m128i)_mm_avx512_cvtepi16_epi32 ((__m128i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtpbh_ps (__m128bh __A)
|
||||||
|
{
|
||||||
|
return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_avx512_slli_epi32 (
|
||||||
|
(__m256i)_mm256_avx512_cvtepi16_epi32 ((__m128i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_cvtpbh_ps (__mmask8 __U, __m128bh __A)
|
||||||
|
{
|
||||||
|
return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_avx512_slli_epi32 (
|
||||||
|
(__m128i)_mm_maskz_cvtepi16_epi32 (
|
||||||
|
(__mmask8)__U, (__m128i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_cvtpbh_ps (__mmask8 __U, __m128bh __A)
|
||||||
|
{
|
||||||
|
return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_avx512_slli_epi32 (
|
||||||
|
(__m256i)_mm256_maskz_cvtepi16_epi32 (
|
||||||
|
(__mmask8)__U, (__m128i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_cvtpbh_ps (__m128 __S, __mmask8 __U, __m128bh __A)
|
||||||
|
{
|
||||||
|
return (__m128)_mm_avx512_castsi128_ps ((__m128i)_mm_mask_slli_epi32 (
|
||||||
|
(__m128i)__S, (__mmask8)__U, (__m128i)_mm_avx512_cvtepi16_epi32 (
|
||||||
|
(__m128i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_cvtpbh_ps (__m256 __S, __mmask8 __U, __m128bh __A)
|
||||||
|
{
|
||||||
|
return (__m256)_mm256_avx512_castsi256_ps ((__m256i)_mm256_mask_slli_epi32 (
|
||||||
|
(__m256i)__S, (__mmask8)__U, (__m256i)_mm256_avx512_cvtepi16_epi32 (
|
||||||
|
(__m128i)__A), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512BF16VL__
|
||||||
|
#undef __DISABLE_AVX512BF16VL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512BF16VL__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512BF16VLINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/* Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <avx512bitalgintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512BITALGINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512BITALGINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined (__AVX512BITALG__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512bitalg,evex512")
|
||||||
|
#define __DISABLE_AVX512BITALG__
|
||||||
|
#endif /* __AVX512BITALG__ */
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_popcnt_epi8 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountb_v64qi ((__v64qi) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_popcnt_epi16 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountw_v32hi ((__v32hi) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_popcnt_epi8 (__m512i __W, __mmask64 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountb_v64qi_mask ((__v64qi) __A,
|
||||||
|
(__v64qi) __W,
|
||||||
|
(__mmask64) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_popcnt_epi8 (__mmask64 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountb_v64qi_mask ((__v64qi) __A,
|
||||||
|
(__v64qi)
|
||||||
|
_mm512_setzero_si512 (),
|
||||||
|
(__mmask64) __U);
|
||||||
|
}
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_popcnt_epi16 (__m512i __W, __mmask32 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountw_v32hi_mask ((__v32hi) __A,
|
||||||
|
(__v32hi) __W,
|
||||||
|
(__mmask32) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_popcnt_epi16 (__mmask32 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountw_v32hi_mask ((__v32hi) __A,
|
||||||
|
(__v32hi)
|
||||||
|
_mm512_setzero_si512 (),
|
||||||
|
(__mmask32) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __mmask64
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_bitshuffle_epi64_mask (__m512i __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__mmask64) __builtin_ia32_vpshufbitqmb512_mask ((__v64qi) __A,
|
||||||
|
(__v64qi) __B,
|
||||||
|
(__mmask64) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __mmask64
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_bitshuffle_epi64_mask (__mmask64 __M, __m512i __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__mmask64) __builtin_ia32_vpshufbitqmb512_mask ((__v64qi) __A,
|
||||||
|
(__v64qi) __B,
|
||||||
|
(__mmask64) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512BITALG__
|
||||||
|
#undef __DISABLE_AVX512BITALG__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512BITALG__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512BITALGINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <avx512bitalgvlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512BITALGVLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512BITALGVLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512BITALG__) || !defined(__AVX512VL__) || defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512bitalg,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512BITALGVL__
|
||||||
|
#endif /* __AVX512BITALGVL__ */
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_popcnt_epi8 (__m256i __W, __mmask32 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountb_v32qi_mask ((__v32qi) __A,
|
||||||
|
(__v32qi) __W,
|
||||||
|
(__mmask32) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_popcnt_epi8 (__mmask32 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountb_v32qi_mask ((__v32qi) __A,
|
||||||
|
(__v32qi)
|
||||||
|
_mm256_avx512_setzero_si256 (),
|
||||||
|
(__mmask32) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __mmask32
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_bitshuffle_epi64_mask (__m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask ((__v32qi) __A,
|
||||||
|
(__v32qi) __B,
|
||||||
|
(__mmask32) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __mmask32
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_bitshuffle_epi64_mask (__mmask32 __M, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__mmask32) __builtin_ia32_vpshufbitqmb256_mask ((__v32qi) __A,
|
||||||
|
(__v32qi) __B,
|
||||||
|
(__mmask32) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __mmask16
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_bitshuffle_epi64_mask (__m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask ((__v16qi) __A,
|
||||||
|
(__v16qi) __B,
|
||||||
|
(__mmask16) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __mmask16
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_bitshuffle_epi64_mask (__mmask16 __M, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__mmask16) __builtin_ia32_vpshufbitqmb128_mask ((__v16qi) __A,
|
||||||
|
(__v16qi) __B,
|
||||||
|
(__mmask16) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_popcnt_epi8 (__m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountb_v32qi ((__v32qi) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_popcnt_epi16 (__m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountw_v16hi ((__v16hi) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_popcnt_epi8 (__m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountb_v16qi ((__v16qi) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_popcnt_epi16 (__m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountw_v8hi ((__v8hi) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_popcnt_epi16 (__m256i __W, __mmask16 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountw_v16hi_mask ((__v16hi) __A,
|
||||||
|
(__v16hi) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_popcnt_epi16 (__mmask16 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountw_v16hi_mask ((__v16hi) __A,
|
||||||
|
(__v16hi)
|
||||||
|
_mm256_avx512_setzero_si256 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_popcnt_epi8 (__m128i __W, __mmask16 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountb_v16qi_mask ((__v16qi) __A,
|
||||||
|
(__v16qi) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_popcnt_epi8 (__mmask16 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountb_v16qi_mask ((__v16qi) __A,
|
||||||
|
(__v16qi)
|
||||||
|
_mm_avx512_setzero_si128 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_popcnt_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountw_v8hi_mask ((__v8hi) __A,
|
||||||
|
(__v8hi) __W,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_popcnt_epi16 (__mmask8 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountw_v8hi_mask ((__v8hi) __A,
|
||||||
|
(__v8hi)
|
||||||
|
_mm_avx512_setzero_si128 (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
#ifdef __DISABLE_AVX512BITALGVL__
|
||||||
|
#undef __DISABLE_AVX512BITALGVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512BITALGVL__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512BITALGVLINTRIN_H_INCLUDED */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512cdintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512CDINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512CDINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVX512CD__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512cd,evex512")
|
||||||
|
#define __DISABLE_AVX512CD__
|
||||||
|
#endif /* __AVX512CD__ */
|
||||||
|
|
||||||
|
/* Internal data types for implementing the intrinsics. */
|
||||||
|
typedef long long __v8di __attribute__ ((__vector_size__ (64)));
|
||||||
|
typedef int __v16si __attribute__ ((__vector_size__ (64)));
|
||||||
|
|
||||||
|
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||||
|
vector types, and their scalar components. */
|
||||||
|
typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||||
|
typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||||
|
|
||||||
|
typedef unsigned char __mmask8;
|
||||||
|
typedef unsigned short __mmask16;
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_conflict_epi32 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
|
||||||
|
(__v16si) _mm512_setzero_si512 (),
|
||||||
|
(__mmask16) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_conflict_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
|
||||||
|
(__v16si) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_conflict_epi32 (__mmask16 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vpconflictsi_512_mask ((__v16si) __A,
|
||||||
|
(__v16si) _mm512_setzero_si512 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_conflict_epi64 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
|
||||||
|
(__v8di) _mm512_setzero_si512 (),
|
||||||
|
(__mmask8) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_conflict_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
|
||||||
|
(__v8di) __W,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_conflict_epi64 (__mmask8 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vpconflictdi_512_mask ((__v8di) __A,
|
||||||
|
(__v8di) _mm512_setzero_si512 (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_lzcnt_epi64 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
|
||||||
|
(__v8di) _mm512_setzero_si512 (),
|
||||||
|
(__mmask8) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_lzcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
|
||||||
|
(__v8di) __W,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_lzcnt_epi64 (__mmask8 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vplzcntq_512_mask ((__v8di) __A,
|
||||||
|
(__v8di) _mm512_setzero_si512 (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_lzcnt_epi32 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
|
||||||
|
(__v16si) _mm512_setzero_si512 (),
|
||||||
|
(__mmask16) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_lzcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
|
||||||
|
(__v16si) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_lzcnt_epi32 (__mmask16 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i)
|
||||||
|
__builtin_ia32_vplzcntd_512_mask ((__v16si) __A,
|
||||||
|
(__v16si) _mm512_setzero_si512 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_broadcastmb_epi64 (__mmask8 __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_broadcastmb512 (__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_broadcastmw_epi32 (__mmask16 __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_broadcastmw512 (__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512CD__
|
||||||
|
#undef __DISABLE_AVX512CD__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512CD__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512CDINTRIN_H_INCLUDED */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,536 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512erintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512ERINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512ERINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVX512ER__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512er,evex512")
|
||||||
|
#define __DISABLE_AVX512ER__
|
||||||
|
#endif /* __AVX512ER__ */
|
||||||
|
|
||||||
|
/* Internal data types for implementing the intrinsics. */
|
||||||
|
typedef double __v8df __attribute__ ((__vector_size__ (64)));
|
||||||
|
typedef float __v16sf __attribute__ ((__vector_size__ (64)));
|
||||||
|
|
||||||
|
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||||
|
vector types, and their scalar components. */
|
||||||
|
typedef float __m512 __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||||
|
typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||||
|
|
||||||
|
typedef unsigned char __mmask8;
|
||||||
|
typedef unsigned short __mmask16;
|
||||||
|
|
||||||
|
#ifdef __OPTIMIZE__
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_exp2a23_round_pd (__m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) _mm512_undefined_pd (),
|
||||||
|
(__mmask8) -1, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_exp2a23_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) __W,
|
||||||
|
(__mmask8) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_exp2a23_round_pd (__mmask8 __U, __m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_exp2pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) _mm512_setzero_pd (),
|
||||||
|
(__mmask8) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_exp2a23_round_ps (__m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) _mm512_undefined_ps (),
|
||||||
|
(__mmask16) -1, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_exp2a23_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) __W,
|
||||||
|
(__mmask16) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_exp2a23_round_ps (__mmask16 __U, __m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_exp2ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_rcp28_round_pd (__m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) _mm512_undefined_pd (),
|
||||||
|
(__mmask8) -1, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_rcp28_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) __W,
|
||||||
|
(__mmask8) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_rcp28_round_pd (__mmask8 __U, __m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_rcp28pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) _mm512_setzero_pd (),
|
||||||
|
(__mmask8) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_rcp28_round_ps (__m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) _mm512_undefined_ps (),
|
||||||
|
(__mmask16) -1, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_rcp28_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) __W,
|
||||||
|
(__mmask16) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_rcp28_round_ps (__mmask16 __U, __m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_rcp28ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_rcp28_round_sd (__m128d __A, __m128d __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128d) __builtin_ia32_rcp28sd_round ((__v2df) __B,
|
||||||
|
(__v2df) __A,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_rcp28_round_sd (__m128d __W, __mmask8 __U, __m128d __A,
|
||||||
|
__m128d __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128d) __builtin_ia32_rcp28sd_mask_round ((__v2df) __B,
|
||||||
|
(__v2df) __A,
|
||||||
|
(__v2df) __W,
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_rcp28_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128d) __builtin_ia32_rcp28sd_mask_round ((__v2df) __B,
|
||||||
|
(__v2df) __A,
|
||||||
|
(__v2df)
|
||||||
|
_mm_setzero_pd (),
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_rcp28_round_ss (__m128 __A, __m128 __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_rcp28ss_round ((__v4sf) __B,
|
||||||
|
(__v4sf) __A,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_rcp28_round_ss (__m128 __W, __mmask8 __U, __m128 __A,
|
||||||
|
__m128 __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_rcp28ss_mask_round ((__v4sf) __B,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(__v4sf) __W,
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_rcp28_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_rcp28ss_mask_round ((__v4sf) __B,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(__v4sf)
|
||||||
|
_mm_setzero_ps (),
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_rsqrt28_round_pd (__m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) _mm512_undefined_pd (),
|
||||||
|
(__mmask8) -1, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_rsqrt28_round_pd (__m512d __W, __mmask8 __U, __m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) __W,
|
||||||
|
(__mmask8) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_rsqrt28_round_pd (__mmask8 __U, __m512d __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512d) __builtin_ia32_rsqrt28pd_mask ((__v8df) __A,
|
||||||
|
(__v8df) _mm512_setzero_pd (),
|
||||||
|
(__mmask8) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_rsqrt28_round_ps (__m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) _mm512_undefined_ps (),
|
||||||
|
(__mmask16) -1, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_rsqrt28_round_ps (__m512 __W, __mmask16 __U, __m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) __W,
|
||||||
|
(__mmask16) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_rsqrt28_round_ps (__mmask16 __U, __m512 __A, int __R)
|
||||||
|
{
|
||||||
|
return (__m512) __builtin_ia32_rsqrt28ps_mask ((__v16sf) __A,
|
||||||
|
(__v16sf) _mm512_setzero_ps (),
|
||||||
|
(__mmask16) __U, __R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_rsqrt28_round_sd (__m128d __A, __m128d __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128d) __builtin_ia32_rsqrt28sd_round ((__v2df) __B,
|
||||||
|
(__v2df) __A,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_rsqrt28_round_sd (__m128d __W, __mmask8 __U, __m128d __A,
|
||||||
|
__m128d __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128d) __builtin_ia32_rsqrt28sd_mask_round ((__v2df) __B,
|
||||||
|
(__v2df) __A,
|
||||||
|
(__v2df) __W,
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128d
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_rsqrt28_round_sd (__mmask8 __U, __m128d __A, __m128d __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128d) __builtin_ia32_rsqrt28sd_mask_round ((__v2df) __B,
|
||||||
|
(__v2df) __A,
|
||||||
|
(__v2df)
|
||||||
|
_mm_setzero_pd (),
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_rsqrt28_round_ss (__m128 __A, __m128 __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_rsqrt28ss_round ((__v4sf) __B,
|
||||||
|
(__v4sf) __A,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_rsqrt28_round_ss (__m128 __W, __mmask8 __U, __m128 __A,
|
||||||
|
__m128 __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_rsqrt28ss_mask_round ((__v4sf) __B,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(__v4sf) __W,
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_rsqrt28_round_ss (__mmask8 __U, __m128 __A, __m128 __B, int __R)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_rsqrt28ss_mask_round ((__v4sf) __B,
|
||||||
|
(__v4sf) __A,
|
||||||
|
(__v4sf)
|
||||||
|
_mm_setzero_ps (),
|
||||||
|
__U,
|
||||||
|
__R);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define _mm512_exp2a23_round_pd(A, C) \
|
||||||
|
__builtin_ia32_exp2pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C)
|
||||||
|
|
||||||
|
#define _mm512_mask_exp2a23_round_pd(W, U, A, C) \
|
||||||
|
__builtin_ia32_exp2pd_mask(A, W, U, C)
|
||||||
|
|
||||||
|
#define _mm512_maskz_exp2a23_round_pd(U, A, C) \
|
||||||
|
__builtin_ia32_exp2pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C)
|
||||||
|
|
||||||
|
#define _mm512_exp2a23_round_ps(A, C) \
|
||||||
|
__builtin_ia32_exp2ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C)
|
||||||
|
|
||||||
|
#define _mm512_mask_exp2a23_round_ps(W, U, A, C) \
|
||||||
|
__builtin_ia32_exp2ps_mask(A, W, U, C)
|
||||||
|
|
||||||
|
#define _mm512_maskz_exp2a23_round_ps(U, A, C) \
|
||||||
|
__builtin_ia32_exp2ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C)
|
||||||
|
|
||||||
|
#define _mm512_rcp28_round_pd(A, C) \
|
||||||
|
__builtin_ia32_rcp28pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C)
|
||||||
|
|
||||||
|
#define _mm512_mask_rcp28_round_pd(W, U, A, C) \
|
||||||
|
__builtin_ia32_rcp28pd_mask(A, W, U, C)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rcp28_round_pd(U, A, C) \
|
||||||
|
__builtin_ia32_rcp28pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C)
|
||||||
|
|
||||||
|
#define _mm512_rcp28_round_ps(A, C) \
|
||||||
|
__builtin_ia32_rcp28ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C)
|
||||||
|
|
||||||
|
#define _mm512_mask_rcp28_round_ps(W, U, A, C) \
|
||||||
|
__builtin_ia32_rcp28ps_mask(A, W, U, C)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rcp28_round_ps(U, A, C) \
|
||||||
|
__builtin_ia32_rcp28ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C)
|
||||||
|
|
||||||
|
#define _mm512_rsqrt28_round_pd(A, C) \
|
||||||
|
__builtin_ia32_rsqrt28pd_mask(A, (__v8df)_mm512_setzero_pd(), -1, C)
|
||||||
|
|
||||||
|
#define _mm512_mask_rsqrt28_round_pd(W, U, A, C) \
|
||||||
|
__builtin_ia32_rsqrt28pd_mask(A, W, U, C)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rsqrt28_round_pd(U, A, C) \
|
||||||
|
__builtin_ia32_rsqrt28pd_mask(A, (__v8df)_mm512_setzero_pd(), U, C)
|
||||||
|
|
||||||
|
#define _mm512_rsqrt28_round_ps(A, C) \
|
||||||
|
__builtin_ia32_rsqrt28ps_mask(A, (__v16sf)_mm512_setzero_ps(), -1, C)
|
||||||
|
|
||||||
|
#define _mm512_mask_rsqrt28_round_ps(W, U, A, C) \
|
||||||
|
__builtin_ia32_rsqrt28ps_mask(A, W, U, C)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rsqrt28_round_ps(U, A, C) \
|
||||||
|
__builtin_ia32_rsqrt28ps_mask(A, (__v16sf)_mm512_setzero_ps(), U, C)
|
||||||
|
|
||||||
|
#define _mm_rcp28_round_sd(A, B, R) \
|
||||||
|
__builtin_ia32_rcp28sd_round(A, B, R)
|
||||||
|
|
||||||
|
#define _mm_mask_rcp28_round_sd(W, U, A, B, R) \
|
||||||
|
__builtin_ia32_rcp28sd_mask_round ((A), (B), (W), (U), (R))
|
||||||
|
|
||||||
|
#define _mm_maskz_rcp28_round_sd(U, A, B, R) \
|
||||||
|
__builtin_ia32_rcp28sd_mask_round ((A), (B), (__v2df) _mm_setzero_pd (), \
|
||||||
|
(U), (R))
|
||||||
|
|
||||||
|
#define _mm_rcp28_round_ss(A, B, R) \
|
||||||
|
__builtin_ia32_rcp28ss_round(A, B, R)
|
||||||
|
|
||||||
|
#define _mm_mask_rcp28_round_ss(W, U, A, B, R) \
|
||||||
|
__builtin_ia32_rcp28ss_mask_round ((A), (B), (W), (U), (R))
|
||||||
|
|
||||||
|
#define _mm_maskz_rcp28_round_ss(U, A, B, R) \
|
||||||
|
__builtin_ia32_rcp28ss_mask_round ((A), (B), (__v4sf) _mm_setzero_ps (), \
|
||||||
|
(U), (R))
|
||||||
|
|
||||||
|
#define _mm_rsqrt28_round_sd(A, B, R) \
|
||||||
|
__builtin_ia32_rsqrt28sd_round(A, B, R)
|
||||||
|
|
||||||
|
#define _mm_mask_rsqrt28_round_sd(W, U, A, B, R) \
|
||||||
|
__builtin_ia32_rsqrt28sd_mask_round ((A), (B), (W), (U), (R))
|
||||||
|
|
||||||
|
#define _mm_maskz_rsqrt28_round_sd(U, A, B, R) \
|
||||||
|
__builtin_ia32_rsqrt28sd_mask_round ((A), (B), (__v2df) _mm_setzero_pd (),\
|
||||||
|
(U), (R))
|
||||||
|
|
||||||
|
#define _mm_rsqrt28_round_ss(A, B, R) \
|
||||||
|
__builtin_ia32_rsqrt28ss_round(A, B, R)
|
||||||
|
|
||||||
|
#define _mm_mask_rsqrt28_round_ss(W, U, A, B, R) \
|
||||||
|
__builtin_ia32_rsqrt28ss_mask_round ((A), (B), (W), (U), (R))
|
||||||
|
|
||||||
|
#define _mm_maskz_rsqrt28_round_ss(U, A, B, R) \
|
||||||
|
__builtin_ia32_rsqrt28ss_mask_round ((A), (B), (__v4sf) _mm_setzero_ps (),\
|
||||||
|
(U), (R))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _mm_mask_rcp28_sd(W, U, A, B)\
|
||||||
|
_mm_mask_rcp28_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_maskz_rcp28_sd(U, A, B)\
|
||||||
|
_mm_maskz_rcp28_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_mask_rcp28_ss(W, U, A, B)\
|
||||||
|
_mm_mask_rcp28_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_maskz_rcp28_ss(U, A, B)\
|
||||||
|
_mm_maskz_rcp28_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_mask_rsqrt28_sd(W, U, A, B)\
|
||||||
|
_mm_mask_rsqrt28_round_sd ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_maskz_rsqrt28_sd(U, A, B)\
|
||||||
|
_mm_maskz_rsqrt28_round_sd ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_mask_rsqrt28_ss(W, U, A, B)\
|
||||||
|
_mm_mask_rsqrt28_round_ss ((W), (U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_maskz_rsqrt28_ss(U, A, B)\
|
||||||
|
_mm_maskz_rsqrt28_round_ss ((U), (A), (B), _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_exp2a23_pd(A) \
|
||||||
|
_mm512_exp2a23_round_pd(A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_mask_exp2a23_pd(W, U, A) \
|
||||||
|
_mm512_mask_exp2a23_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_maskz_exp2a23_pd(U, A) \
|
||||||
|
_mm512_maskz_exp2a23_round_pd(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_exp2a23_ps(A) \
|
||||||
|
_mm512_exp2a23_round_ps(A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_mask_exp2a23_ps(W, U, A) \
|
||||||
|
_mm512_mask_exp2a23_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_maskz_exp2a23_ps(U, A) \
|
||||||
|
_mm512_maskz_exp2a23_round_ps(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_rcp28_pd(A) \
|
||||||
|
_mm512_rcp28_round_pd(A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_mask_rcp28_pd(W, U, A) \
|
||||||
|
_mm512_mask_rcp28_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rcp28_pd(U, A) \
|
||||||
|
_mm512_maskz_rcp28_round_pd(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_rcp28_ps(A) \
|
||||||
|
_mm512_rcp28_round_ps(A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_mask_rcp28_ps(W, U, A) \
|
||||||
|
_mm512_mask_rcp28_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rcp28_ps(U, A) \
|
||||||
|
_mm512_maskz_rcp28_round_ps(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_rsqrt28_pd(A) \
|
||||||
|
_mm512_rsqrt28_round_pd(A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_mask_rsqrt28_pd(W, U, A) \
|
||||||
|
_mm512_mask_rsqrt28_round_pd(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rsqrt28_pd(U, A) \
|
||||||
|
_mm512_maskz_rsqrt28_round_pd(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_rsqrt28_ps(A) \
|
||||||
|
_mm512_rsqrt28_round_ps(A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_mask_rsqrt28_ps(W, U, A) \
|
||||||
|
_mm512_mask_rsqrt28_round_ps(W, U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm512_maskz_rsqrt28_ps(U, A) \
|
||||||
|
_mm512_maskz_rsqrt28_round_ps(U, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_rcp28_sd(A, B) \
|
||||||
|
__builtin_ia32_rcp28sd_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_rcp28_ss(A, B) \
|
||||||
|
__builtin_ia32_rcp28ss_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_rsqrt28_sd(A, B) \
|
||||||
|
__builtin_ia32_rsqrt28sd_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#define _mm_rsqrt28_ss(A, B) \
|
||||||
|
__builtin_ia32_rsqrt28ss_round(B, A, _MM_FROUND_CUR_DIRECTION)
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512ER__
|
||||||
|
#undef __DISABLE_AVX512ER__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512ER__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512ERINTRIN_H_INCLUDED */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512ifmaintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512IFMAINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512IFMAINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined (__AVX512IFMA__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512ifma,evex512")
|
||||||
|
#define __DISABLE_AVX512IFMA__
|
||||||
|
#endif /* __AVX512IFMA__ */
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_madd52lo_epu64 (__m512i __X, __m512i __Y, __m512i __Z)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __X,
|
||||||
|
(__v8di) __Y,
|
||||||
|
(__v8di) __Z,
|
||||||
|
(__mmask8) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_madd52hi_epu64 (__m512i __X, __m512i __Y, __m512i __Z)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __X,
|
||||||
|
(__v8di) __Y,
|
||||||
|
(__v8di) __Z,
|
||||||
|
(__mmask8) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_madd52lo_epu64 (__m512i __W, __mmask8 __M, __m512i __X,
|
||||||
|
__m512i __Y)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmadd52luq512_mask ((__v8di) __W,
|
||||||
|
(__v8di) __X,
|
||||||
|
(__v8di) __Y,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_madd52hi_epu64 (__m512i __W, __mmask8 __M, __m512i __X,
|
||||||
|
__m512i __Y)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmadd52huq512_mask ((__v8di) __W,
|
||||||
|
(__v8di) __X,
|
||||||
|
(__v8di) __Y,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_madd52lo_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmadd52luq512_maskz ((__v8di) __X,
|
||||||
|
(__v8di) __Y,
|
||||||
|
(__v8di) __Z,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_madd52hi_epu64 (__mmask8 __M, __m512i __X, __m512i __Y, __m512i __Z)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmadd52huq512_maskz ((__v8di) __X,
|
||||||
|
(__v8di) __Y,
|
||||||
|
(__v8di) __Z,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512IFMA__
|
||||||
|
#undef __DISABLE_AVX512IFMA__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512IFMA__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512IFMAINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512ifmavlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512IFMAVLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512IFMAVLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VL__) || !defined(__AVX512IFMA__) || defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512ifma,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512IFMAVL__
|
||||||
|
#endif /* __AVX512IFMAVL__ */
|
||||||
|
|
||||||
|
#define _mm_madd52lo_epu64(A, B, C) \
|
||||||
|
((__m128i) __builtin_ia32_vpmadd52luq128 ((__v2di) (A), \
|
||||||
|
(__v2di) (B), \
|
||||||
|
(__v2di) (C)))
|
||||||
|
|
||||||
|
#define _mm_madd52hi_epu64(A, B, C) \
|
||||||
|
((__m128i) __builtin_ia32_vpmadd52huq128 ((__v2di) (A), \
|
||||||
|
(__v2di) (B), \
|
||||||
|
(__v2di) (C)))
|
||||||
|
|
||||||
|
#define _mm256_madd52lo_epu64(A, B, C) \
|
||||||
|
((__m256i) __builtin_ia32_vpmadd52luq256 ((__v4di) (A), \
|
||||||
|
(__v4di) (B), \
|
||||||
|
(__v4di) (C)))
|
||||||
|
|
||||||
|
|
||||||
|
#define _mm256_madd52hi_epu64(A, B, C) \
|
||||||
|
((__m256i) __builtin_ia32_vpmadd52huq256 ((__v4di) (A), \
|
||||||
|
(__v4di) (B), \
|
||||||
|
(__v4di) (C)))
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_madd52lo_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmadd52luq128_mask ((__v2di) __W,
|
||||||
|
(__v2di) __X,
|
||||||
|
(__v2di) __Y,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_madd52hi_epu64 (__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmadd52huq128_mask ((__v2di) __W,
|
||||||
|
(__v2di) __X,
|
||||||
|
(__v2di) __Y,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_madd52lo_epu64 (__m256i __W, __mmask8 __M, __m256i __X,
|
||||||
|
__m256i __Y)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmadd52luq256_mask ((__v4di) __W,
|
||||||
|
(__v4di) __X,
|
||||||
|
(__v4di) __Y,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_madd52hi_epu64 (__m256i __W, __mmask8 __M, __m256i __X,
|
||||||
|
__m256i __Y)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmadd52huq256_mask ((__v4di) __W,
|
||||||
|
(__v4di) __X,
|
||||||
|
(__v4di) __Y,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_madd52lo_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmadd52luq128_maskz ((__v2di) __X,
|
||||||
|
(__v2di) __Y,
|
||||||
|
(__v2di) __Z,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_madd52hi_epu64 (__mmask8 __M, __m128i __X, __m128i __Y, __m128i __Z)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmadd52huq128_maskz ((__v2di) __X,
|
||||||
|
(__v2di) __Y,
|
||||||
|
(__v2di) __Z,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_madd52lo_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmadd52luq256_maskz ((__v4di) __X,
|
||||||
|
(__v4di) __Y,
|
||||||
|
(__v4di) __Z,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_madd52hi_epu64 (__mmask8 __M, __m256i __X, __m256i __Y, __m256i __Z)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmadd52huq256_maskz ((__v4di) __X,
|
||||||
|
(__v4di) __Y,
|
||||||
|
(__v4di) __Z,
|
||||||
|
(__mmask8) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512IFMAVL__
|
||||||
|
#undef __DISABLE_AVX512IFMAVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512IFMAVL__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512IFMAVLINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,269 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512pfintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512PFINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512PFINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVX512PF__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512pf,evex512")
|
||||||
|
#define __DISABLE_AVX512PF__
|
||||||
|
#endif /* __AVX512PF__ */
|
||||||
|
|
||||||
|
/* Internal data types for implementing the intrinsics. */
|
||||||
|
typedef long long __v8di __attribute__ ((__vector_size__ (64)));
|
||||||
|
typedef int __v16si __attribute__ ((__vector_size__ (64)));
|
||||||
|
|
||||||
|
/* The Intel API is flexible enough that we must allow aliasing with other
|
||||||
|
vector types, and their scalar components. */
|
||||||
|
typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__));
|
||||||
|
|
||||||
|
typedef unsigned char __mmask8;
|
||||||
|
typedef unsigned short __mmask16;
|
||||||
|
|
||||||
|
#ifdef __OPTIMIZE__
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i32gather_pd (__m256i __index, void const *__addr,
|
||||||
|
int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfdpd ((__mmask8) 0xFF, (__v8si) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i32gather_ps (__m512i __index, void const *__addr,
|
||||||
|
int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfdps ((__mmask16) 0xFFFF, (__v16si) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i32gather_pd (__m256i __index, __mmask8 __mask,
|
||||||
|
void const *__addr, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfdpd (__mask, (__v8si) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i32gather_ps (__m512i __index, __mmask16 __mask,
|
||||||
|
void const *__addr, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfdps (__mask, (__v16si) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i64gather_pd (__m512i __index, void const *__addr,
|
||||||
|
int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfqpd ((__mmask8) 0xFF, (__v8di) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i64gather_ps (__m512i __index, void const *__addr,
|
||||||
|
int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfqps ((__mmask8) 0xFF, (__v8di) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i64gather_pd (__m512i __index, __mmask8 __mask,
|
||||||
|
void const *__addr, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfqpd (__mask, (__v8di) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i64gather_ps (__m512i __index, __mmask8 __mask,
|
||||||
|
void const *__addr, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_gatherpfqps (__mask, (__v8di) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i32scatter_pd (void *__addr, __m256i __index, int __scale,
|
||||||
|
int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfdpd ((__mmask8) 0xFF, (__v8si) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i32scatter_ps (void *__addr, __m512i __index, int __scale,
|
||||||
|
int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfdps ((__mmask16) 0xFFFF, (__v16si) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i32scatter_pd (void *__addr, __mmask8 __mask,
|
||||||
|
__m256i __index, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfdpd (__mask, (__v8si) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i32scatter_ps (void *__addr, __mmask16 __mask,
|
||||||
|
__m512i __index, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfdps (__mask, (__v16si) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i64scatter_pd (void *__addr, __m512i __index, int __scale,
|
||||||
|
int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfqpd ((__mmask8) 0xFF, (__v8di) __index,__addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_prefetch_i64scatter_ps (void *__addr, __m512i __index, int __scale,
|
||||||
|
int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfqps ((__mmask8) 0xFF, (__v8di) __index, __addr,
|
||||||
|
__scale, __hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i64scatter_pd (void *__addr, __mmask8 __mask,
|
||||||
|
__m512i __index, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfqpd (__mask, (__v8di) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_prefetch_i64scatter_ps (void *__addr, __mmask8 __mask,
|
||||||
|
__m512i __index, int __scale, int __hint)
|
||||||
|
{
|
||||||
|
__builtin_ia32_scatterpfqps (__mask, (__v8di) __index, __addr, __scale,
|
||||||
|
__hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define _mm512_prefetch_i32gather_pd(INDEX, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfdpd ((__mmask8)0xFF, (__v8si)(__m256i) (INDEX), \
|
||||||
|
(void const *) (ADDR), (int) (SCALE), \
|
||||||
|
(int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i32gather_ps(INDEX, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfdps ((__mmask16)0xFFFF, (__v16si)(__m512i) (INDEX), \
|
||||||
|
(void const *) (ADDR), (int) (SCALE), \
|
||||||
|
(int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i32gather_pd(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfdpd ((__mmask8) (MASK), (__v8si)(__m256i) (INDEX), \
|
||||||
|
(void const *) (ADDR), (int) (SCALE), \
|
||||||
|
(int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i32gather_ps(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfdps ((__mmask16) (MASK), (__v16si)(__m512i) (INDEX),\
|
||||||
|
(void const *) (ADDR), (int) (SCALE), \
|
||||||
|
(int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i64gather_pd(INDEX, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfqpd ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i64gather_ps(INDEX, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfqps ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i64gather_pd(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfqpd ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i64gather_ps(INDEX, MASK, ADDR, SCALE, HINT) \
|
||||||
|
__builtin_ia32_gatherpfqps ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i32scatter_pd(ADDR, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfdpd ((__mmask8)0xFF, (__v8si)(__m256i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i32scatter_ps(ADDR, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfdps ((__mmask16)0xFFFF, (__v16si)(__m512i) (INDEX),\
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i32scatter_pd(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfdpd ((__mmask8) (MASK), (__v8si)(__m256i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i32scatter_ps(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfdps ((__mmask16) (MASK), \
|
||||||
|
(__v16si)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i64scatter_pd(ADDR, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfqpd ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_prefetch_i64scatter_ps(ADDR, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfqps ((__mmask8)0xFF, (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i64scatter_pd(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfqpd ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
|
||||||
|
#define _mm512_mask_prefetch_i64scatter_ps(ADDR, MASK, INDEX, SCALE, HINT) \
|
||||||
|
__builtin_ia32_scatterpfqps ((__mmask8) (MASK), (__v8di)(__m512i) (INDEX), \
|
||||||
|
(void *) (ADDR), (int) (SCALE), (int) (HINT))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512PF__
|
||||||
|
#undef __DISABLE_AVX512PF__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512PF__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512PFINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,545 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vbmi2intrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __AVX512VBMI2INTRIN_H_INCLUDED
|
||||||
|
#define __AVX512VBMI2INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VBMI2__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vbmi2,evex512")
|
||||||
|
#define __DISABLE_AVX512VBMI2__
|
||||||
|
#endif /* __AVX512VBMI2__ */
|
||||||
|
|
||||||
|
#ifdef __OPTIMIZE__
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shrdi_epi16 (__m512i __A, __m512i __B, int __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshrd_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||||
|
__C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shrdi_epi32 (__m512i __A, __m512i __B, int __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshrd_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
__C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shrdi_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D,
|
||||||
|
int __E)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrd_v16si_mask ((__v16si)__C,
|
||||||
|
(__v16si) __D, __E, (__v16si) __A, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shrdi_epi32 (__mmask16 __A, __m512i __B, __m512i __C, int __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrd_v16si_mask ((__v16si)__B,
|
||||||
|
(__v16si) __C, __D, (__v16si) _mm512_setzero_si512 (), (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shrdi_epi64 (__m512i __A, __m512i __B, int __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshrd_v8di ((__v8di)__A, (__v8di) __B, __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shrdi_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D,
|
||||||
|
int __E)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrd_v8di_mask ((__v8di)__C, (__v8di) __D,
|
||||||
|
__E, (__v8di) __A, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shrdi_epi64 (__mmask8 __A, __m512i __B, __m512i __C, int __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrd_v8di_mask ((__v8di)__B, (__v8di) __C,
|
||||||
|
__D, (__v8di) _mm512_setzero_si512 (), (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shldi_epi16 (__m512i __A, __m512i __B, int __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshld_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||||
|
__C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shldi_epi32 (__m512i __A, __m512i __B, int __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshld_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
__C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shldi_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D,
|
||||||
|
int __E)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshld_v16si_mask ((__v16si)__C,
|
||||||
|
(__v16si) __D, __E, (__v16si) __A, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shldi_epi32 (__mmask16 __A, __m512i __B, __m512i __C, int __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshld_v16si_mask ((__v16si)__B,
|
||||||
|
(__v16si) __C, __D, (__v16si) _mm512_setzero_si512 (), (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shldi_epi64 (__m512i __A, __m512i __B, int __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshld_v8di ((__v8di)__A, (__v8di) __B, __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shldi_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D,
|
||||||
|
int __E)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshld_v8di_mask ((__v8di)__C, (__v8di) __D,
|
||||||
|
__E, (__v8di) __A, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shldi_epi64 (__mmask8 __A, __m512i __B, __m512i __C, int __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshld_v8di_mask ((__v8di)__B, (__v8di) __C,
|
||||||
|
__D, (__v8di) _mm512_setzero_si512 (), (__mmask8)__A);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define _mm512_shrdi_epi16(A, B, C) \
|
||||||
|
((__m512i) __builtin_ia32_vpshrd_v32hi ((__v32hi)(__m512i)(A), \
|
||||||
|
(__v32hi)(__m512i)(B),(int)(C)))
|
||||||
|
#define _mm512_shrdi_epi32(A, B, C) \
|
||||||
|
((__m512i) __builtin_ia32_vpshrd_v16si ((__v16si)(__m512i)(A), \
|
||||||
|
(__v16si)(__m512i)(B),(int)(C)))
|
||||||
|
#define _mm512_mask_shrdi_epi32(A, B, C, D, E) \
|
||||||
|
((__m512i) __builtin_ia32_vpshrd_v16si_mask ((__v16si)(__m512i)(C), \
|
||||||
|
(__v16si)(__m512i)(D), \
|
||||||
|
(int)(E), \
|
||||||
|
(__v16si)(__m512i)(A), \
|
||||||
|
(__mmask16)(B)))
|
||||||
|
#define _mm512_maskz_shrdi_epi32(A, B, C, D) \
|
||||||
|
((__m512i) \
|
||||||
|
__builtin_ia32_vpshrd_v16si_mask ((__v16si)(__m512i)(B), \
|
||||||
|
(__v16si)(__m512i)(C),(int)(D), \
|
||||||
|
(__v16si)(__m512i)_mm512_setzero_si512 (), \
|
||||||
|
(__mmask16)(A)))
|
||||||
|
#define _mm512_shrdi_epi64(A, B, C) \
|
||||||
|
((__m512i) __builtin_ia32_vpshrd_v8di ((__v8di)(__m512i)(A), \
|
||||||
|
(__v8di)(__m512i)(B),(int)(C)))
|
||||||
|
#define _mm512_mask_shrdi_epi64(A, B, C, D, E) \
|
||||||
|
((__m512i) __builtin_ia32_vpshrd_v8di_mask ((__v8di)(__m512i)(C), \
|
||||||
|
(__v8di)(__m512i)(D), (int)(E), \
|
||||||
|
(__v8di)(__m512i)(A), \
|
||||||
|
(__mmask8)(B)))
|
||||||
|
#define _mm512_maskz_shrdi_epi64(A, B, C, D) \
|
||||||
|
((__m512i) \
|
||||||
|
__builtin_ia32_vpshrd_v8di_mask ((__v8di)(__m512i)(B), \
|
||||||
|
(__v8di)(__m512i)(C),(int)(D), \
|
||||||
|
(__v8di)(__m512i)_mm512_setzero_si512 (), \
|
||||||
|
(__mmask8)(A)))
|
||||||
|
#define _mm512_shldi_epi16(A, B, C) \
|
||||||
|
((__m512i) __builtin_ia32_vpshld_v32hi ((__v32hi)(__m512i)(A), \
|
||||||
|
(__v32hi)(__m512i)(B),(int)(C)))
|
||||||
|
#define _mm512_shldi_epi32(A, B, C) \
|
||||||
|
((__m512i) __builtin_ia32_vpshld_v16si ((__v16si)(__m512i)(A), \
|
||||||
|
(__v16si)(__m512i)(B),(int)(C)))
|
||||||
|
#define _mm512_mask_shldi_epi32(A, B, C, D, E) \
|
||||||
|
((__m512i) __builtin_ia32_vpshld_v16si_mask ((__v16si)(__m512i)(C), \
|
||||||
|
(__v16si)(__m512i)(D), \
|
||||||
|
(int)(E), \
|
||||||
|
(__v16si)(__m512i)(A), \
|
||||||
|
(__mmask16)(B)))
|
||||||
|
#define _mm512_maskz_shldi_epi32(A, B, C, D) \
|
||||||
|
((__m512i) \
|
||||||
|
__builtin_ia32_vpshld_v16si_mask ((__v16si)(__m512i)(B), \
|
||||||
|
(__v16si)(__m512i)(C),(int)(D), \
|
||||||
|
(__v16si)(__m512i)_mm512_setzero_si512 (), \
|
||||||
|
(__mmask16)(A)))
|
||||||
|
#define _mm512_shldi_epi64(A, B, C) \
|
||||||
|
((__m512i) __builtin_ia32_vpshld_v8di ((__v8di)(__m512i)(A), \
|
||||||
|
(__v8di)(__m512i)(B), (int)(C)))
|
||||||
|
#define _mm512_mask_shldi_epi64(A, B, C, D, E) \
|
||||||
|
((__m512i) __builtin_ia32_vpshld_v8di_mask ((__v8di)(__m512i)(C), \
|
||||||
|
(__v8di)(__m512i)(D), (int)(E), \
|
||||||
|
(__v8di)(__m512i)(A), \
|
||||||
|
(__mmask8)(B)))
|
||||||
|
#define _mm512_maskz_shldi_epi64(A, B, C, D) \
|
||||||
|
((__m512i) \
|
||||||
|
__builtin_ia32_vpshld_v8di_mask ((__v8di)(__m512i)(B), \
|
||||||
|
(__v8di)(__m512i)(C),(int)(D), \
|
||||||
|
(__v8di)(__m512i)_mm512_setzero_si512 (), \
|
||||||
|
(__mmask8)(A)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shrdv_epi16 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshrdv_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||||
|
(__v32hi) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shrdv_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshrdv_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
(__v16si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shrdv_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrdv_v16si_mask ((__v16si)__A,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shrdv_epi32 (__mmask16 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrdv_v16si_maskz ((__v16si)__B,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shrdv_epi64 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshrdv_v8di ((__v8di)__A, (__v8di) __B,
|
||||||
|
(__v8di) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shrdv_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrdv_v8di_mask ((__v8di)__A, (__v8di) __C,
|
||||||
|
(__v8di) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shrdv_epi64 (__mmask8 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrdv_v8di_maskz ((__v8di)__B, (__v8di) __C,
|
||||||
|
(__v8di) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shldv_epi16 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshldv_v32hi ((__v32hi)__A, (__v32hi) __B,
|
||||||
|
(__v32hi) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shldv_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshldv_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
(__v16si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shldv_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshldv_v16si_mask ((__v16si)__A,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shldv_epi32 (__mmask16 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshldv_v16si_maskz ((__v16si)__B,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_shldv_epi64 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpshldv_v8di ((__v8di)__A, (__v8di) __B,
|
||||||
|
(__v8di) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shldv_epi64 (__m512i __A, __mmask8 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshldv_v8di_mask ((__v8di)__A, (__v8di) __C,
|
||||||
|
(__v8di) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shldv_epi64 (__mmask8 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshldv_v8di_maskz ((__v8di)__B, (__v8di) __C,
|
||||||
|
(__v8di) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_compress_epi8 (__m512i __A, __mmask64 __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi)__C,
|
||||||
|
(__v64qi)__A, (__mmask64)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_compress_epi8 (__mmask64 __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_compressqi512_mask ((__v64qi)__B,
|
||||||
|
(__v64qi)_mm512_setzero_si512 (), (__mmask64)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_compressstoreu_epi8 (void * __A, __mmask64 __B, __m512i __C)
|
||||||
|
{
|
||||||
|
__builtin_ia32_compressstoreuqi512_mask ((__v64qi *) __A, (__v64qi) __C,
|
||||||
|
(__mmask64) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_compress_epi16 (__m512i __A, __mmask32 __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi)__C,
|
||||||
|
(__v32hi)__A, (__mmask32)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_compress_epi16 (__mmask32 __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_compresshi512_mask ((__v32hi)__B,
|
||||||
|
(__v32hi)_mm512_setzero_si512 (), (__mmask32)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_compressstoreu_epi16 (void * __A, __mmask32 __B, __m512i __C)
|
||||||
|
{
|
||||||
|
__builtin_ia32_compressstoreuhi512_mask ((__v32hi *) __A, (__v32hi) __C,
|
||||||
|
(__mmask32) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_expand_epi8 (__m512i __A, __mmask64 __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandqi512_mask ((__v64qi) __C,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__mmask64) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_expand_epi8 (__mmask64 __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandqi512_maskz ((__v64qi) __B,
|
||||||
|
(__v64qi) _mm512_setzero_si512 (), (__mmask64) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_expandloadu_epi8 (__m512i __A, __mmask64 __B, const void * __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandloadqi512_mask ((const __v64qi *) __C,
|
||||||
|
(__v64qi) __A, (__mmask64) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_expandloadu_epi8 (__mmask64 __A, const void * __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandloadqi512_maskz ((const __v64qi *) __B,
|
||||||
|
(__v64qi) _mm512_setzero_si512 (), (__mmask64) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_expand_epi16 (__m512i __A, __mmask32 __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandhi512_mask ((__v32hi) __C,
|
||||||
|
(__v32hi) __A,
|
||||||
|
(__mmask32) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_expand_epi16 (__mmask32 __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandhi512_maskz ((__v32hi) __B,
|
||||||
|
(__v32hi) _mm512_setzero_si512 (), (__mmask32) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_expandloadu_epi16 (__m512i __A, __mmask32 __B, const void * __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandloadhi512_mask ((const __v32hi *) __C,
|
||||||
|
(__v32hi) __A, (__mmask32) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_expandloadu_epi16 (__mmask32 __A, const void * __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_expandloadhi512_maskz ((const __v32hi *) __B,
|
||||||
|
(__v32hi) _mm512_setzero_si512 (), (__mmask32) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __OPTIMIZE__
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shrdi_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D,
|
||||||
|
int __E)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)__C,
|
||||||
|
(__v32hi) __D, __E, (__v32hi) __A, (__mmask32)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shrdi_epi16 (__mmask32 __A, __m512i __B, __m512i __C, int __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)__B,
|
||||||
|
(__v32hi) __C, __D, (__v32hi) _mm512_setzero_si512 (), (__mmask32)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shldi_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D,
|
||||||
|
int __E)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshld_v32hi_mask ((__v32hi)__C,
|
||||||
|
(__v32hi) __D, __E, (__v32hi) __A, (__mmask32)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shldi_epi16 (__mmask32 __A, __m512i __B, __m512i __C, int __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshld_v32hi_mask ((__v32hi)__B,
|
||||||
|
(__v32hi) __C, __D, (__v32hi) _mm512_setzero_si512 (), (__mmask32)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define _mm512_mask_shrdi_epi16(A, B, C, D, E) \
|
||||||
|
((__m512i) __builtin_ia32_vpshrd_v32hi_mask ((__v32hi)(__m512i)(C), \
|
||||||
|
(__v32hi)(__m512i)(D), \
|
||||||
|
(int)(E), \
|
||||||
|
(__v32hi)(__m512i)(A), \
|
||||||
|
(__mmask32)(B)))
|
||||||
|
#define _mm512_maskz_shrdi_epi16(A, B, C, D) \
|
||||||
|
((__m512i) \
|
||||||
|
__builtin_ia32_vpshrd_v32hi_mask ((__v32hi)(__m512i)(B), \
|
||||||
|
(__v32hi)(__m512i)(C),(int)(D), \
|
||||||
|
(__v32hi)(__m512i)_mm512_setzero_si512 (), \
|
||||||
|
(__mmask32)(A)))
|
||||||
|
#define _mm512_mask_shldi_epi16(A, B, C, D, E) \
|
||||||
|
((__m512i) __builtin_ia32_vpshld_v32hi_mask ((__v32hi)(__m512i)(C), \
|
||||||
|
(__v32hi)(__m512i)(D), \
|
||||||
|
(int)(E), \
|
||||||
|
(__v32hi)(__m512i)(A), \
|
||||||
|
(__mmask32)(B)))
|
||||||
|
#define _mm512_maskz_shldi_epi16(A, B, C, D) \
|
||||||
|
((__m512i) \
|
||||||
|
__builtin_ia32_vpshld_v32hi_mask ((__v32hi)(__m512i)(B), \
|
||||||
|
(__v32hi)(__m512i)(C),(int)(D), \
|
||||||
|
(__v32hi)(__m512i)_mm512_setzero_si512 (), \
|
||||||
|
(__mmask32)(A)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shrdv_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrdv_v32hi_mask ((__v32hi)__A,
|
||||||
|
(__v32hi) __C, (__v32hi) __D, (__mmask32)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shrdv_epi16 (__mmask32 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshrdv_v32hi_maskz ((__v32hi)__B,
|
||||||
|
(__v32hi) __C, (__v32hi) __D, (__mmask32)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_shldv_epi16 (__m512i __A, __mmask32 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshldv_v32hi_mask ((__v32hi)__A,
|
||||||
|
(__v32hi) __C, (__v32hi) __D, (__mmask32)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_shldv_epi16 (__mmask32 __A, __m512i __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpshldv_v32hi_maskz ((__v32hi)__B,
|
||||||
|
(__v32hi) __C, (__v32hi) __D, (__mmask32)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VBMI2__
|
||||||
|
#undef __DISABLE_AVX512VBMI2__
|
||||||
|
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VBMI2__ */
|
||||||
|
|
||||||
|
#endif /* __AVX512VBMI2INTRIN_H_INCLUDED */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vbmiintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VBMIINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VBMIINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined (__AVX512VBMI__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vbmi,evex512")
|
||||||
|
#define __DISABLE_AVX512VBMI__
|
||||||
|
#endif /* __AVX512VBMI__ */
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_multishift_epi64_epi8 (__m512i __W, __mmask64 __M, __m512i __X, __m512i __Y)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
|
||||||
|
(__v64qi) __Y,
|
||||||
|
(__v64qi) __W,
|
||||||
|
(__mmask64) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_multishift_epi64_epi8 (__mmask64 __M, __m512i __X, __m512i __Y)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
|
||||||
|
(__v64qi) __Y,
|
||||||
|
(__v64qi)
|
||||||
|
_mm512_setzero_si512 (),
|
||||||
|
(__mmask64) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_multishift_epi64_epi8 (__m512i __X, __m512i __Y)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpmultishiftqb512_mask ((__v64qi) __X,
|
||||||
|
(__v64qi) __Y,
|
||||||
|
(__v64qi)
|
||||||
|
_mm512_undefined_epi32 (),
|
||||||
|
(__mmask64) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_permutexvar_epi8 (__m512i __A, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__v64qi)
|
||||||
|
_mm512_undefined_epi32 (),
|
||||||
|
(__mmask64) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_permutexvar_epi8 (__mmask64 __M, __m512i __A,
|
||||||
|
__m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__v64qi)
|
||||||
|
_mm512_setzero_si512(),
|
||||||
|
(__mmask64) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_permutexvar_epi8 (__m512i __W, __mmask64 __M, __m512i __A,
|
||||||
|
__m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_permvarqi512_mask ((__v64qi) __B,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__v64qi) __W,
|
||||||
|
(__mmask64) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_permutex2var_epi8 (__m512i __A, __m512i __I, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__v64qi) __B,
|
||||||
|
(__mmask64) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_permutex2var_epi8 (__m512i __A, __mmask64 __U,
|
||||||
|
__m512i __I, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpermt2varqi512_mask ((__v64qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__v64qi) __B,
|
||||||
|
(__mmask64)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask2_permutex2var_epi8 (__m512i __A, __m512i __I,
|
||||||
|
__mmask64 __U, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpermi2varqi512_mask ((__v64qi) __A,
|
||||||
|
(__v64qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v64qi) __B,
|
||||||
|
(__mmask64)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_permutex2var_epi8 (__mmask64 __U, __m512i __A,
|
||||||
|
__m512i __I, __m512i __B)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpermt2varqi512_maskz ((__v64qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v64qi) __A,
|
||||||
|
(__v64qi) __B,
|
||||||
|
(__mmask64)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VBMI__
|
||||||
|
#undef __DISABLE_AVX512VBMI__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VBMI__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512VBMIINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vbmivlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VBMIVLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VBMIVLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VL__) || !defined(__AVX512VBMI__) || defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vbmi,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512VBMIVL__
|
||||||
|
#endif /* __AVX512VBMIVL__ */
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_multishift_epi64_epi8 (__m256i __W, __mmask32 __M, __m256i __X, __m256i __Y)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
|
||||||
|
(__v32qi) __Y,
|
||||||
|
(__v32qi) __W,
|
||||||
|
(__mmask32) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_multishift_epi64_epi8 (__mmask32 __M, __m256i __X, __m256i __Y)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
|
||||||
|
(__v32qi) __Y,
|
||||||
|
(__v32qi)
|
||||||
|
_mm256_avx512_setzero_si256 (),
|
||||||
|
(__mmask32) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_multishift_epi64_epi8 (__m256i __X, __m256i __Y)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmultishiftqb256_mask ((__v32qi) __X,
|
||||||
|
(__v32qi) __Y,
|
||||||
|
(__v32qi)
|
||||||
|
_mm256_avx512_undefined_si256 (),
|
||||||
|
(__mmask32) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_multishift_epi64_epi8 (__m128i __W, __mmask16 __M, __m128i __X, __m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
|
||||||
|
(__v16qi) __Y,
|
||||||
|
(__v16qi) __W,
|
||||||
|
(__mmask16) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_multishift_epi64_epi8 (__mmask16 __M, __m128i __X, __m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
|
||||||
|
(__v16qi) __Y,
|
||||||
|
(__v16qi)
|
||||||
|
_mm_avx512_setzero_si128 (),
|
||||||
|
(__mmask16) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_multishift_epi64_epi8 (__m128i __X, __m128i __Y)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmultishiftqb128_mask ((__v16qi) __X,
|
||||||
|
(__v16qi) __Y,
|
||||||
|
(__v16qi)
|
||||||
|
_mm_avx512_undefined_si128 (),
|
||||||
|
(__mmask16) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_permutexvar_epi8 (__m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
|
||||||
|
(__v32qi) __A,
|
||||||
|
(__v32qi)
|
||||||
|
_mm256_avx512_undefined_si256 (),
|
||||||
|
(__mmask32) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_permutexvar_epi8 (__mmask32 __M, __m256i __A,
|
||||||
|
__m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
|
||||||
|
(__v32qi) __A,
|
||||||
|
(__v32qi)
|
||||||
|
_mm256_avx512_setzero_si256 (),
|
||||||
|
(__mmask32) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_permutexvar_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
|
||||||
|
__m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_permvarqi256_mask ((__v32qi) __B,
|
||||||
|
(__v32qi) __A,
|
||||||
|
(__v32qi) __W,
|
||||||
|
(__mmask32) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_permutexvar_epi8 (__m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
|
||||||
|
(__v16qi) __A,
|
||||||
|
(__v16qi)
|
||||||
|
_mm_avx512_undefined_si128 (),
|
||||||
|
(__mmask16) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_permutexvar_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
|
||||||
|
(__v16qi) __A,
|
||||||
|
(__v16qi)
|
||||||
|
_mm_avx512_setzero_si128 (),
|
||||||
|
(__mmask16) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_permutexvar_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
|
||||||
|
__m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_permvarqi128_mask ((__v16qi) __B,
|
||||||
|
(__v16qi) __A,
|
||||||
|
(__v16qi) __W,
|
||||||
|
(__mmask16) __M);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_permutex2var_epi8 (__m256i __A, __m256i __I, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v32qi) __A,
|
||||||
|
(__v32qi) __B,
|
||||||
|
(__mmask32) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_permutex2var_epi8 (__m256i __A, __mmask32 __U,
|
||||||
|
__m256i __I, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpermt2varqi256_mask ((__v32qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v32qi) __A,
|
||||||
|
(__v32qi) __B,
|
||||||
|
(__mmask32)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask2_permutex2var_epi8 (__m256i __A, __m256i __I,
|
||||||
|
__mmask32 __U, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpermi2varqi256_mask ((__v32qi) __A,
|
||||||
|
(__v32qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v32qi) __B,
|
||||||
|
(__mmask32)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_permutex2var_epi8 (__mmask32 __U, __m256i __A,
|
||||||
|
__m256i __I, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpermt2varqi256_maskz ((__v32qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v32qi) __A,
|
||||||
|
(__v32qi) __B,
|
||||||
|
(__mmask32)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_permutex2var_epi8 (__m128i __A, __m128i __I, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v16qi) __A,
|
||||||
|
(__v16qi) __B,
|
||||||
|
(__mmask16) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_permutex2var_epi8 (__m128i __A, __mmask16 __U, __m128i __I,
|
||||||
|
__m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpermt2varqi128_mask ((__v16qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v16qi) __A,
|
||||||
|
(__v16qi) __B,
|
||||||
|
(__mmask16)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask2_permutex2var_epi8 (__m128i __A, __m128i __I, __mmask16 __U,
|
||||||
|
__m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpermi2varqi128_mask ((__v16qi) __A,
|
||||||
|
(__v16qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v16qi) __B,
|
||||||
|
(__mmask16)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_permutex2var_epi8 (__mmask16 __U, __m128i __A, __m128i __I,
|
||||||
|
__m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpermt2varqi128_maskz ((__v16qi) __I
|
||||||
|
/* idx */ ,
|
||||||
|
(__v16qi) __A,
|
||||||
|
(__v16qi) __B,
|
||||||
|
(__mmask16)
|
||||||
|
__U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VBMIVL__
|
||||||
|
#undef __DISABLE_AVX512VBMIVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VBMIVL__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512VBMIVLINTRIN_H_INCLUDED */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,144 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vnniintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __AVX512VNNIINTRIN_H_INCLUDED
|
||||||
|
#define __AVX512VNNIINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VNNI__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vnni,evex512")
|
||||||
|
#define __DISABLE_AVX512VNNI__
|
||||||
|
#endif /* __AVX512VNNI__ */
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_dpbusd_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpdpbusd_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
(__v16si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_dpbusd_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpbusd_v16si_mask ((__v16si)__A,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_dpbusd_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||||
|
__m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpbusd_v16si_maskz ((__v16si)__B,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_dpbusds_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpdpbusds_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
(__v16si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_dpbusds_epi32 (__m512i __A, __mmask16 __B, __m512i __C,
|
||||||
|
__m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpbusds_v16si_mask ((__v16si)__A,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_dpbusds_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||||
|
__m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpbusds_v16si_maskz ((__v16si)__B,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_dpwssd_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpdpwssd_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
(__v16si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_dpwssd_epi32 (__m512i __A, __mmask16 __B, __m512i __C, __m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpwssd_v16si_mask ((__v16si)__A,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_dpwssd_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||||
|
__m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpwssd_v16si_maskz ((__v16si)__B,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_dpwssds_epi32 (__m512i __A, __m512i __B, __m512i __C)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpdpwssds_v16si ((__v16si)__A, (__v16si) __B,
|
||||||
|
(__v16si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_dpwssds_epi32 (__m512i __A, __mmask16 __B, __m512i __C,
|
||||||
|
__m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpwssds_v16si_mask ((__v16si)__A,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_dpwssds_epi32 (__mmask16 __A, __m512i __B, __m512i __C,
|
||||||
|
__m512i __D)
|
||||||
|
{
|
||||||
|
return (__m512i)__builtin_ia32_vpdpwssds_v16si_maskz ((__v16si)__B,
|
||||||
|
(__v16si) __C, (__v16si) __D, (__mmask16)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VNNI__
|
||||||
|
#undef __DISABLE_AVX512VNNI__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VNNI__ */
|
||||||
|
|
||||||
|
#endif /* __AVX512VNNIINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/* Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vnnivlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VNNIVLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VNNIVLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VL__) || !defined(__AVX512VNNI__) || defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vnni,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512VNNIVL__
|
||||||
|
#endif /* __AVX512VNNIVL__ */
|
||||||
|
|
||||||
|
#define _mm256_dpbusd_epi32(A, B, C) \
|
||||||
|
((__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) (A), \
|
||||||
|
(__v8si) (B), \
|
||||||
|
(__v8si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_dpbusd_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpbusd_v8si_mask ((__v8si)__A, (__v8si) __C,
|
||||||
|
(__v8si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_dpbusd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpbusd_v8si_maskz ((__v8si)__B,
|
||||||
|
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm_dpbusd_epi32(A, B, C) \
|
||||||
|
((__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) (A), \
|
||||||
|
(__v4si) (B), \
|
||||||
|
(__v4si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_dpbusd_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpbusd_v4si_mask ((__v4si)__A, (__v4si) __C,
|
||||||
|
(__v4si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_dpbusd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpbusd_v4si_maskz ((__v4si)__B,
|
||||||
|
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm256_dpbusds_epi32(A, B, C) \
|
||||||
|
((__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) (A), \
|
||||||
|
(__v8si) (B), \
|
||||||
|
(__v8si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_dpbusds_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpbusds_v8si_mask ((__v8si)__A,
|
||||||
|
(__v8si) __C, (__v8si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_dpbusds_epi32 (__mmask8 __A, __m256i __B, __m256i __C,
|
||||||
|
__m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpbusds_v8si_maskz ((__v8si)__B,
|
||||||
|
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm_dpbusds_epi32(A, B, C) \
|
||||||
|
((__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) (A), \
|
||||||
|
(__v4si) (B), \
|
||||||
|
(__v4si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_dpbusds_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpbusds_v4si_mask ((__v4si)__A,
|
||||||
|
(__v4si) __C, (__v4si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_dpbusds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpbusds_v4si_maskz ((__v4si)__B,
|
||||||
|
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm256_dpwssd_epi32(A, B, C) \
|
||||||
|
((__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) (A), \
|
||||||
|
(__v8si) (B), \
|
||||||
|
(__v8si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_dpwssd_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpwssd_v8si_mask ((__v8si)__A, (__v8si) __C,
|
||||||
|
(__v8si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_dpwssd_epi32 (__mmask8 __A, __m256i __B, __m256i __C, __m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpwssd_v8si_maskz ((__v8si)__B,
|
||||||
|
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm_dpwssd_epi32(A, B, C) \
|
||||||
|
((__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) (A), \
|
||||||
|
(__v4si) (B), \
|
||||||
|
(__v4si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_dpwssd_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpwssd_v4si_mask ((__v4si)__A, (__v4si) __C,
|
||||||
|
(__v4si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_dpwssd_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpwssd_v4si_maskz ((__v4si)__B,
|
||||||
|
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm256_dpwssds_epi32(A, B, C) \
|
||||||
|
((__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) (A), \
|
||||||
|
(__v8si) (B), \
|
||||||
|
(__v8si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_dpwssds_epi32 (__m256i __A, __mmask8 __B, __m256i __C, __m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpwssds_v8si_mask ((__v8si)__A,
|
||||||
|
(__v8si) __C, (__v8si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_dpwssds_epi32 (__mmask8 __A, __m256i __B, __m256i __C,
|
||||||
|
__m256i __D)
|
||||||
|
{
|
||||||
|
return (__m256i)__builtin_ia32_vpdpwssds_v8si_maskz ((__v8si)__B,
|
||||||
|
(__v8si) __C, (__v8si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _mm_dpwssds_epi32(A, B, C) \
|
||||||
|
((__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) (A), \
|
||||||
|
(__v4si) (B), \
|
||||||
|
(__v4si) (C)))
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_dpwssds_epi32 (__m128i __A, __mmask8 __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpwssds_v4si_mask ((__v4si)__A,
|
||||||
|
(__v4si) __C, (__v4si) __D, (__mmask8)__B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_dpwssds_epi32 (__mmask8 __A, __m128i __B, __m128i __C, __m128i __D)
|
||||||
|
{
|
||||||
|
return (__m128i)__builtin_ia32_vpdpwssds_v4si_maskz ((__v4si)__B,
|
||||||
|
(__v4si) __C, (__v4si) __D, (__mmask8)__A);
|
||||||
|
}
|
||||||
|
#ifdef __DISABLE_AVX512VNNIVL__
|
||||||
|
#undef __DISABLE_AVX512VNNIVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VNNIVL__ */
|
||||||
|
#endif /* __DISABLE_AVX512VNNIVL__ */
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vp2intersectintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VP2INTERSECTINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VP2INTERSECTINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VP2INTERSECT__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vp2intersect,evex512")
|
||||||
|
#define __DISABLE_AVX512VP2INTERSECT__
|
||||||
|
#endif /* __AVX512VP2INTERSECT__ */
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_2intersect_epi32 (__m512i __A, __m512i __B, __mmask16 *__U,
|
||||||
|
__mmask16 *__M)
|
||||||
|
{
|
||||||
|
__builtin_ia32_2intersectd512 (__U, __M, (__v16si) __A, (__v16si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_2intersect_epi64 (__m512i __A, __m512i __B, __mmask8 *__U,
|
||||||
|
__mmask8 *__M)
|
||||||
|
{
|
||||||
|
__builtin_ia32_2intersectq512 (__U, __M, (__v8di) __A, (__v8di) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VP2INTERSECT__
|
||||||
|
#undef __DISABLE_AVX512VP2INTERSECT__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VP2INTERSECT__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512VP2INTERSECTINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/* Copyright (C) 2019-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avx512vp2intersectintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VP2INTERSECT__) || !defined(__AVX512VL__) \
|
||||||
|
|| defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vp2intersect,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512VP2INTERSECTVL__
|
||||||
|
#endif /* __AVX512VP2INTERSECTVL__ */
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_2intersect_epi32 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M)
|
||||||
|
{
|
||||||
|
__builtin_ia32_2intersectd128 (__U, __M, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_2intersect_epi32 (__m256i __A, __m256i __B, __mmask8 *__U,
|
||||||
|
__mmask8 *__M)
|
||||||
|
{
|
||||||
|
__builtin_ia32_2intersectd256 (__U, __M, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_2intersect_epi64 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M)
|
||||||
|
{
|
||||||
|
__builtin_ia32_2intersectq128 (__U, __M, (__v2di) __A, (__v2di) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline void
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_2intersect_epi64 (__m256i __A, __m256i __B, __mmask8 *__U,
|
||||||
|
__mmask8 *__M)
|
||||||
|
{
|
||||||
|
__builtin_ia32_2intersectq256 (__U, __M, (__v4di) __A, (__v4di) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VP2INTERSECTVL__
|
||||||
|
#undef __DISABLE_AVX512VP2INTERSECTVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VP2INTERSECTVL__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <avx512vpopcntdqintrin.h> directly; include <x86intrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VPOPCNTDQINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VPOPCNTDQINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined (__AVX512VPOPCNTDQ__) || !defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vpopcntdq,evex512")
|
||||||
|
#define __DISABLE_AVX512VPOPCNTDQ__
|
||||||
|
#endif /* __AVX512VPOPCNTDQ__ */
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_popcnt_epi32 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountd_v16si ((__v16si) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_popcnt_epi32 (__m512i __W, __mmask16 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountd_v16si_mask ((__v16si) __A,
|
||||||
|
(__v16si) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_popcnt_epi32 (__mmask16 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountd_v16si_mask ((__v16si) __A,
|
||||||
|
(__v16si)
|
||||||
|
_mm512_setzero_si512 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_popcnt_epi64 (__m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountq_v8di ((__v8di) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_mask_popcnt_epi64 (__m512i __W, __mmask8 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountq_v8di_mask ((__v8di) __A,
|
||||||
|
(__v8di) __W,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m512i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm512_maskz_popcnt_epi64 (__mmask8 __U, __m512i __A)
|
||||||
|
{
|
||||||
|
return (__m512i) __builtin_ia32_vpopcountq_v8di_mask ((__v8di) __A,
|
||||||
|
(__v8di)
|
||||||
|
_mm512_setzero_si512 (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VPOPCNTDQ__
|
||||||
|
#undef __DISABLE_AVX512VPOPCNTDQ__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VPOPCNTDQ__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512VPOPCNTDQINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/* Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
# error "Never use <avx512vpopcntdqvlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED
|
||||||
|
#define _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVX512VPOPCNTDQ__) || !defined(__AVX512VL__) \
|
||||||
|
|| defined (__EVEX512__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avx512vpopcntdq,avx512vl,no-evex512")
|
||||||
|
#define __DISABLE_AVX512VPOPCNTDQVL__
|
||||||
|
#endif /* __AVX512VPOPCNTDQVL__ */
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_popcnt_epi32 (__m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountd_v4si ((__v4si) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_popcnt_epi32 (__m128i __W, __mmask16 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountd_v4si_mask ((__v4si) __A,
|
||||||
|
(__v4si) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_popcnt_epi32 (__mmask16 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountd_v4si_mask ((__v4si) __A,
|
||||||
|
(__v4si)
|
||||||
|
_mm_avx512_setzero_si128 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_popcnt_epi32 (__m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountd_v8si ((__v8si) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_popcnt_epi32 (__m256i __W, __mmask16 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountd_v8si_mask ((__v8si) __A,
|
||||||
|
(__v8si) __W,
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_popcnt_epi32 (__mmask16 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountd_v8si_mask ((__v8si) __A,
|
||||||
|
(__v8si)
|
||||||
|
_mm256_avx512_setzero_si256 (),
|
||||||
|
(__mmask16) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_popcnt_epi64 (__m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountq_v2di ((__v2di) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_mask_popcnt_epi64 (__m128i __W, __mmask8 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountq_v2di_mask ((__v2di) __A,
|
||||||
|
(__v2di) __W,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_maskz_popcnt_epi64 (__mmask8 __U, __m128i __A)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpopcountq_v2di_mask ((__v2di) __A,
|
||||||
|
(__v2di)
|
||||||
|
_mm_avx512_setzero_si128 (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_popcnt_epi64 (__m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountq_v4di ((__v4di) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_mask_popcnt_epi64 (__m256i __W, __mmask8 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountq_v4di_mask ((__v4di) __A,
|
||||||
|
(__v4di) __W,
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_maskz_popcnt_epi64 (__mmask8 __U, __m256i __A)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpopcountq_v4di_mask ((__v4di) __A,
|
||||||
|
(__v4di)
|
||||||
|
_mm256_avx512_setzero_si256 (),
|
||||||
|
(__mmask8) __U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVX512VPOPCNTDQVL__
|
||||||
|
#undef __DISABLE_AVX512VPOPCNTDQVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVX512VPOPCNTDQVL__ */
|
||||||
|
|
||||||
|
#endif /* _AVX512VPOPCNTDQVLINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avxifmaintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVXIFMAINTRIN_H_INCLUDED
|
||||||
|
#define _AVXIFMAINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVXIFMA__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avxifma")
|
||||||
|
#define __DISABLE_AVXIFMA__
|
||||||
|
#endif /* __AVXIFMA__ */
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_madd52lo_avx_epu64 (__m128i __X, __m128i __Y, __m128i __Z)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmadd52luq128 ((__v2di) __X,
|
||||||
|
(__v2di) __Y,
|
||||||
|
(__v2di) __Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_madd52hi_avx_epu64 (__m128i __X, __m128i __Y, __m128i __Z)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpmadd52huq128 ((__v2di) __X,
|
||||||
|
(__v2di) __Y,
|
||||||
|
(__v2di) __Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_madd52lo_avx_epu64 (__m256i __X, __m256i __Y, __m256i __Z)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmadd52luq256 ((__v4di) __X,
|
||||||
|
(__v4di) __Y,
|
||||||
|
(__v4di) __Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_madd52hi_avx_epu64 (__m256i __X, __m256i __Y, __m256i __Z)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpmadd52huq256 ((__v4di) __X,
|
||||||
|
(__v4di) __Y,
|
||||||
|
(__v4di) __Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVXIFMA__
|
||||||
|
#undef __DISABLE_AVXIFMA__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVXIFMA__ */
|
||||||
|
|
||||||
|
#endif /* _AVXIFMAINTRIN_H_INCLUDED */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,140 @@
|
|||||||
|
/* Copyright (C) 2021-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avxneconvertintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVXNECONVERTINTRIN_H_INCLUDED
|
||||||
|
#define _AVXNECONVERTINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __AVXNECONVERT__
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target ("avxneconvert")
|
||||||
|
#define __DISABLE_AVXNECONVERT__
|
||||||
|
#endif /* __AVXNECONVERT__ */
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_bcstnebf16_ps (const void *__P)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_vbcstnebf162ps128 ((const __bf16 *) __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_bcstnebf16_ps (const void *__P)
|
||||||
|
{
|
||||||
|
return (__m256) __builtin_ia32_vbcstnebf162ps256 ((const __bf16 *) __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_bcstnesh_ps (const void *__P)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_vbcstnesh2ps128 ((const _Float16 *) __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_bcstnesh_ps (const void *__P)
|
||||||
|
{
|
||||||
|
return (__m256) __builtin_ia32_vbcstnesh2ps256 ((const _Float16 *) __P);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtneebf16_ps (const __m128bh *__A)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_vcvtneebf162ps128 ((const __v8bf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtneebf16_ps (const __m256bh *__A)
|
||||||
|
{
|
||||||
|
return (__m256) __builtin_ia32_vcvtneebf162ps256 ((const __v16bf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtneeph_ps (const __m128h *__A)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_vcvtneeph2ps128 ((const __v8hf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtneeph_ps (const __m256h *__A)
|
||||||
|
{
|
||||||
|
return (__m256) __builtin_ia32_vcvtneeph2ps256 ((const __v16hf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtneobf16_ps (const __m128bh *__A)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_vcvtneobf162ps128 ((const __v8bf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtneobf16_ps (const __m256bh *__A)
|
||||||
|
{
|
||||||
|
return (__m256) __builtin_ia32_vcvtneobf162ps256 ((const __v16bf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtneoph_ps (const __m128h *__A)
|
||||||
|
{
|
||||||
|
return (__m128) __builtin_ia32_vcvtneoph2ps128 ((const __v8hf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtneoph_ps (const __m256h *__A)
|
||||||
|
{
|
||||||
|
return (__m256) __builtin_ia32_vcvtneoph2ps256 ((const __v16hf *) __A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_cvtneps_avx_pbh (__m128 __A)
|
||||||
|
{
|
||||||
|
return (__m128bh) __builtin_ia32_cvtneps2bf16_v4sf (__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128bh
|
||||||
|
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_cvtneps_avx_pbh (__m256 __A)
|
||||||
|
{
|
||||||
|
return (__m128bh) __builtin_ia32_cvtneps2bf16_v8sf (__A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVXNECONVERT__
|
||||||
|
#undef __DISABLE_AVXNECONVERT__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVXNECONVERT__ */
|
||||||
|
|
||||||
|
#endif /* _AVXNECONVERTINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/* Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avxvnniint16intrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVXVNNIINT16INTRIN_H_INCLUDED
|
||||||
|
#define _AVXVNNIINT16INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVXVNNIINT16__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avxvnniint16")
|
||||||
|
#define __DISABLE_AVXVNNIINT16__
|
||||||
|
#endif /* __AVXVNNIINT16__ */
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwsud_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpwsud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwsuds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpwsuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwusd_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpwusd128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwusds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpwusds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwuud_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpwuud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwuuds_avx_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpwuuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwsud_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpwsud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwsuds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpwsuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwusd_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpwusd256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwusds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpwusds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwuud_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpwuud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwuuds_avx_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpwuuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVXVNNIINT16__
|
||||||
|
#undef __DISABLE_AVXVNNIINT16__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVXVNNIINT16__ */
|
||||||
|
|
||||||
|
#endif /* __AVXVNNIINT16INTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if !defined _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avxvnniint8vlintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVXVNNIINT8INTRIN_H_INCLUDED
|
||||||
|
#define _AVXVNNIINT8INTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVXVNNIINT8__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avxvnniint8")
|
||||||
|
#define __DISABLE_AVXVNNIINT8__
|
||||||
|
#endif /* __AVXVNNIINT8__ */
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbssd_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpbssd128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbssds_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpbssds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbsud_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpbsud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbsuds_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpbsuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbuud_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpbuud128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbuuds_epi32 (__m128i __W, __m128i __A, __m128i __B)
|
||||||
|
{
|
||||||
|
return (__m128i)
|
||||||
|
__builtin_ia32_vpdpbuuds128 ((__v4si) __W, (__v4si) __A, (__v4si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbssd_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpbssd256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbssds_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpbssds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbsud_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpbsud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbsuds_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpbsuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbuud_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpbuud256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbuuds_epi32 (__m256i __W, __m256i __A, __m256i __B)
|
||||||
|
{
|
||||||
|
return (__m256i)
|
||||||
|
__builtin_ia32_vpdpbuuds256 ((__v8si) __W, (__v8si) __A, (__v8si) __B);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVXVNNIINT8__
|
||||||
|
#undef __DISABLE_AVXVNNIINT8__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVXVNNIINT8__ */
|
||||||
|
|
||||||
|
#endif /* __AVXVNNIINT8INTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/* Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef _IMMINTRIN_H_INCLUDED
|
||||||
|
#error "Never use <avxvnniintrin.h> directly; include <immintrin.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AVXVNNIINTRIN_H_INCLUDED
|
||||||
|
#define _AVXVNNIINTRIN_H_INCLUDED
|
||||||
|
|
||||||
|
#if !defined(__AVXVNNI__)
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC target("avxvnni")
|
||||||
|
#define __DISABLE_AVXVNNIVL__
|
||||||
|
#endif /* __AVXVNNIVL__ */
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbusd_avx_epi32(__m256i __A, __m256i __B, __m256i __C)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpdpbusd_v8si ((__v8si) __A,
|
||||||
|
(__v8si) __B,
|
||||||
|
(__v8si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbusd_avx_epi32(__m128i __A, __m128i __B, __m128i __C)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpdpbusd_v4si ((__v4si) __A,
|
||||||
|
(__v4si) __B,
|
||||||
|
(__v4si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpbusds_avx_epi32(__m256i __A, __m256i __B, __m256i __C)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpdpbusds_v8si ((__v8si) __A,
|
||||||
|
(__v8si) __B,
|
||||||
|
(__v8si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpbusds_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpdpbusds_v4si ((__v4si) __A,
|
||||||
|
(__v4si) __B,
|
||||||
|
(__v4si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwssd_avx_epi32(__m256i __A,__m256i __B,__m256i __C)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpdpwssd_v8si ((__v8si) __A,
|
||||||
|
(__v8si) __B,
|
||||||
|
(__v8si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwssd_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpdpwssd_v4si ((__v4si) __A,
|
||||||
|
(__v4si) __B,
|
||||||
|
(__v4si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m256i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm256_dpwssds_avx_epi32(__m256i __A,__m256i __B,__m256i __C)
|
||||||
|
{
|
||||||
|
return (__m256i) __builtin_ia32_vpdpwssds_v8si ((__v8si) __A,
|
||||||
|
(__v8si) __B,
|
||||||
|
(__v8si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __inline __m128i
|
||||||
|
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||||
|
_mm_dpwssds_avx_epi32(__m128i __A,__m128i __B,__m128i __C)
|
||||||
|
{
|
||||||
|
return (__m128i) __builtin_ia32_vpdpwssds_v4si ((__v4si) __A,
|
||||||
|
(__v4si) __B,
|
||||||
|
(__v4si) __C);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __DISABLE_AVXVNNIVL__
|
||||||
|
#undef __DISABLE_AVXVNNIVL__
|
||||||
|
#pragma GCC pop_options
|
||||||
|
#endif /* __DISABLE_AVXVNNIVL__ */
|
||||||
|
#endif /* _AVXVNNIINTRIN_H_INCLUDED */
|
||||||
@@ -0,0 +1,343 @@
|
|||||||
|
// auto_ptr implementation -*- C++ -*-
|
||||||
|
|
||||||
|
// Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
// permissions described in the GCC Runtime Library Exception, version
|
||||||
|
// 3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License and
|
||||||
|
// a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/** @file backward/auto_ptr.h
|
||||||
|
* This is an internal header file, included by other library headers.
|
||||||
|
* Do not attempt to use it directly. @headername{memory}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BACKWARD_AUTO_PTR_H
|
||||||
|
#define _BACKWARD_AUTO_PTR_H 1
|
||||||
|
|
||||||
|
#include <bits/c++config.h>
|
||||||
|
#include <debug/debug.h>
|
||||||
|
|
||||||
|
namespace std _GLIBCXX_VISIBILITY(default)
|
||||||
|
{
|
||||||
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper class to provide auto_ptr with reference semantics.
|
||||||
|
* For example, an auto_ptr can be assigned (or constructed from)
|
||||||
|
* the result of a function which returns an auto_ptr by value.
|
||||||
|
*
|
||||||
|
* All the auto_ptr_ref stuff should happen behind the scenes.
|
||||||
|
*/
|
||||||
|
template<typename _Tp1>
|
||||||
|
struct auto_ptr_ref
|
||||||
|
{
|
||||||
|
_Tp1* _M_ptr;
|
||||||
|
|
||||||
|
explicit
|
||||||
|
auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
|
||||||
|
} _GLIBCXX11_DEPRECATED;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A simple smart pointer providing strict ownership semantics.
|
||||||
|
*
|
||||||
|
* The Standard says:
|
||||||
|
* <pre>
|
||||||
|
* An @c auto_ptr owns the object it holds a pointer to. Copying
|
||||||
|
* an @c auto_ptr copies the pointer and transfers ownership to the
|
||||||
|
* destination. If more than one @c auto_ptr owns the same object
|
||||||
|
* at the same time the behavior of the program is undefined.
|
||||||
|
*
|
||||||
|
* The uses of @c auto_ptr include providing temporary
|
||||||
|
* exception-safety for dynamically allocated memory, passing
|
||||||
|
* ownership of dynamically allocated memory to a function, and
|
||||||
|
* returning dynamically allocated memory from a function. @c
|
||||||
|
* auto_ptr does not meet the CopyConstructible and Assignable
|
||||||
|
* requirements for Standard Library <a
|
||||||
|
* href="tables.html#65">container</a> elements and thus
|
||||||
|
* instantiating a Standard Library container with an @c auto_ptr
|
||||||
|
* results in undefined behavior.
|
||||||
|
* </pre>
|
||||||
|
* Quoted from [20.4.5]/3.
|
||||||
|
*
|
||||||
|
* Good examples of what can and cannot be done with auto_ptr can
|
||||||
|
* be found in the libstdc++ testsuite.
|
||||||
|
*
|
||||||
|
* _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||||
|
* 127. auto_ptr<> conversion issues
|
||||||
|
* These resolutions have all been incorporated.
|
||||||
|
*
|
||||||
|
* @headerfile memory
|
||||||
|
* @deprecated Deprecated in C++11, no longer in the standard since C++17.
|
||||||
|
* Use `unique_ptr` instead.
|
||||||
|
*/
|
||||||
|
template<typename _Tp>
|
||||||
|
class auto_ptr
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
_Tp* _M_ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// The pointed-to type.
|
||||||
|
typedef _Tp element_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An %auto_ptr is usually constructed from a raw pointer.
|
||||||
|
* @param __p A pointer (defaults to NULL).
|
||||||
|
*
|
||||||
|
* This object now @e owns the object pointed to by @a __p.
|
||||||
|
*/
|
||||||
|
explicit
|
||||||
|
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An %auto_ptr can be constructed from another %auto_ptr.
|
||||||
|
* @param __a Another %auto_ptr of the same type.
|
||||||
|
*
|
||||||
|
* This object now @e owns the object previously owned by @a __a,
|
||||||
|
* which has given up ownership.
|
||||||
|
*/
|
||||||
|
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An %auto_ptr can be constructed from another %auto_ptr.
|
||||||
|
* @param __a Another %auto_ptr of a different but related type.
|
||||||
|
*
|
||||||
|
* A pointer-to-Tp1 must be convertible to a
|
||||||
|
* pointer-to-Tp/element_type.
|
||||||
|
*
|
||||||
|
* This object now @e owns the object previously owned by @a __a,
|
||||||
|
* which has given up ownership.
|
||||||
|
*/
|
||||||
|
template<typename _Tp1>
|
||||||
|
auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief %auto_ptr assignment operator.
|
||||||
|
* @param __a Another %auto_ptr of the same type.
|
||||||
|
*
|
||||||
|
* This object now @e owns the object previously owned by @a __a,
|
||||||
|
* which has given up ownership. The object that this one @e
|
||||||
|
* used to own and track has been deleted.
|
||||||
|
*/
|
||||||
|
auto_ptr&
|
||||||
|
operator=(auto_ptr& __a) throw()
|
||||||
|
{
|
||||||
|
reset(__a.release());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief %auto_ptr assignment operator.
|
||||||
|
* @param __a Another %auto_ptr of a different but related type.
|
||||||
|
*
|
||||||
|
* A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type.
|
||||||
|
*
|
||||||
|
* This object now @e owns the object previously owned by @a __a,
|
||||||
|
* which has given up ownership. The object that this one @e
|
||||||
|
* used to own and track has been deleted.
|
||||||
|
*/
|
||||||
|
template<typename _Tp1>
|
||||||
|
auto_ptr&
|
||||||
|
operator=(auto_ptr<_Tp1>& __a) throw()
|
||||||
|
{
|
||||||
|
reset(__a.release());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the %auto_ptr goes out of scope, the object it owns is
|
||||||
|
* deleted. If it no longer owns anything (i.e., @c get() is
|
||||||
|
* @c NULL), then this has no effect.
|
||||||
|
*
|
||||||
|
* The C++ standard says there is supposed to be an empty throw
|
||||||
|
* specification here, but omitting it is standard conforming. Its
|
||||||
|
* presence can be detected only if _Tp::~_Tp() throws, but this is
|
||||||
|
* prohibited. [17.4.3.6]/2
|
||||||
|
*/
|
||||||
|
~auto_ptr() { delete _M_ptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Smart pointer dereferencing.
|
||||||
|
*
|
||||||
|
* If this %auto_ptr no longer owns anything, then this
|
||||||
|
* operation will crash. (For a smart pointer, <em>no longer owns
|
||||||
|
* anything</em> is the same as being a null pointer, and you know
|
||||||
|
* what happens when you dereference one of those...)
|
||||||
|
*/
|
||||||
|
element_type&
|
||||||
|
operator*() const throw()
|
||||||
|
{
|
||||||
|
__glibcxx_assert(_M_ptr != 0);
|
||||||
|
return *_M_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Smart pointer dereferencing.
|
||||||
|
*
|
||||||
|
* This returns the pointer itself, which the language then will
|
||||||
|
* automatically cause to be dereferenced.
|
||||||
|
*/
|
||||||
|
element_type*
|
||||||
|
operator->() const throw()
|
||||||
|
{
|
||||||
|
__glibcxx_assert(_M_ptr != 0);
|
||||||
|
return _M_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bypassing the smart pointer.
|
||||||
|
* @return The raw pointer being managed.
|
||||||
|
*
|
||||||
|
* You can get a copy of the pointer that this object owns, for
|
||||||
|
* situations such as passing to a function which only accepts
|
||||||
|
* a raw pointer.
|
||||||
|
*
|
||||||
|
* @note This %auto_ptr still owns the memory.
|
||||||
|
*/
|
||||||
|
element_type*
|
||||||
|
get() const throw() { return _M_ptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bypassing the smart pointer.
|
||||||
|
* @return The raw pointer being managed.
|
||||||
|
*
|
||||||
|
* You can get a copy of the pointer that this object owns, for
|
||||||
|
* situations such as passing to a function which only accepts
|
||||||
|
* a raw pointer.
|
||||||
|
*
|
||||||
|
* @note This %auto_ptr no longer owns the memory. When this object
|
||||||
|
* goes out of scope, nothing will happen.
|
||||||
|
*/
|
||||||
|
element_type*
|
||||||
|
release() throw()
|
||||||
|
{
|
||||||
|
element_type* __tmp = _M_ptr;
|
||||||
|
_M_ptr = 0;
|
||||||
|
return __tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Forcibly deletes the managed object.
|
||||||
|
* @param __p A pointer (defaults to NULL).
|
||||||
|
*
|
||||||
|
* This object now @e owns the object pointed to by @a __p. The
|
||||||
|
* previous object has been deleted.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
reset(element_type* __p = 0) throw()
|
||||||
|
{
|
||||||
|
if (__p != _M_ptr)
|
||||||
|
{
|
||||||
|
delete _M_ptr;
|
||||||
|
_M_ptr = __p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Automatic conversions
|
||||||
|
*
|
||||||
|
* These operations are supposed to convert an %auto_ptr into and from
|
||||||
|
* an auto_ptr_ref automatically as needed. This would allow
|
||||||
|
* constructs such as
|
||||||
|
* @code
|
||||||
|
* auto_ptr<Derived> func_returning_auto_ptr(.....);
|
||||||
|
* ...
|
||||||
|
* auto_ptr<Base> ptr = func_returning_auto_ptr(.....);
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* But it doesn't work, and won't be fixed. For further details see
|
||||||
|
* http://cplusplus.github.io/LWG/lwg-closed.html#463
|
||||||
|
*/
|
||||||
|
auto_ptr(auto_ptr_ref<element_type> __ref) throw()
|
||||||
|
: _M_ptr(__ref._M_ptr) { }
|
||||||
|
|
||||||
|
auto_ptr&
|
||||||
|
operator=(auto_ptr_ref<element_type> __ref) throw()
|
||||||
|
{
|
||||||
|
if (__ref._M_ptr != this->get())
|
||||||
|
{
|
||||||
|
delete _M_ptr;
|
||||||
|
_M_ptr = __ref._M_ptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp1>
|
||||||
|
operator auto_ptr_ref<_Tp1>() throw()
|
||||||
|
{ return auto_ptr_ref<_Tp1>(this->release()); }
|
||||||
|
|
||||||
|
template<typename _Tp1>
|
||||||
|
operator auto_ptr<_Tp1>() throw()
|
||||||
|
{ return auto_ptr<_Tp1>(this->release()); }
|
||||||
|
} _GLIBCXX11_DEPRECATED_SUGGEST("std::unique_ptr");
|
||||||
|
|
||||||
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||||
|
// 541. shared_ptr template assignment and void
|
||||||
|
template<>
|
||||||
|
class auto_ptr<void>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef void element_type;
|
||||||
|
} _GLIBCXX11_DEPRECATED;
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
#if _GLIBCXX_HOSTED
|
||||||
|
template<_Lock_policy _Lp>
|
||||||
|
template<typename _Tp>
|
||||||
|
inline
|
||||||
|
__shared_count<_Lp>::__shared_count(std::auto_ptr<_Tp>&& __r)
|
||||||
|
: _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get()))
|
||||||
|
{ __r.release(); }
|
||||||
|
|
||||||
|
template<typename _Tp, _Lock_policy _Lp>
|
||||||
|
template<typename _Tp1, typename>
|
||||||
|
inline
|
||||||
|
__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
||||||
|
: _M_ptr(__r.get()), _M_refcount()
|
||||||
|
{
|
||||||
|
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
|
||||||
|
static_assert( sizeof(_Tp1) > 0, "incomplete type" );
|
||||||
|
_Tp1* __tmp = __r.get();
|
||||||
|
_M_refcount = __shared_count<_Lp>(std::move(__r));
|
||||||
|
_M_enable_shared_from_this_with(__tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Tp>
|
||||||
|
template<typename _Tp1, typename>
|
||||||
|
inline
|
||||||
|
shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
||||||
|
: __shared_ptr<_Tp>(std::move(__r)) { }
|
||||||
|
#endif // HOSTED
|
||||||
|
|
||||||
|
template<typename _Tp, typename _Dp>
|
||||||
|
template<typename _Up, typename>
|
||||||
|
inline
|
||||||
|
unique_ptr<_Tp, _Dp>::unique_ptr(auto_ptr<_Up>&& __u) noexcept
|
||||||
|
: _M_t(__u.release(), deleter_type()) { }
|
||||||
|
#endif // C++11
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
_GLIBCXX_END_NAMESPACE_VERSION
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif /* _BACKWARD_AUTO_PTR_H */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user