// File: rossy[P]crossc/SPIRV-Cross/spirv_msl.cpp
// Function: spirv_cross::CompilerMSL::emit_glsl_op(unsigned int, unsigned int, unsigned int, unsigned int const*, unsigned int)
void CompilerMSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop, const uint32_t *args, uint32_t count)
{
	GLSLstd450 op = static_cast<GLSLstd450>(eop);

	switch (op)
	{
	case GLSLstd450Atan2:
		emit_binary_func_op(result_type, id, args[0], args[1], "atan2");
		break;
	case GLSLstd450InverseSqrt:
		emit_unary_func_op(result_type, id, args[0], "rsqrt");
		break;
	case GLSLstd450RoundEven:
		emit_unary_func_op(result_type, id, args[0], "rint");
		break;

	case GLSLstd450FindSMsb:
		emit_unary_func_op(result_type, id, args[0], "findSMSB");
		break;
	case GLSLstd450FindUMsb:
		emit_unary_func_op(result_type, id, args[0], "findUMSB");
		break;

	case GLSLstd450PackSnorm4x8:
		emit_unary_func_op(result_type, id, args[0], "pack_float_to_snorm4x8");
		break;
	case GLSLstd450PackUnorm4x8:
		emit_unary_func_op(result_type, id, args[0], "pack_float_to_unorm4x8");
		break;
	case GLSLstd450PackSnorm2x16:
		emit_unary_func_op(result_type, id, args[0], "pack_float_to_snorm2x16");
		break;
	case GLSLstd450PackUnorm2x16:
		emit_unary_func_op(result_type, id, args[0], "pack_float_to_unorm2x16");
		break;

	case GLSLstd450PackHalf2x16:
	{
		auto expr = join("as_type<uint>(half2(", to_expression(args[0]), "))");
		emit_op(result_type, id, expr, should_forward(args[0]));
		inherit_expression_dependencies(id, args[0]);
		break;
	}

	case GLSLstd450UnpackSnorm4x8:
		emit_unary_func_op(result_type, id, args[0], "unpack_snorm4x8_to_float");
		break;
	case GLSLstd450UnpackUnorm4x8:
		emit_unary_func_op(result_type, id, args[0], "unpack_unorm4x8_to_float");
		break;
	case GLSLstd450UnpackSnorm2x16:
		emit_unary_func_op(result_type, id, args[0], "unpack_snorm2x16_to_float");
		break;
	case GLSLstd450UnpackUnorm2x16:
		emit_unary_func_op(result_type, id, args[0], "unpack_unorm2x16_to_float");
		break;

	case GLSLstd450UnpackHalf2x16:
	{
		auto expr = join("float2(as_type<half2>(", to_expression(args[0]), "))");
		emit_op(result_type, id, expr, should_forward(args[0]));
		inherit_expression_dependencies(id, args[0]);
		break;
	}

	case GLSLstd450PackDouble2x32:
		emit_unary_func_op(result_type, id, args[0], "unsupported_GLSLstd450PackDouble2x32"); // Currently unsupported
		break;
	case GLSLstd450UnpackDouble2x32:
		emit_unary_func_op(result_type, id, args[0], "unsupported_GLSLstd450UnpackDouble2x32"); // Currently unsupported
		break;

	case GLSLstd450MatrixInverse:
	{
		auto &mat_type = get<SPIRType>(result_type);
		switch (mat_type.columns)
		{
		case 2:
			emit_unary_func_op(result_type, id, args[0], "spvInverse2x2");
			break;
		case 3:
			emit_unary_func_op(result_type, id, args[0], "spvInverse3x3");
			break;
		case 4:
			emit_unary_func_op(result_type, id, args[0], "spvInverse4x4");
			break;
		default:
			break;
		}
		break;
	}

	case GLSLstd450FMin:
		// If the result type isn't float, don't bother calling the specific
		// precise::/fast:: version. Metal doesn't have those for half and
		// double types.
		if (get<SPIRType>(result_type).basetype != SPIRType::Float)
			emit_binary_func_op(result_type, id, args[0], args[1], "min");
		else
			emit_binary_func_op(result_type, id, args[0], args[1], "fast::min");
		break;

	case GLSLstd450FMax:
		if (get<SPIRType>(result_type).basetype != SPIRType::Float)
			emit_binary_func_op(result_type, id, args[0], args[1], "max");
		else
			emit_binary_func_op(result_type, id, args[0], args[1], "fast::max");
		break;

	case GLSLstd450FClamp:
		// TODO: If args[1] is 0 and args[2] is 1, emit a saturate() call.
		if (get<SPIRType>(result_type).basetype != SPIRType::Float)
			emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "clamp");
		else
			emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "fast::clamp");
		break;

	case GLSLstd450NMin:
		if (get<SPIRType>(result_type).basetype != SPIRType::Float)
			emit_binary_func_op(result_type, id, args[0], args[1], "min");
		else
			emit_binary_func_op(result_type, id, args[0], args[1], "precise::min");
		break;

	case GLSLstd450NMax:
		if (get<SPIRType>(result_type).basetype != SPIRType::Float)
			emit_binary_func_op(result_type, id, args[0], args[1], "max");
		else
			emit_binary_func_op(result_type, id, args[0], args[1], "precise::max");
		break;

	case GLSLstd450NClamp:
		// TODO: If args[1] is 0 and args[2] is 1, emit a saturate() call.
		if (get<SPIRType>(result_type).basetype != SPIRType::Float)
			emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "clamp");
		else
			emit_trinary_func_op(result_type, id, args[0], args[1], args[2], "precise::clamp");
		break;

		// TODO:
		//        GLSLstd450InterpolateAtCentroid (centroid_no_perspective qualifier)
		//        GLSLstd450InterpolateAtSample (sample_no_perspective qualifier)
		//        GLSLstd450InterpolateAtOffset

	default:
		CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
		break;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movq %r8, -0x20(%rbp)
