// File: /workspace/github_c_makefile_star2_O1/hoobaa[P]ficl/system.c
// Function: ficlSystemCreate
ficlSystem *ficlSystemCreate(ficlSystemInformation *fsi)
{
    ficlInteger dictionarySize;
    ficlInteger environmentSize;
	ficlInteger stackSize;
    ficlSystem *system;
	ficlCallback callback;
	ficlSystemInformation fauxInfo;
	ficlDictionary *environment;



	if (fsi == NULL)
	{
		fsi = &fauxInfo;
		ficlSystemInformationInitialize(fsi);
	}

	callback.context = fsi->context;
	callback.textOut = fsi->textOut;
	callback.errorOut = fsi->errorOut;
	callback.system = NULL;
	callback.vm = NULL;

    FICL_ASSERT(&callback, sizeof(ficlInteger) >= sizeof(void *));
    FICL_ASSERT(&callback, sizeof(ficlUnsigned) >= sizeof(void *));
#if (FICL_WANT_FLOAT)
    FICL_ASSERT(&callback, sizeof(ficlFloat) <= sizeof(ficlInteger));
#endif

    system = ficlMalloc(sizeof(ficlSystem));

    FICL_ASSERT(&callback, system);

    memset(system, 0, sizeof(ficlSystem));

    dictionarySize = fsi->dictionarySize;
    if (dictionarySize <= 0)
        dictionarySize = FICL_DEFAULT_DICTIONARY_SIZE;

    environmentSize = fsi->environmentSize;
    if (environmentSize <= 0)
        environmentSize = FICL_DEFAULT_DICTIONARY_SIZE;

    stackSize = fsi->stackSize;
    if (stackSize < FICL_DEFAULT_STACK_SIZE)
        stackSize = FICL_DEFAULT_STACK_SIZE;

    system->dictionary = ficlDictionaryCreateHashed(system, (unsigned)dictionarySize, FICL_HASH_SIZE);
    system->dictionary->forthWordlist->name = "forth-wordlist";

    environment = ficlDictionaryCreate(system, (unsigned)environmentSize);
    system->environment = environment;
    system->environment->forthWordlist->name = "environment";

    system->callback.textOut = fsi->textOut;
    system->callback.errorOut = fsi->errorOut;
    system->callback.context = fsi->context;
    system->callback.system = system;
    system->callback.vm = NULL;
    system->stackSize = stackSize;

#if FICL_WANT_LOCALS
    /*
    ** The locals dictionary is only searched while compiling,
    ** but this is where speed is most important. On the other
    ** hand, the dictionary gets emptied after each use of locals
    ** The need to balance search speed with the cost of the 'empty'
    ** operation led me to select a single-threaded list...
    */
    system->locals = ficlDictionaryCreate(system, (unsigned)FICL_MAX_LOCALS * FICL_CELLS_PER_WORD);
#endif /* FICL_WANT_LOCALS */

    /*
    ** Build the precompiled dictionary and load softwords. We need a temporary
    ** VM to do this - ficlNewVM links one to the head of the system VM list.
    ** ficlCompilePlatform (defined in win32.c, for example) adds platform specific words.
    */
    ficlSystemCompileCore(system);
    ficlSystemCompilePrefix(system);

#if FICL_WANT_FLOAT
    ficlSystemCompileFloat(system);
#endif /* FICL_WANT_FLOAT */

#if FICL_WANT_PLATFORM
    ficlSystemCompilePlatform(system);
#endif /* FICL_WANT_PLATFORM */

    ficlSystemSetVersion(system);

    /*
    ** Establish the parse order. Note that prefixes precede numbers -
    ** this allows constructs like "0b101010" which might parse as a
    ** hex value otherwise.
    */
    ficlSystemAddPrimitiveParseStep(system, "?word", ficlVmParseWord);
    ficlSystemAddPrimitiveParseStep(system, "?prefix", ficlVmParsePrefix);
    ficlSystemAddPrimitiveParseStep(system, "?number", ficlVmParseNumber);
#if FICL_WANT_FLOAT
    ficlSystemAddPrimitiveParseStep(system, "?float", ficlVmParseFloatNumber);
#endif

    /*
    ** Now create a temporary VM to compile the softwords. Since all VMs are
    ** linked into the vmList of ficlSystem, we don't have to pass the VM
    ** to ficlCompileSoftCore -- it just hijacks whatever it finds in the VM list.
    ** Ficl 2.05: vmCreate no longer depends on the presence of INTERPRET in the
    ** dictionary, so a VM can be created before the dictionary is built. It just
    ** can't do much...
    */
    ficlSystemCreateVm(system);
#define ADD_COMPILE_FLAG(name) ficlDictionarySetConstant(environment, #name, name)
	ADD_COMPILE_FLAG(FICL_WANT_LZ_SOFTCORE);
	ADD_COMPILE_FLAG(FICL_WANT_FILE);
	ADD_COMPILE_FLAG(FICL_WANT_FLOAT);
	ADD_COMPILE_FLAG(FICL_WANT_DEBUGGER);
	ADD_COMPILE_FLAG(FICL_WANT_EXTENDED_PREFIX);
	ADD_COMPILE_FLAG(FICL_WANT_USER);
	ADD_COMPILE_FLAG(FICL_WANT_LOCALS);
	ADD_COMPILE_FLAG(FICL_WANT_OOP);
	ADD_COMPILE_FLAG(FICL_WANT_SOFTWORDS);
	ADD_COMPILE_FLAG(FICL_WANT_MULTITHREADED);
	ADD_COMPILE_FLAG(FICL_WANT_OPTIMIZE);
	ADD_COMPILE_FLAG(FICL_WANT_VCALL);

	ADD_COMPILE_FLAG(FICL_PLATFORM_ALIGNMENT);

	ADD_COMPILE_FLAG(FICL_ROBUST);

#define ADD_COMPILE_STRING(name) ficlDictionarySetConstantString(environment, #name, name)
	ADD_COMPILE_STRING(FICL_PLATFORM_ARCHITECTURE);
	ADD_COMPILE_STRING(FICL_PLATFORM_OS);

    ficlSystemCompileSoftCore(system);
    ficlSystemDestroyVm(system->vmList);

	if (ficlSystemGlobal == NULL)
		ficlSystemGlobal = system;

    return system;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
testq %rdi, %rdi
je 0x355c
movq %rdi, %r14
leaq 0x8(%rdi), %rax
movq %rax, (%rsp)
leaq 0x18(%rdi), %r12
leaq 0x20(%rdi), %r13
leaq 0x10(%rdi), %rbp
leaq 0x28(%rdi), %r15
addq $0x14, %r14
jmp 0x3594
xorl %eax, %eax
leaq 0x30(%rsp), %rcx
movq %rcx, (%rsp)
movq %rax, (%rcx)
leaq 0x10(%rsp), %rbp
movl %eax, (%rbp)
leaq 0x14(%rsp), %r14
movl %eax, (%r14)
leaq 0x28(%rsp), %r12
movq %rax, (%r12)
leaq 0x20(%rsp), %r13
movq %rax, (%r13)
leaq 0x8(%rsp), %r15
movl %eax, (%r15)
movl $0xc8, %edi
callq 0xb40f
movq %rax, %rbx
movl $0xc8, %edx
movq %rax, %rdi
xorl %esi, %esi
callq 0x3130
movl (%rbp), %esi
testl %esi, %esi
movl $0x3000, %eax           # imm = 0x3000
cmovlel %eax, %esi
movl (%r15), %ebp
testl %ebp, %ebp
cmovlel %eax, %ebp
movl (%r14), %eax
cmpl $0x81, %eax
movl $0x80, %r15d
cmovgel %eax, %r15d
movq %rbx, %rdi
movl $0xf1, %edx
callq 0xc661
movq %rax, 0x38(%rbx)
movq 0x18(%rax), %rax
leaq 0xaa53(%rip), %rcx      # 0xe046
movq %rcx, 0x8(%rax)
movq %rbx, %rdi
movl %ebp, %esi
callq 0xc5e4
movq %rax, %r14
movq %rax, 0x40(%rbx)
movq 0x18(%rax), %rax
leaq 0xaa42(%rip), %rcx      # 0xe055
movq %rcx, 0x8(%rax)
movq (%r12), %rax
movq %rax, 0x8(%rbx)
movq (%r13), %rax
movq %rax, 0x10(%rbx)
movq (%rsp), %rax
movq (%rax), %rax
movq %rax, (%rbx)
movq %rbx, 0x18(%rbx)
movq $0x0, 0x20(%rbx)
movq %r15, 0xb0(%rbx)
movq %rbx, %rdi
callq 0x7241
movq %rbx, %rdi
callq 0x411b
movq %rbx, %rdi
callq 0x3dfb
movq %rbx, %rdi
callq 0xb4be
leaq 0x1c(%rsp), %r15
xorl %eax, %eax
movl %eax, (%r15)
leaq 0x18(%rsp), %r12
movl %eax, (%r12)
movq 0x40(%rbx), %r13
leaq 0xab38(%rip), %rdi      # 0xe1ba
leaq 0xab37(%rip), %rsi      # 0xe1c0
movq %r15, %rdx
movq %r12, %rcx
xorl %eax, %eax
callq 0x3250
movslq (%r12), %rcx
movslq (%r15), %rdx
leaq 0xab22(%rip), %rsi      # 0xe1c6
movq %r13, %rdi
callq 0xc42a
leaq 0xab20(%rip), %rsi      # 0xe1d3
movq %r13, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa99d(%rip), %rsi      # 0xe061
leaq 0x39de(%rip), %rdx      # 0x70a9
movq %rbx, %rdi
callq 0x38b4
leaq 0xa98d(%rip), %rsi      # 0xe067
leaq 0x98b(%rip), %rdx       # 0x406c
movq %rbx, %rdi
callq 0x38b4
leaq 0xa97f(%rip), %rsi      # 0xe06f
leaq 0x3875(%rip), %rdx      # 0x6f6c
movq %rbx, %rdi
callq 0x38b4
leaq 0xa971(%rip), %rsi      # 0xe077
leaq 0x48a(%rip), %rdx       # 0x3b97
movq %rbx, %rdi
callq 0x38b4
movl 0xb0(%rbx), %edx
xorl %edi, %edi
movl %edx, %esi
callq 0x5290
movq 0x30(%rbx), %rcx
movq %rcx, 0x28(%rax)
movq 0x20(%rbx), %rcx
movq %rcx, 0x20(%rax)
movups (%rbx), %xmm0
movups 0x10(%rbx), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movq %rax, 0x20(%rax)
movq %rbx, 0x18(%rax)
movq %rax, 0x30(%rbx)
leaq 0xa929(%rip), %rsi      # 0xe07e
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa92b(%rip), %rsi      # 0xe094
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa926(%rip), %rsi      # 0xe0a3
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa922(%rip), %rsi      # 0xe0b3
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa921(%rip), %rsi      # 0xe0c6
movq %r14, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa92a(%rip), %rsi      # 0xe0e0
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa925(%rip), %rsi      # 0xe0ef
movq %r14, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa925(%rip), %rsi      # 0xe100
movq %r14, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa922(%rip), %rsi      # 0xe10e
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa922(%rip), %rsi      # 0xe122
movq %r14, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa929(%rip), %rsi      # 0xe13a
movl $0x1, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa928(%rip), %rsi      # 0xe14d
movq %r14, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa927(%rip), %rsi      # 0xe15d
movl $0x8, %edx
movq %r14, %rdi
callq 0xc36c
leaq 0xa92b(%rip), %rsi      # 0xe175
movq %r14, %rdi
xorl %edx, %edx
callq 0xc36c
leaq 0xa926(%rip), %rsi      # 0xe181
leaq 0xa93a(%rip), %rdx      # 0xe19c
movq %r14, %rdi
callq 0xc46a
leaq 0xa933(%rip), %rsi      # 0xe1a4
leaq 0xa93d(%rip), %rdx      # 0xe1b5
movq %r14, %rdi
callq 0xc46a
movq %rbx, %rdi
callq 0x41c4
movq 0x30(%rbx), %rdi
callq 0x394a
cmpq $0x0, 0x14bff(%rip)     # 0x18498
jne 0x38a2
movq %rbx, 0x14bf6(%rip)     # 0x18498
movq %rbx, %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq