// File: /workspace/github_c_makefile_star2_O1/adamjedlicka[P]blu/src/vm/debug/debug.c
// Function: bluDisassembleInstruction
int32_t bluDisassembleInstruction(bluChunk* chunk, int32_t offset) {
	printf("%04d ", offset);
	if (offset > 0 && chunk->lines.data[offset] == chunk->lines.data[offset - 1]) {
		printf("   | ");
	} else {
		printf("%4d ", chunk->lines.data[offset]);
	}

	uint8_t instruction = chunk->code.data[offset];

	switch (instruction) {

	case OP_CONSTANT: return constantInstruction("OP_CONSTANT", chunk, offset);
	case OP_FALSE: return simpleInstruction("OP_FALSE", offset);
	case OP_NIL: return simpleInstruction("OP_NIL", offset);
	case OP_TRUE: return simpleInstruction("OP_TRUE", offset);
	case OP_ARRAY: return shortInstruction("OP_ARRAY", chunk, offset);

	case OP_POP: return simpleInstruction("OP_POP", offset);

	case OP_GET_LOCAL: return shortInstruction("OP_GET_LOCAL", chunk, offset);
	case OP_SET_LOCAL: return shortInstruction("OP_SET_LOCAL", chunk, offset);
	case OP_DEFINE_GLOBAL: return constantInstruction("OP_DEFINE_GLOBAL", chunk, offset);
	case OP_GET_GLOBAL: return constantInstruction("OP_GET_GLOBAL", chunk, offset);
	case OP_SET_GLOBAL: return constantInstruction("OP_SET_GLOBAL", chunk, offset);
	case OP_GET_UPVALUE: return shortInstruction("OP_GET_UPVALUE", chunk, offset);
	case OP_SET_UPVALUE: return shortInstruction("OP_SET_UPVALUE", chunk, offset);
	case OP_GET_PROPERTY: return shortInstruction("OP_GET_PROPERTY", chunk, offset);
	case OP_SET_PROPERTY: return shortInstruction("OP_SET_PROPERTY", chunk, offset);
	case OP_GET_SUPER: return shortInstruction("OP_GET_SUPER", chunk, offset);
	case OP_SUBSCRIPT_GET: return simpleInstruction("OP_SUBSCRIPT_GET", offset);
	case OP_SUBSCRIPT_SET: return simpleInstruction("OP_SUBSCRIPT_SET", offset);

	case OP_CALL: return byteInstruction("OP_CALL", chunk, offset);
	case OP_INVOKE: return invokeInstruction("OP_INVOKE", chunk, offset);
	case OP_SUPER: return invokeInstruction("OP_SUPER", chunk, offset);
	case OP_JUMP: return jumpInstruction("OP_JUMP", chunk, offset);
	case OP_JUMP_IF_FALSE: return jumpInstruction("OP_JUMP_IF_FALSE", chunk, offset);
	case OP_JUMP_IF_TRUE: return jumpInstruction("OP_JUMP_IF_TRUE", chunk, offset);
	case OP_LOOP: return loopInstruction("OP_LOOP", chunk, offset);

	case OP_EQUAL: return simpleInstruction("OP_EQUAL", offset);
	case OP_NOT_EQUAL: return simpleInstruction("OP_NOT_EQUAL", offset);
	case OP_GREATER: return simpleInstruction("OP_GREATER", offset);
	case OP_GREATER_EQUAL: return simpleInstruction("OP_GREATER_EQUAL", offset);
	case OP_LESS: return simpleInstruction("OP_LESS", offset);
	case OP_LESS_EQUAL: return simpleInstruction("OP_LESS_EQUAL", offset);
	case OP_ADD: return simpleInstruction("OP_ADD", offset);
	case OP_DIVIDE: return simpleInstruction("OP_DIVIDE", offset);
	case OP_REMINDER: return simpleInstruction("OP_REMINDER", offset);
	case OP_SUBTRACT: return simpleInstruction("OP_SUBTRACT", offset);
	case OP_MULTIPLY: return simpleInstruction("OP_MULTIPLY", offset);
	case OP_POWER: return simpleInstruction("OP_POWER", offset);
	case OP_NOT: return simpleInstruction("OP_NOT", offset);
	case OP_NEGATE: return simpleInstruction("OP_NEGATE", offset);

	case OP_CLOSE_OPVALUE: return simpleInstruction("OP_CLOSE_OPVALUE", offset);
	case OP_CLOSURE: {
		uint16_t slot = ((chunk->code.data[offset + 1] << 8) & 0xff) | (chunk->code.data[offset + 2] & 0xff);
		offset += 3;

		printf("%-16s %6d ", "OP_CLOSURE", slot);
		bluPrintValue(chunk->constants.data[slot]);
		printf("\n");

		bluObjFunction* function = AS_FUNCTION(chunk->constants.data[slot]);
		for (uint16_t i = 0; i < function->upvalueCount; i++) {
			bool isLocal = chunk->code.data[offset];
			uint16_t index = ((chunk->code.data[offset + 1] << 8) & 0xff) | (chunk->code.data[offset + 2] & 0xff);
			offset += 3;
			printf("%04d    | %s %d\n", offset - 2, isLocal ? "local" : "upvalue", index);
		}

		return offset;
	}

	case OP_CLASS: return shortInstruction("OP_CLASS", chunk, offset);
	case OP_INHERIT: return simpleInstruction("OP_INHERIT", offset);
	case OP_METHOD: return shortInstruction("OP_METHOD", chunk, offset);
	case OP_METHOD_FOREIGN: return shortInstruction("OP_METHOD_FOREIGN", chunk, offset);
	case OP_METHOD_STATIC: return shortInstruction("OP_METHOD_STATIC", chunk, offset);

	case OP_IMPORT: return constantInstruction("OP_IMPORT", chunk, offset);

	case OP_ECHO: return simpleInstruction("OP_ECHO", offset);
	case OP_RETURN: return simpleInstruction("OP_RETURN", offset);

	case OP_ASSERT: return simpleInstruction("OP_ASSERT", offset);

	default: printf("Unknown opcode %d\n", instruction); return offset + 1;
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %esi, %ebx
movq %rdi, %r14
leaq 0x3d81(%rip), %rdi      # 0xaad4
xorl %eax, %eax
callq 0x20f0
movslq %ebx, %r15
testl %ebx, %ebx
jle 0x6d80
movq 0x20(%r14), %rax
movl %ebx, %ecx
movl (%rax,%rcx,4), %edx
cmpl -0x4(%rax,%rcx,4), %edx
jne 0x6d80
leaq 0x3d63(%rip), %rdi      # 0xaada
xorl %eax, %eax
callq 0x20f0
jmp 0x6d96
movq 0x20(%r14), %rax
movl (%rax,%r15,4), %esi
leaq 0x3d51(%rip), %rdi      # 0xaae0
xorl %eax, %eax
callq 0x20f0
movq 0x10(%r14), %rax
movzbl (%rax,%r15), %esi
cmpq $0x31, %rsi
ja 0x720e
leaq 0x3c5c(%rip), %rcx      # 0xaa0c
movslq (%rcx,%rsi,4), %rdx
addq %rcx, %rdx
jmpq *%rdx
leaq 0x3d25(%rip), %rdi      # 0xaae5
jmp 0x71f9
movzbl 0x2(%rax,%r15), %edx
leaq 0x3fbc(%rip), %rdi      # 0xad8e
leaq 0x3f31(%rip), %rsi      # 0xad0a
jmp 0x7126
leaq 0x3eba(%rip), %rdi      # 0xac9f
jmp 0x71d8
leaq 0x3f50(%rip), %rdi      # 0xad41
jmp 0x71d8
leaq 0x3e8d(%rip), %rdi      # 0xac8a
jmp 0x71d8
leaq 0x3e8d(%rip), %rdi      # 0xac96
jmp 0x71d8
leaq 0x3e1a(%rip), %rdi      # 0xac2f
jmp 0x71d8
leaq 0x3e5d(%rip), %rdi      # 0xac7e
jmp 0x71d8
leaq 0x3d7e(%rip), %rdi      # 0xabab
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3f4f(%rip), %rdi      # 0xad8e
leaq 0x3ece(%rip), %rsi      # 0xad14
jmp 0x7126
movzbl 0x2(%rax,%r15), %edx
leaq 0x3f36(%rip), %rdi      # 0xad8e
leaq 0x3d2f(%rip), %rsi      # 0xab8e
jmp 0x7126
leaq 0x3e07(%rip), %rdi      # 0xac72
jmp 0x71d8
leaq 0x3ed2(%rip), %rdi      # 0xad49
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3f05(%rip), %rdi      # 0xad8e
leaq 0x3cd0(%rip), %rsi      # 0xab60
jmp 0x7126
leaq 0x3eb7(%rip), %rdi      # 0xad53
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3ee0(%rip), %rdi      # 0xad8e
leaq 0x3c54(%rip), %rsi      # 0xab09
jmp 0x7126
movzbl 0x2(%rax,%r15), %r15d
leaq 0x3dfa(%rip), %rdi      # 0xacc1
leaq 0x3dfe(%rip), %rsi      # 0xaccc
movl %r15d, %edx
xorl %eax, %eax
callq 0x20f0
movq 0x40(%r14), %rax
shll $0x4, %r15d
movl (%rax,%r15), %edi
movq 0x8(%rax,%r15), %rsi
callq 0x2981
movl $0xa, %edi
callq 0x2040
movq 0x40(%r14), %rax
movq 0x8(%rax,%r15), %r12
leal 0x3(%rbx), %ebp
cmpw $0x0, 0x22(%r12)
je 0x71e1
movslq %ebp, %r13
addl $0x4, %ebx
leaq 0x3db9(%rip), %r15      # 0xacd7
xorl %ebp, %ebp
movq 0x10(%r14), %rax
cmpb $0x0, (%rax,%r13)
movzbl 0x2(%rax,%r13), %ecx
leaq 0x3db2(%rip), %rdx      # 0xace8
leaq 0x3db1(%rip), %rax      # 0xacee
cmoveq %rax, %rdx
movq %r15, %rdi
movl %ebx, %esi
xorl %eax, %eax
callq 0x20f0
incl %ebp
addq $0x3, %r13
addl $0x3, %ebx
cmpw 0x22(%r12), %bp
jb 0x6f20
decl %ebx
jmp 0x71df
movzbl 0x2(%rax,%r15), %edx
leaq 0x3e1c(%rip), %rdi      # 0xad8e
leaq 0x3bf6(%rip), %rsi      # 0xab6f
jmp 0x7126
leaq 0x3bbf(%rip), %rdi      # 0xab44
jmp 0x71f9
leaq 0x3c88(%rip), %rdi      # 0xac19
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ecx
subl %edx, %ecx
addl $0x2, %ecx
leaq 0x3def(%rip), %rdi      # 0xad99
leaq 0x3c60(%rip), %rsi      # 0xac11
xorl %eax, %eax
callq 0x20f0
jmp 0x712d
leaq 0x3b36(%rip), %rdi      # 0xaafa
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3db8(%rip), %rdi      # 0xad8e
leaq 0x3bc1(%rip), %rsi      # 0xab9e
jmp 0x7126
leaq 0x3b18(%rip), %rdi      # 0xab01
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3d93(%rip), %rdi      # 0xad8e
leaq 0x3b24(%rip), %rsi      # 0xab26
jmp 0x7126
leaq 0x3ae3(%rip), %rdi      # 0xaaf1
jmp 0x71d8
leaq 0x3c47(%rip), %rdi      # 0xac61
jmp 0x71d8
leaq 0x3b96(%rip), %rdi      # 0xabbc
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3d56(%rip), %rdi      # 0xad8e
leaq 0x3cb7(%rip), %rsi      # 0xacf6
jmp 0x7126
movzbl 0x1(%rax,%r15), %ecx
movzbl 0x3(%rax,%r15), %edx
leaq 0x3d42(%rip), %rdi      # 0xad99
leaq 0x3b81(%rip), %rsi      # 0xabdf
jmp 0x7179
leaq 0x3aa8(%rip), %rdi      # 0xab12
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ebp
addl $0x3, %ebp
leal (%rbx,%rdx), %ecx
addl $0x3, %ecx
leaq 0x3d12(%rip), %rdi      # 0xad99
leaq 0x3b5a(%rip), %rsi      # 0xabe8
jmp 0x71ad
movzbl 0x2(%rax,%r15), %edx
leaq 0x3cee(%rip), %rdi      # 0xad8e
leaq 0x3ad7(%rip), %rsi      # 0xab7e
jmp 0x7126
movzbl 0x2(%rax,%r15), %edx
leaq 0x3cd8(%rip), %rdi      # 0xad8e
leaq 0x3a5c(%rip), %rsi      # 0xab19
jmp 0x7126
movzbl 0x1(%rax,%r15), %edx
leaq 0x3cc2(%rip), %rdi      # 0xad8e
leaq 0x3afa(%rip), %rsi      # 0xabcd
xorl %eax, %eax
callq 0x20f0
addl $0x2, %ebx
jmp 0x71df
leaq 0x3a69(%rip), %rdi      # 0xab52
jmp 0x71f9
leaq 0x3a3e(%rip), %rdi      # 0xab33
jmp 0x71f9
leaq 0x3b52(%rip), %rdi      # 0xac53
jmp 0x71d8
leaq 0x3b5b(%rip), %rdi      # 0xac68
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
leaq 0x3c6f(%rip), %rdi      # 0xad8e
leaq 0x3c00(%rip), %rsi      # 0xad26
xorl %eax, %eax
callq 0x20f0
addl $0x3, %ebx
jmp 0x71df
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ebp
addl $0x3, %ebp
leal (%rbx,%rdx), %ecx
addl $0x3, %ecx
leaq 0x3c4c(%rip), %rdi      # 0xad99
leaq 0x3a9c(%rip), %rsi      # 0xabf0
jmp 0x71ad
leaq 0x3b53(%rip), %rdi      # 0xacb0
jmp 0x71d8
movzbl 0x1(%rax,%r15), %ecx
movzbl 0x3(%rax,%r15), %edx
leaq 0x3c27(%rip), %rdi      # 0xad99
leaq 0x3a5c(%rip), %rsi      # 0xabd5
xorl %eax, %eax
callq 0x20f0
addl $0x4, %ebx
jmp 0x71df
leaq 0x3b73(%rip), %rdi      # 0xacff
jmp 0x71d8
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ebp
addl $0x3, %ebp
leal (%rbx,%rdx), %ecx
addl $0x3, %ecx
leaq 0x3bf3(%rip), %rdi      # 0xad99
leaq 0x3a54(%rip), %rsi      # 0xac01
xorl %eax, %eax
callq 0x20f0
jmp 0x71e1
leaq 0x3a7d(%rip), %rdi      # 0xac3a
jmp 0x71d8
leaq 0x3a85(%rip), %rdi      # 0xac4b
jmp 0x71d8
leaq 0x3ad7(%rip), %rdi      # 0xaca6
jmp 0x71d8
leaq 0x3a4a(%rip), %rdi      # 0xac22
callq 0x2070
incl %ebx
movl %ebx, %ebp
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3b3e(%rip), %rdi      # 0xad37
movq %r14, %rsi
movl %ebx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x721e
leaq 0x3b48(%rip), %rdi      # 0xad5d
xorl %eax, %eax
callq 0x20f0
jmp 0x71dd