// File: /workspace/github_c_makefile_star2_O3/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 0x4ba9(%rip), %rdi      # 0x9784
xorl %eax, %eax
callq 0x20f0
movq 0x20(%r14), %rax
testl %ebx, %ebx
jle 0x4c08
movl %ebx, %r15d
movl (%rax,%r15,4), %ecx
cmpl -0x4(%rax,%r15,4), %ecx
jne 0x4c08
leaq 0x4b8b(%rip), %rdi      # 0x978a
xorl %eax, %eax
callq 0x20f0
jmp 0x4c1d
movslq %ebx, %r15
movl (%rax,%r15,4), %esi
leaq 0x4b7a(%rip), %rdi      # 0x9790
xorl %eax, %eax
callq 0x20f0
movq 0x10(%r14), %rax
movzbl (%rax,%r15), %esi
cmpq $0x31, %rsi
ja 0x5095
leaq 0x4a85(%rip), %rcx      # 0x96bc
movslq (%rcx,%rsi,4), %rdx
addq %rcx, %rdx
jmpq *%rdx
leaq 0x4b4e(%rip), %rdi      # 0x9795
jmp 0x5080
movzbl 0x2(%rax,%r15), %edx
leaq 0x4de5(%rip), %rdi      # 0x9a3e
leaq 0x4d5a(%rip), %rsi      # 0x99ba
jmp 0x4fad
leaq 0x4ce3(%rip), %rdi      # 0x994f
jmp 0x505f
leaq 0x4d79(%rip), %rdi      # 0x99f1
jmp 0x505f
leaq 0x4cb6(%rip), %rdi      # 0x993a
jmp 0x505f
leaq 0x4cb6(%rip), %rdi      # 0x9946
jmp 0x505f
leaq 0x4c43(%rip), %rdi      # 0x98df
jmp 0x505f
leaq 0x4c86(%rip), %rdi      # 0x992e
jmp 0x505f
leaq 0x4ba7(%rip), %rdi      # 0x985b
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4d78(%rip), %rdi      # 0x9a3e
leaq 0x4cf7(%rip), %rsi      # 0x99c4
jmp 0x4fad
movzbl 0x2(%rax,%r15), %edx
leaq 0x4d5f(%rip), %rdi      # 0x9a3e
leaq 0x4b58(%rip), %rsi      # 0x983e
jmp 0x4fad
leaq 0x4c30(%rip), %rdi      # 0x9922
jmp 0x505f
leaq 0x4cfb(%rip), %rdi      # 0x99f9
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4d2e(%rip), %rdi      # 0x9a3e
leaq 0x4af9(%rip), %rsi      # 0x9810
jmp 0x4fad
leaq 0x4ce0(%rip), %rdi      # 0x9a03
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4d09(%rip), %rdi      # 0x9a3e
leaq 0x4a7d(%rip), %rsi      # 0x97b9
jmp 0x4fad
movzbl 0x2(%rax,%r15), %r15d
leaq 0x4c23(%rip), %rdi      # 0x9971
leaq 0x4c27(%rip), %rsi      # 0x997c
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 0x7487
movl $0xa, %edi
callq 0x2040
movq 0x40(%r14), %rax
movq 0x8(%rax,%r15), %r12
leal 0x3(%rbx), %ebp
cmpw $0x0, 0x22(%r12)
je 0x5068
movslq %ebp, %r13
addl $0x4, %ebx
leaq 0x4be2(%rip), %r15      # 0x9987
xorl %ebp, %ebp
movq 0x10(%r14), %rax
cmpb $0x0, (%rax,%r13)
movzbl 0x2(%rax,%r13), %ecx
leaq 0x4bdb(%rip), %rdx      # 0x9998
leaq 0x4bda(%rip), %rax      # 0x999e
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 0x4da7
decl %ebx
jmp 0x5066
movzbl 0x2(%rax,%r15), %edx
leaq 0x4c45(%rip), %rdi      # 0x9a3e
leaq 0x4a1f(%rip), %rsi      # 0x981f
jmp 0x4fad
leaq 0x49e8(%rip), %rdi      # 0x97f4
jmp 0x5080
leaq 0x4ab1(%rip), %rdi      # 0x98c9
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ecx
subl %edx, %ecx
addl $0x2, %ecx
leaq 0x4c18(%rip), %rdi      # 0x9a49
leaq 0x4a89(%rip), %rsi      # 0x98c1
xorl %eax, %eax
callq 0x20f0
jmp 0x4fb4
leaq 0x495f(%rip), %rdi      # 0x97aa
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4be1(%rip), %rdi      # 0x9a3e
leaq 0x49ea(%rip), %rsi      # 0x984e
jmp 0x4fad
leaq 0x4941(%rip), %rdi      # 0x97b1
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4bbc(%rip), %rdi      # 0x9a3e
leaq 0x494d(%rip), %rsi      # 0x97d6
jmp 0x4fad
leaq 0x490c(%rip), %rdi      # 0x97a1
jmp 0x505f
leaq 0x4a70(%rip), %rdi      # 0x9911
jmp 0x505f
leaq 0x49bf(%rip), %rdi      # 0x986c
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4b7f(%rip), %rdi      # 0x9a3e
leaq 0x4ae0(%rip), %rsi      # 0x99a6
jmp 0x4fad
movzbl 0x1(%rax,%r15), %ecx
movzbl 0x3(%rax,%r15), %edx
leaq 0x4b6b(%rip), %rdi      # 0x9a49
leaq 0x49aa(%rip), %rsi      # 0x988f
jmp 0x5000
leaq 0x48d1(%rip), %rdi      # 0x97c2
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ebp
addl $0x3, %ebp
leal (%rbx,%rdx), %ecx
addl $0x3, %ecx
leaq 0x4b3b(%rip), %rdi      # 0x9a49
leaq 0x4983(%rip), %rsi      # 0x9898
jmp 0x5034
movzbl 0x2(%rax,%r15), %edx
leaq 0x4b17(%rip), %rdi      # 0x9a3e
leaq 0x4900(%rip), %rsi      # 0x982e
jmp 0x4fad
movzbl 0x2(%rax,%r15), %edx
leaq 0x4b01(%rip), %rdi      # 0x9a3e
leaq 0x4885(%rip), %rsi      # 0x97c9
jmp 0x4fad
movzbl 0x1(%rax,%r15), %edx
leaq 0x4aeb(%rip), %rdi      # 0x9a3e
leaq 0x4923(%rip), %rsi      # 0x987d
xorl %eax, %eax
callq 0x20f0
addl $0x2, %ebx
jmp 0x5066
leaq 0x4892(%rip), %rdi      # 0x9802
jmp 0x5080
leaq 0x4867(%rip), %rdi      # 0x97e3
jmp 0x5080
leaq 0x497b(%rip), %rdi      # 0x9903
jmp 0x505f
leaq 0x4984(%rip), %rdi      # 0x9918
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
leaq 0x4a98(%rip), %rdi      # 0x9a3e
leaq 0x4a29(%rip), %rsi      # 0x99d6
xorl %eax, %eax
callq 0x20f0
addl $0x3, %ebx
jmp 0x5066
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ebp
addl $0x3, %ebp
leal (%rbx,%rdx), %ecx
addl $0x3, %ecx
leaq 0x4a75(%rip), %rdi      # 0x9a49
leaq 0x48c5(%rip), %rsi      # 0x98a0
jmp 0x5034
leaq 0x497c(%rip), %rdi      # 0x9960
jmp 0x505f
movzbl 0x1(%rax,%r15), %ecx
movzbl 0x3(%rax,%r15), %edx
leaq 0x4a50(%rip), %rdi      # 0x9a49
leaq 0x4885(%rip), %rsi      # 0x9885
xorl %eax, %eax
callq 0x20f0
addl $0x4, %ebx
jmp 0x5066
leaq 0x499c(%rip), %rdi      # 0x99af
jmp 0x505f
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ebp
addl $0x3, %ebp
leal (%rbx,%rdx), %ecx
addl $0x3, %ecx
leaq 0x4a1c(%rip), %rdi      # 0x9a49
leaq 0x487d(%rip), %rsi      # 0x98b1
xorl %eax, %eax
callq 0x20f0
jmp 0x5068
leaq 0x48a6(%rip), %rdi      # 0x98ea
jmp 0x505f
leaq 0x48ae(%rip), %rdi      # 0x98fb
jmp 0x505f
leaq 0x4900(%rip), %rdi      # 0x9956
jmp 0x505f
leaq 0x4873(%rip), %rdi      # 0x98d2
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 0x4967(%rip), %rdi      # 0x99e7
movq %r14, %rsi
movl %ebx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x50a5
leaq 0x4971(%rip), %rdi      # 0x9a0d
xorl %eax, %eax
callq 0x20f0
jmp 0x5064