// File: /workspace/github_cpp_makefile_star2_O2/rofl0r[P]ascc/cs_parser.cpp
// Function: do_variable_memory_access(ccCompiledScript*, int, int, bool, int, int, bool, bool, int, bool, bool, int, int, bool, bool, int)
int do_variable_memory_access(ccCompiledScript *scrip, int variableSym,
                              int variableSymType, bool isProperty,
                              int writing, int mustBeWritable,
                              bool addressof, bool extraoffset,
                              int soffset, bool isPointer,
                              bool wholePointerAccess,
                              int mainVariableSym, int mainVariableType,
                              bool isDynamicArray, bool negateLiteral,
                              int extra_struct_offset) {
  int gotValType = 0;
  int readcmd = get_readcmd_for_size(sym.entries[variableSym].ssize, writing);

  if (mainVariableType == SYM_VARTYPE) {
    // it's a static member property
    if (!isProperty) {
      cc_error("static non-property access: internal error");
      return -1;
    }
    // just write 0 to AX for ease of debugging if anything
    // goes wrong
    scrip->write_cmd2(SCMD_LITTOREG, SREG_AX, 0);

    gotValType = sym.entries[variableSym].vartype;
    if (sym.entries[variableSym].flags & SFLG_CONST)
      gotValType |= STYPE_CONST;
  }
  else if ((mainVariableType == SYM_LITERALVALUE) || (mainVariableType == SYM_CONSTANT)) {
    if ((writing) || (mustBeWritable)) {
      if(mainVariableType == SYM_LITERALVALUE)
        cc_error("cannot write to a literal value");
      else
        cc_error("cannot write to constant");
      return -1;
    }
    int varSymValue;
    if (accept_literal_or_constant_value(variableSym, varSymValue, negateLiteral, "Error parsing integer value") < 0) {
      return -1;
    }
    if(negateLiteral && varSymValue < 0 && ccGetOption(SCOPT_OLDNEGATE)!=0) {
      scrip->write_cmd2(SCMD_LITTOREG, SREG_AX, varSymValue*-1);
      scrip->write_cmd2(SCMD_LITTOREG, SREG_BX, 0);
      scrip->write_cmd2(SCMD_SUBREG, SREG_BX, SREG_AX);
      scrip->write_cmd2(SCMD_REGTOREG, SREG_BX, SREG_AX);
    } else {
      scrip->write_cmd2(SCMD_LITTOREG,SREG_AX, varSymValue);
    }
    gotValType = sym.normalIntSym;
  }
  else if (mainVariableType == SYM_LITERALFLOAT) {
    if ((writing) || (mustBeWritable)) {
      cc_error("cannot write to a literal value");
      return -1;
    }
    scrip->write_cmd2(SCMD_LITTOREG, SREG_AX, float_to_int_raw((float)atof(sym.get_name(variableSym))));
    gotValType = sym.normalFloatSym;
  }
  else if ((mainVariableType == SYM_LOCALVAR) ||
           (mainVariableType == SYM_GLOBALVAR)) {

    gotValType = sym.entries[variableSym].vartype;
    if (sym.entries[variableSym].flags & SFLG_CONST)
      gotValType |= STYPE_CONST;

    // a "normal" variable
    if (isPointer) {
      // the address is already in MAR by the caller
      if ((!wholePointerAccess) && ((!addressof) || (soffset) || (extraoffset)))
        scrip->write_cmd(SCMD_CHECKNULL);
      if (soffset)
        scrip->write_cmd2(SCMD_ADD, SREG_MAR, soffset);
    }
    else if (mainVariableType == SYM_LOCALVAR) {
      // a local one
      load_stack_variable(scrip, scrip->cur_sp - soffset);
    }
    else {
      // global variable
      if (sym.entries[mainVariableSym].flags & SFLG_IMPORTED) {
        // imported variable, so get the import address and then add any offset
        scrip->write_cmd2(SCMD_LITTOREG,SREG_MAR,sym.entries[mainVariableSym].soffs);
        scrip->fixup_previous(FIXUP_IMPORT);
        if (soffset != 0)
          scrip->write_cmd2(SCMD_ADD,SREG_MAR,soffset);
      }
      else {
        scrip->write_cmd2(SCMD_LITTOREG,SREG_MAR,soffset);
        scrip->fixup_previous(FIXUP_GLOBALDATA);
      }
    }

    if (extraoffset && !isRawPointer(variableSym))
    {
      if (isDynamicArray)
      {
        scrip->write_cmd1(SCMD_MEMREADPTR, SREG_MAR);
        scrip->write_cmd(SCMD_CHECKNULL);
        scrip->write_cmd1(SCMD_DYNAMICBOUNDS, SREG_CX);
      }

      scrip->write_cmd2(SCMD_ADDREG,SREG_MAR,SREG_CX);
    }
    else if (isDynamicArray)
    {
      // not accessing an element of it, must be whole thing
      wholePointerAccess = true;
      gotValType |= STYPE_DYNARRAY;
    }

    if (extra_struct_offset)
      scrip->write_cmd2(SCMD_ADD, SREG_MAR, extra_struct_offset);

    if ((wholePointerAccess) && (writing))
      scrip->write_cmd1(SCMD_MEMWRITEPTR, SREG_AX);
    else if ((wholePointerAccess) && (!writing))
      scrip->write_cmd1(SCMD_MEMREADPTR, SREG_AX);
    else if (addressof)
      scrip->write_cmd2(SCMD_REGTOREG,SREG_MAR,SREG_AX);
    else if(isRawPointer(variableSym)) {
      if (extraoffset) {
        // load pointer value into mar
        scrip->write_cmd1(SCMD_MEMREAD, SREG_MAR);
        // add offset
        scrip->write_cmd2(SCMD_ADDREG,SREG_MAR,SREG_CX);
        // read pointed-to value
        scrip->write_cmd1(readcmd,SREG_AX);
      } else {
        // put pointer value into AX
        scrip->write_cmd1(writing ? SCMD_MEMWRITE : SCMD_MEMREAD, SREG_AX);
      }
    } else
      scrip->write_cmd1(readcmd,SREG_AX);
    }
  else if (mainVariableType == SYM_STRING) {
    if (writing) {
      cc_error("cannot write to a literal string");
      return -1;
    }

    scrip->write_cmd2(SCMD_LITTOREG,SREG_AX,soffset);
    scrip->fixup_previous(FIXUP_STRING);
    gotValType = sym.normalStringSym | STYPE_CONST;
  }
  else if (mainVariableType == SYM_STRUCTMEMBER) {
    cc_error("must include parent structure of member '%s'",sym.get_friendly_name(mainVariableSym).c_str());
    return -1;
    }
  else if (mainVariableType == SYM_NULL) {
    if (writing) {
      cc_error("Invalid use of null");
      return -1;
    }
    scrip->write_cmd2(SCMD_LITTOREG, SREG_AX, 0);
    gotValType = sym.nullSym | STYPE_POINTER;
  }
  else {
    cc_error("read/write ax called with non-variable parameter ('%s')",sym.get_friendly_name(variableSym).c_str());
    return -1;
    }

  if ((addressof) && (!isProperty))
    gotValType |= STYPE_POINTER;
  else if ((isProperty) && (sym.entries[variableSym].flags & SFLG_POINTER))
    gotValType |= STYPE_POINTER;

  if (writing) {
    if (check_type_mismatch(scrip->ax_val_type, gotValType, 1))
      return -1;
  }
  else
    scrip->ax_val_type = gotValType;

  if (isProperty) {
    // process_arrays_and_members will have set addressOf to true,
    // so AX now contains the struct address, and BX
    // contains the new value if this is a Set
    if (call_property_func(scrip, variableSym, writing))
      return -1;
  }

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %r9d, %r13d
movl %r8d, %ebp
movl %ecx, %r14d
movq %rdi, %rbx
movl 0xa0(%rsp), %r12d
movl %esi, 0x10(%rsp)
movslq %esi, %rax
leaq 0x1c716(%rip), %rcx     # 0x256f0
movq 0x28(%rcx), %rcx
imulq $0xb0, %rax, %r15
movl 0x38(%rcx,%r15), %edi
movl %r8d, %esi
callq 0x79d7
cmpl $0x2e, %r12d
jne 0x9046
testb %r14b, %r14b
je 0x906d
pushq $0x6
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
callq 0x11e6a
leaq 0x1c6dc(%rip), %rax     # 0x256f0
movq 0x28(%rax), %rax
movswl 0x30(%rax,%r15), %ecx
movl 0x28(%rax,%r15), %r13d
shll $0xd, %r13d
andl $0x20000000, %r13d      # imm = 0x20000000
orl %ecx, %r13d
movl 0x28(%rax,%r15), %eax
shll $0x16, %eax
andl $0x40000000, %eax       # imm = 0x40000000
orl %eax, %r13d
jmp 0x9448
movb 0x70(%rsp), %r8b
leal -0x13(%r12), %edx
cmpl $0x1, %edx
ja 0x9076
orl %ebp, %r13d
je 0x9139
cmpl $0x13, %r12d
je 0x9085
leaq 0x1026c(%rip), %rdi     # 0x192d7
jmp 0x908c
leaq 0x10218(%rip), %rdi     # 0x1928c
jmp 0x908c
cmpl $0x16, %r12d
jne 0x9098
orl %ebp, %r13d
je 0x9206
leaq 0x1022b(%rip), %rdi     # 0x192b7
xorl %eax, %eax
callq 0xf258
jmp 0x9481
movl %eax, 0x14(%rsp)
movl 0x98(%rsp), %edx
movl 0x80(%rsp), %ecx
leal -0x1(%r12), %eax
cmpl $0x1, %eax
ja 0x91d4
leaq 0x1c631(%rip), %rax     # 0x256f0
movq 0x28(%rax), %rax
movswl 0x30(%rax,%r15), %esi
movl 0x28(%rax,%r15), %r13d
shll $0xd, %r13d
andl $0x20000000, %r13d      # imm = 0x20000000
cmpb $0x0, 0x88(%rsp)
je 0x9267
cmpb $0x0, 0x90(%rsp)
movq %rbx, %r12
jne 0x9128
testl %ecx, %ecx
setne %al
movl %r8d, %ecx
xorb $0x1, %cl
orb 0x78(%rsp), %cl
orb %al, %cl
cmpb $0x1, %cl
jne 0x936e
movl %esi, 0xc(%rsp)
pushq $0x34
popq %rsi
movq %r12, %rdi
callq 0x11de8
movl 0xc(%rsp), %esi
movl 0x80(%rsp), %ecx
testl %ecx, %ecx
je 0x936e
movl %esi, 0xc(%rsp)
jmp 0x935c
movb 0xb0(%rsp), %r13b
movzbl %r13b, %edx
leaq 0x101a4(%rip), %rcx     # 0x192f0
leaq 0x18(%rsp), %rsi
movl 0x10(%rsp), %edi
callq 0x5b7b
testl %eax, %eax
js 0x9481
movl 0x18(%rsp), %r12d
testl %r12d, %r12d
sets %al
andb %al, %r13b
cmpb $0x1, %r13b
jne 0x9247
movl $0x400, %edi            # imm = 0x400
callq 0x127df
testl %eax, %eax
je 0x9247
negl %r12d
pushq $0x6
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
movl %r12d, %ecx
callq 0x11e6a
pushq $0x4
popq %r12
movq %rbx, %rdi
pushq $0x6
popq %rsi
movl %r12d, %edx
xorl %ecx, %ecx
callq 0x11e6a
pushq $0xc
popq %rsi
movq %rbx, %rdi
movl %r12d, %edx
pushq $0x3
popq %r12
movl %r12d, %ecx
callq 0x11e6a
movq %rbx, %rdi
movl %r12d, %esi
pushq $0x4
popq %rdx
jmp 0x9250
cmpl $0xa, %r12d
je 0x929c
cmpl $0x15, %r12d
je 0x9288
cmpl $0x12, %r12d
jne 0x92f6
testl %ebp, %ebp
je 0x9555
leaq 0x1010b(%rip), %rdi     # 0x1930c
jmp 0x908c
leaq 0x1c4e3(%rip), %r12     # 0x256f0
movq %r12, %rdi
movl 0x10(%rsp), %esi
movl %r8d, %r13d
callq 0x10b48
movq %rax, %rdi
callq 0x33f0
cvtsd2ss %xmm0, %xmm0
movd %xmm0, %ecx
pushq $0x6
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
callq 0x11e6a
movl %r13d, %ecx
movl 0x14(%r12), %r13d
jmp 0x9424
pushq $0x6
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
movl %r12d, %ecx
callq 0x11e6a
leaq 0x1c491(%rip), %rax     # 0x256f0
movl (%rax), %r13d
jmp 0x9420
cmpl $0x2, %r12d
jne 0x92c3
movq %rbx, %rdi
movl %esi, %r12d
movl 0x8d40(%rbx), %esi
subl %ecx, %esi
callq 0x5035
movl %r12d, %esi
jmp 0x936e
testl %ebp, %ebp
je 0x9529
leaq 0x100c3(%rip), %rdi     # 0x1935a
jmp 0x908c
leaq 0x1c44d(%rip), %rsi     # 0x256f0
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x10864
movq (%rbx), %rsi
leaq 0x10073(%rip), %rdi     # 0x1932d
xorl %eax, %eax
callq 0xf258
jmp 0x931f
movl %esi, 0xc(%rsp)
movslq %edx, %rdx
imulq $0xb0, %rdx, %rdx
testb $0x4, 0x28(%rax,%rdx)
movq %rbx, %r12
jne 0x932e
pushq $0x6
popq %rsi
pushq $0x2
popq %rdx
movq %r12, %rdi
callq 0x11e6a
pushq $0x1
popq %rsi
movq %r12, %rdi
callq 0x120e4
jmp 0x936a
leaq 0x1c3f3(%rip), %rsi     # 0x256f0
leaq 0x18(%rsp), %r14
movq %r14, %rdi
movl 0x10(%rsp), %edx
callq 0x10864
movq (%r14), %rsi
leaq 0x10056(%rip), %rdi     # 0x1936e
xorl %eax, %eax
callq 0xf258
leaq 0x18(%rsp), %rdi
callq 0x31a0
jmp 0x9481
addq %rdx, %rax
movl 0x34(%rax), %ecx
pushq $0x6
popq %rsi
pushq $0x2
popq %rdx
movq %r12, %rdi
callq 0x11e6a
pushq $0x4
popq %rsi
movq %r12, %rdi
callq 0x120e4
movl 0x80(%rsp), %ecx
testl %ecx, %ecx
movl 0xc(%rsp), %esi
je 0x936e
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
movq %r12, %rdi
callq 0x11e6a
movl 0xc(%rsp), %esi
movl 0xb8(%rsp), %r8d
movb 0xa8(%rsp), %r12b
orl %esi, %r13d
cmpb $0x0, 0x78(%rsp)
je 0x93a1
movl 0x10(%rsp), %edi
callq 0x8d7d
movl 0xb8(%rsp), %r8d
testl %eax, %eax
je 0x9497
movl %r13d, %eax
orl $0x10000000, %eax       # imm = 0x10000000
movb 0x90(%rsp), %cl
orb %r12b, %cl
testb %r12b, %r12b
cmovnel %eax, %r13d
testl %r8d, %r8d
je 0x93d6
pushq $0x1
popq %rsi
pushq $0x2
popq %rdx
movq %rbx, %rdi
movl %ecx, %r12d
movl %r8d, %ecx
callq 0x11e6a
movl %r12d, %ecx
testl %ebp, %ebp
sete %al
xorb $0x1, %cl
orb %cl, %al
jne 0x93e6
pushq $0x2f
jmp 0x9414
testl %ebp, %ebp
setne %al
orb %cl, %al
je 0x9412
movb 0x70(%rsp), %r12b
testb %r12b, %r12b
je 0x94e8
pushq $0x2
popq %rdx
pushq $0x3
popq %rcx
movq %rbx, %rdi
movl %ecx, %esi
callq 0x11e6a
movl %r12d, %ecx
jmp 0x9424
pushq $0x30
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
callq 0x11e4a
movb 0x70(%rsp), %cl
xorb $0x1, %cl
orb %r14b, %cl
je 0x9441
testb %r14b, %r14b
je 0x9448
leaq 0x1c2b8(%rip), %rax     # 0x256f0
movq 0x28(%rax), %rax
jmp 0x9031
orl $0x40000000, %r13d      # imm = 0x40000000
testl %ebp, %ebp
je 0x9463
movl 0x8d4c(%rbx), %edi
pushq $0x1
popq %rdx
movl %r13d, %esi
callq 0x6faa
testl %eax, %eax
jne 0x9481
jmp 0x946a
movl %r13d, 0x8d4c(%rbx)
testb %r14b, %r14b
je 0x9493
movq %rbx, %rdi
movl 0x10(%rsp), %esi
movl %ebp, %edx
callq 0x8dbb
testl %eax, %eax
je 0x9493
pushq $-0x1
popq %rax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %eax, %eax
jmp 0x9484
testb %r12b, %r12b
je 0x94c3
pushq $0x30
popq %rsi
pushq $0x2
popq %rdx
movq %rbx, %rdi
callq 0x11e4a
pushq $0x34
popq %rsi
movq %rbx, %rdi
callq 0x11de8
pushq $0x47
popq %rsi
pushq $0x5
popq %rdx
movq %rbx, %rdi
callq 0x11e4a
pushq $0xb
popq %rsi
pushq $0x2
popq %rdx
pushq $0x5
popq %rcx
movq %rbx, %rdi
callq 0x11e6a
movb 0x90(%rsp), %cl
movl 0xb8(%rsp), %r8d
jmp 0x93ba
movl 0x10(%rsp), %edi
callq 0x8d7d
testl %eax, %eax
je 0x959b
cmpb $0x0, 0x78(%rsp)
je 0x958e
pushq $0x7
popq %rsi
pushq $0x2
popq %r12
movq %rbx, %rdi
movl %r12d, %edx
callq 0x11e4a
pushq $0xb
popq %rsi
pushq $0x5
popq %rcx
movq %rbx, %rdi
movl %r12d, %edx
callq 0x11e6a
jmp 0x959b
pushq $0x6
popq %rsi
pushq $0x3
popq %rdx
movq %rbx, %rdi
movl %r8d, %r12d
xorl %ecx, %ecx
callq 0x11e6a
movl %r12d, %ecx
movl $0x40000000, %r13d      # imm = 0x40000000
leaq 0x1c1a4(%rip), %rax     # 0x256f0
orl 0x1c(%rax), %r13d
jmp 0x9424
pushq $0x6
popq %rsi
pushq $0x3
popq %r12
movq %rbx, %rdi
movl %r12d, %edx
movl %r8d, %r13d
callq 0x11e6a
movq %rbx, %rdi
movl %r12d, %esi
callq 0x120e4
movl %r13d, %ecx
movl $0x20000000, %r13d      # imm = 0x20000000
leaq 0x1c16b(%rip), %rax     # 0x256f0
orl 0x10(%rax), %r13d
jmp 0x9424
cmpl $0x1, %ebp
pushq $0x7
popq %rax
sbbl $-0x1, %eax
movl %eax, 0x14(%rsp)
pushq $0x3
popq %rdx
movq %rbx, %rdi
movl 0x14(%rsp), %esi
callq 0x11e4a
jmp 0x942c
jmp 0x95b1
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x31a0
movq %rbx, %rdi
callq 0x3560