// File: /workspace/github_c_makefile_star2_O2/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 0x3538
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 0x3574
leaq 0x30(%rsp), %rax
movq %rax, (%rsp)
andq $0x0, (%rax)
leaq 0x10(%rsp), %rbp
andl $0x0, (%rbp)
leaq 0x14(%rsp), %r14
andl $0x0, (%r14)
leaq 0x28(%rsp), %r12
andq $0x0, (%r12)
leaq 0x20(%rsp), %r13
andq $0x0, (%r13)
leaq 0x8(%rsp), %r15
andl $0x0, (%r15)
movl $0xc8, %edi
callq 0xac87
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 0xbc8a
movq %rax, 0x38(%rbx)
movq 0x18(%rax), %rax
leaq 0xaa73(%rip), %rcx      # 0xe046
movq %rcx, 0x8(%rax)
movq %rbx, %rdi
movl %ebp, %esi
callq 0xbc82
movq %rax, %r14
movq %rax, 0x40(%rbx)
movq 0x18(%rax), %rax
leaq 0xaa62(%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)
andq $0x0, 0x20(%rbx)
movq %r15, 0xb0(%rbx)
movq %rbx, %rdi
callq 0x6e53
movq %rbx, %rdi
callq 0x4042
movq %rbx, %rdi
callq 0x3d32
movq %rbx, %rdi
callq 0xad2f
leaq 0x1c(%rsp), %r15
andl $0x0, (%r15)
leaq 0x18(%rsp), %r12
andl $0x0, (%r12)
movq 0x40(%rbx), %r13
leaq 0xab5b(%rip), %rdi      # 0xe1ba
leaq 0xab5a(%rip), %rsi      # 0xe1c0
movq %r15, %rdx
movq %r12, %rcx
xorl %eax, %eax
callq 0x3250
movslq (%r12), %rcx
movslq (%r15), %rdx
leaq 0xab45(%rip), %rsi      # 0xe1c6
movq %r13, %rdi
callq 0xbb0a
leaq 0xab43(%rip), %rsi      # 0xe1d3
movq %r13, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa9c0(%rip), %rsi      # 0xe061
leaq 0x3616(%rip), %rdx      # 0x6cbe
movq %rbx, %rdi
callq 0x3854
leaq 0xa9b0(%rip), %rsi      # 0xe067
leaq 0x8e2(%rip), %rdx       # 0x3fa0
movq %rbx, %rdi
callq 0x3854
leaq 0xa9a2(%rip), %rsi      # 0xe06f
leaq 0x34a7(%rip), %rdx      # 0x6b7b
movq %rbx, %rdi
callq 0x3854
leaq 0xa994(%rip), %rsi      # 0xe077
leaq 0x40e(%rip), %rdx       # 0x3af8
movq %rbx, %rdi
callq 0x3854
movq %rbx, %rdi
callq 0x389b
leaq 0xa97d(%rip), %rsi      # 0xe07e
pushq $0x1
popq %r15
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa97d(%rip), %rsi      # 0xe094
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa97a(%rip), %rsi      # 0xe0a3
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa978(%rip), %rsi      # 0xe0b3
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa979(%rip), %rsi      # 0xe0c6
movq %r14, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa982(%rip), %rsi      # 0xe0e0
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa97f(%rip), %rsi      # 0xe0ef
movq %r14, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa97f(%rip), %rsi      # 0xe100
movq %r14, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa97c(%rip), %rsi      # 0xe10e
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa97e(%rip), %rsi      # 0xe122
movq %r14, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa985(%rip), %rsi      # 0xe13a
movq %r14, %rdi
movq %r15, %rdx
callq 0xba61
leaq 0xa986(%rip), %rsi      # 0xe14d
movq %r14, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa985(%rip), %rsi      # 0xe15d
pushq $0x8
popq %rdx
movq %r14, %rdi
callq 0xba61
leaq 0xa98b(%rip), %rsi      # 0xe175
movq %r14, %rdi
xorl %edx, %edx
callq 0xba61
leaq 0xa986(%rip), %rsi      # 0xe181
leaq 0xa99a(%rip), %rdx      # 0xe19c
movq %r14, %rdi
callq 0xbb48
leaq 0xa993(%rip), %rsi      # 0xe1a4
leaq 0xa99d(%rip), %rdx      # 0xe1b5
movq %r14, %rdi
callq 0xbb48
movq %rbx, %rdi
callq 0x40e8
movq 0x30(%rbx), %rdi
callq 0x38d2
cmpq $0x0, 0x15c5f(%rip)     # 0x19498
jne 0x3842
movq %rbx, 0x15c56(%rip)     # 0x19498
movq %rbx, %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq