// File: /workspace/github_c_makefile_star2_O2/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 0x52dd(%rip), %rdi      # 0x9748
xorl %eax, %eax
callq 0x20f0
movq 0x20(%r14), %rax
testl %ebx, %ebx
jle 0x4498
movl %ebx, %r15d
movl (%rax,%r15,4), %ecx
cmpl -0x4(%rax,%r15,4), %ecx
jne 0x4498
leaq 0x52bf(%rip), %rdi      # 0x974e
xorl %eax, %eax
callq 0x20f0
jmp 0x44ad
movslq %ebx, %r15
movl (%rax,%r15,4), %esi
leaq 0x52ae(%rip), %rdi      # 0x9754
xorl %eax, %eax
callq 0x20f0
movq 0x10(%r14), %rax
movzbl (%rax,%r15), %esi
cmpq $0x31, %rsi
ja 0x4831
leaq 0x51b9(%rip), %rcx      # 0x9680
movslq (%rcx,%rsi,4), %rdx
addq %rcx, %rdx
jmpq *%rdx
leaq 0x5282(%rip), %rdi      # 0x9759
jmp 0x481c
leaq 0x549b(%rip), %rdi      # 0x997e
jmp 0x476a
leaq 0x5424(%rip), %rdi      # 0x9913
jmp 0x47fd
leaq 0x54ba(%rip), %rdi      # 0x99b5
jmp 0x47fd
leaq 0x53f7(%rip), %rdi      # 0x98fe
jmp 0x47fd
leaq 0x53f7(%rip), %rdi      # 0x990a
jmp 0x47fd
leaq 0x5384(%rip), %rdi      # 0x98a3
jmp 0x47fd
leaq 0x53c7(%rip), %rdi      # 0x98f2
jmp 0x47fd
leaq 0x52e8(%rip), %rdi      # 0x981f
jmp 0x47fd
leaq 0x5445(%rip), %rdi      # 0x9988
jmp 0x476a
leaq 0x52b3(%rip), %rdi      # 0x9802
jmp 0x476a
leaq 0x538b(%rip), %rdi      # 0x98e6
jmp 0x47fd
leaq 0x5456(%rip), %rdi      # 0x99bd
jmp 0x47fd
leaq 0x5261(%rip), %rdi      # 0x97d4
jmp 0x476a
leaq 0x5448(%rip), %rdi      # 0x99c7
jmp 0x47fd
leaq 0x51f2(%rip), %rdi      # 0x977d
jmp 0x476a
movzbl 0x2(%rax,%r15), %ebx
leaq 0x5398(%rip), %rdi      # 0x9935
leaq 0x539c(%rip), %rsi      # 0x9940
movl %ebx, %edx
xorl %eax, %eax
callq 0x20f0
movq 0x40(%r14), %rax
shll $0x4, %ebx
movl (%rax,%rbx), %edi
movq 0x8(%rax,%rbx), %rsi
callq 0x6797
pushq $0xa
popq %rdi
callq 0x2040
movq 0x40(%r14), %rax
movq 0x8(%rax,%rbx), %r12
leaq 0x5383(%rip), %rbp      # 0x995c
leaq 0x536b(%rip), %rbx      # 0x994b
xorl %r13d, %r13d
cmpw 0x22(%r12), %r13w
jae 0x4620
movq 0x10(%r14), %rax
cmpb $0x0, 0x3(%rax,%r15)
movzbl 0x5(%rax,%r15), %ecx
movq %rbp, %rdx
leaq 0x535d(%rip), %rax      # 0x9962
cmoveq %rax, %rdx
leal 0x4(%r15), %esi
movq %rbx, %rdi
xorl %eax, %eax
callq 0x20f0
incl %r13d
addq $0x3, %r15
jmp 0x45e3
addl $0x3, %r15d
movl %r15d, %ebx
jmp 0x4804
leaq 0x51b0(%rip), %rdi      # 0x97e3
jmp 0x476a
leaq 0x5179(%rip), %rdi      # 0x97b8
jmp 0x481c
leaq 0x5242(%rip), %rdi      # 0x988d
jmp 0x47fd
movzbl 0x2(%rax,%r15), %edx
movl %ebx, %ecx
subl %edx, %ecx
addl $0x2, %ecx
leaq 0x53a9(%rip), %rdi      # 0x9a0d
leaq 0x521a(%rip), %rsi      # 0x9885
xorl %eax, %eax
callq 0x20f0
addl $0x3, %ebx
jmp 0x4804
leaq 0x50ed(%rip), %rdi      # 0x976e
jmp 0x47fd
leaq 0x5185(%rip), %rdi      # 0x9812
jmp 0x476a
leaq 0x50dc(%rip), %rdi      # 0x9775
jmp 0x47fd
leaq 0x50f5(%rip), %rdi      # 0x979a
jmp 0x476a
leaq 0x50b4(%rip), %rdi      # 0x9765
jmp 0x47fd
leaq 0x5218(%rip), %rdi      # 0x98d5
jmp 0x47fd
leaq 0x5167(%rip), %rdi      # 0x9830
jmp 0x47fd
leaq 0x5295(%rip), %rdi      # 0x996a
jmp 0x476a
leaq 0x5172(%rip), %rdi      # 0x9853
jmp 0x479b
leaq 0x5099(%rip), %rdi      # 0x9786
jmp 0x47fd
leaq 0x5163(%rip), %rdi      # 0x985c
jmp 0x47c3
leaq 0x50ed(%rip), %rdi      # 0x97f2
jmp 0x476a
leaq 0x507f(%rip), %rdi      # 0x978d
jmp 0x476a
movzbl 0x1(%rax,%r15), %edx
leaq 0x52e5(%rip), %rdi      # 0x9a02
leaq 0x511d(%rip), %rsi      # 0x9841
xorl %eax, %eax
callq 0x20f0
addl $0x2, %ebx
jmp 0x4804
leaq 0x508c(%rip), %rdi      # 0x97c6
jmp 0x481c
leaq 0x5061(%rip), %rdi      # 0x97a7
jmp 0x481c
leaq 0x5175(%rip), %rdi      # 0x98c7
jmp 0x47fd
leaq 0x517e(%rip), %rdi      # 0x98dc
jmp 0x47fd
leaq 0x5230(%rip), %rdi      # 0x999a
movq %r14, %rsi
movl %ebx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x4897
leaq 0x50db(%rip), %rdi      # 0x9864
jmp 0x47c3
leaq 0x5192(%rip), %rdi      # 0x9924
jmp 0x47fd
leaq 0x50ae(%rip), %rdi      # 0x9849
movq %r14, %rsi
movl %ebx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x48bf
leaq 0x51b9(%rip), %rdi      # 0x9973
jmp 0x47fd
leaq 0x50b2(%rip), %rdi      # 0x9875
movq %r14, %rsi
movl %ebx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x48ec
leaq 0x50cc(%rip), %rdi      # 0x98ae
jmp 0x47fd
leaq 0x50d4(%rip), %rdi      # 0x98bf
jmp 0x47fd
leaq 0x5126(%rip), %rdi      # 0x991a
jmp 0x47fd
leaq 0x5099(%rip), %rdi      # 0x9896
callq 0x2070
incl %ebx
movl %ebx, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x518f(%rip), %rdi      # 0x99ab
movq %r14, %rsi
movl %ebx, %edx
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x4841
leaq 0x5199(%rip), %rdi      # 0x99d1
xorl %eax, %eax
callq 0x20f0
jmp 0x4802