movl %r9d, -0x24(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xd0(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %eax
addl $-0x2, %eax
movl %eax, %ecx
movq %rcx, -0xc8(%rbp)
subl $0x4f, %eax
ja 0xffda7
movq -0xc8(%rbp), %rax
leaq 0x4ab81(%rip), %rcx     # 0x14a198
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4903f(%rip), %r9      # 0x148681
callq 0x79330
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x48fb8(%rip), %r8      # 0x14861e
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d798(%rip), %r8      # 0x14ce22
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d779(%rip), %r8      # 0x14ce27
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d75e(%rip), %r8      # 0x14ce30
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d743(%rip), %r8      # 0x14ce39
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d736(%rip), %r8      # 0x14ce50
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d729(%rip), %r8      # 0x14ce67
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d71d(%rip), %r8      # 0x14ce7f
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rsi
movq -0x20(%rbp), %rax
movl (%rax), %edx
leaq -0x68(%rbp), %rdi
movq %rdi, -0xd8(%rbp)
callq 0x71b50
movq -0xd8(%rbp), %rdx
leaq 0x4d700(%rip), %rsi     # 0x14ce97
leaq 0x4d3ee(%rip), %rcx     # 0x14cb8c
leaq -0x48(%rbp), %rdi
callq 0x116d80
jmp 0xff7a9
leaq -0x68(%rbp), %rdi
callq 0x7708
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %eax
movl %eax, -0xe4(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0xe0(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0x78810
movb %al, -0xd9(%rbp)
jmp 0xff7de
movl -0xe0(%rbp), %edx
movl -0xe4(%rbp), %esi
movq -0xd0(%rbp), %rdi
movb -0xd9(%rbp), %al
movzbl %al, %r8d
andl $0x1, %r8d
leaq -0x48(%rbp), %rcx
xorl %r9d, %r9d
callq 0x784f0
jmp 0xff80d
movq -0xd0(%rbp), %rdi
movl -0x10(%rbp), %esi
movq -0x20(%rbp), %rax
movl (%rax), %edx
callq 0x25500
jmp 0xff824
leaq -0x48(%rbp), %rdi
callq 0x7708
jmp 0xffdc4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x7708
jmp 0xffdcd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x7708
jmp 0xffdcd
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d62c(%rip), %r8      # 0x14ceac
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d621(%rip), %r8      # 0x14cec5
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d616(%rip), %r8      # 0x14cede
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d60c(%rip), %r8      # 0x14cef8
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rsi
movq -0x20(%rbp), %rax
movl (%rax), %edx
leaq -0xb8(%rbp), %rdi
movq %rdi, -0xf0(%rbp)
callq 0x71b50
movq -0xf0(%rbp), %rdx
leaq 0x4d5ee(%rip), %rsi     # 0x14cf12
leaq 0x4d261(%rip), %rcx     # 0x14cb8c
leaq -0x98(%rbp), %rdi
callq 0x116e40
jmp 0xff939
leaq -0xb8(%rbp), %rdi
callq 0x7708
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %eax
movl %eax, -0xfc(%rbp)
movl -0x10(%rbp), %eax
movl %eax, -0xf8(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0x78810
movb %al, -0xf1(%rbp)
jmp 0xff971
movl -0xf8(%rbp), %edx
movl -0xfc(%rbp), %esi
movq -0xd0(%rbp), %rdi
movb -0xf1(%rbp), %al
movzbl %al, %r8d
andl $0x1, %r8d
leaq -0x98(%rbp), %rcx
xorl %r9d, %r9d
callq 0x784f0
jmp 0xff9a3
movq -0xd0(%rbp), %rdi
movl -0x10(%rbp), %esi
movq -0x20(%rbp), %rax
movl (%rax), %edx
callq 0x25500
jmp 0xff9ba
leaq -0x98(%rbp), %rdi
callq 0x7708
jmp 0xffdc4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x7708
jmp 0xffdcd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x7708
jmp 0xffdcd
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d50a(%rip), %r8      # 0x14cf29
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d50b(%rip), %r8      # 0x14cf4e
callq 0x79220
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, -0x100(%rbp)
subl $0x2, %eax
je 0xffa94
jmp 0xffa7a
movl -0x100(%rbp), %eax
subl $0x3, %eax
je 0xffab5
jmp 0xffa87
movl -0x100(%rbp), %eax
subl $0x4, %eax
je 0xffad6
jmp 0xffaf7
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d4c7(%rip), %r8      # 0x14cf75
callq 0x79220
jmp 0xffaf9
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d4b4(%rip), %r8      # 0x14cf83
callq 0x79220
jmp 0xffaf9
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
leaq 0x4d4a1(%rip), %r8      # 0x14cf91
callq 0x79220
jmp 0xffaf9
jmp 0xffaf9
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
cmpl $0xa, 0xc(%rax)
je 0xffb3c
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d493(%rip), %r9      # 0x14cfc8
callq 0x79330
jmp 0xffb63
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d441(%rip), %r9      # 0x14cf9f
callq 0x79330
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
cmpl $0xa, 0xc(%rax)
je 0xffba6
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d436(%rip), %r9      # 0x14cfd5
callq 0x79330
jmp 0xffbcd
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d3e1(%rip), %r9      # 0x14cfa9
callq 0x79330
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
cmpl $0xa, 0xc(%rax)
je 0xffc1c
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
movq -0x20(%rbp), %rax
movl 0x8(%rax), %r9d
leaq 0x4d3d1(%rip), %rax     # 0x14cfe2
movq %rax, (%rsp)
callq 0x798c0
jmp 0xffc4f
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
movq -0x20(%rbp), %rax
movl 0x8(%rax), %r9d
leaq 0x4d36d(%rip), %rax     # 0x14cfb3
movq %rax, (%rsp)
callq 0x798c0
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
cmpl $0xa, 0xc(%rax)
je 0xffc92
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d33d(%rip), %r9      # 0x14cfc8
callq 0x79330
jmp 0xffcb9
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d30b(%rip), %r9      # 0x14cfbf
callq 0x79330
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
cmpl $0xa, 0xc(%rax)
je 0xffcfc
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d2e0(%rip), %r9      # 0x14cfd5
callq 0x79330
jmp 0xffd23
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
leaq 0x4d2ae(%rip), %r9      # 0x14cfcc
callq 0x79330
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
callq 0xea90
cmpl $0xa, 0xc(%rax)
je 0xffd72
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
movq -0x20(%rbp), %rax
movl 0x8(%rax), %r9d
leaq 0x4d27b(%rip), %rax     # 0x14cfe2
movq %rax, (%rsp)
callq 0x798c0
jmp 0xffda5
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movq -0x20(%rbp), %rax
movl (%rax), %ecx
movq -0x20(%rbp), %rax
movl 0x4(%rax), %r8d
movq -0x20(%rbp), %rax
movl 0x8(%rax), %r9d
leaq 0x4d23d(%rip), %rax     # 0x14cfd9
movq %rax, (%rsp)
callq 0x798c0
jmp 0xffdc4
movq -0xd0(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x10(%rbp), %edx
movl -0x14(%rbp), %ecx
movq -0x20(%rbp), %r8
movl -0x24(%rbp), %r9d
callq 0x7e110
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0x7640
nopw %cs:(%rax,%rax)