// File: eggnot[P]pixel_camera/matrix/lib/framebuffer.cc
// Function: rgb_matrix::internal::Framebuffer::SetPixel(int, int, unsigned char, unsigned char, unsigned char)
void Framebuffer::SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
  if (x < 0 || x >= columns_ || y < 0 || y >= height_) return;

  const uint16_t red   = MapColor(r);
  const uint16_t green = MapColor(PANEL_SWAP_G_B_ ? b : g);
  const uint16_t blue  = MapColor(PANEL_SWAP_G_B_ ? g : b);

  const int min_bit_plane = kBitPlanes - pwm_bits_;
  IoBits *bits = ValueAt(y & row_mask_, x, min_bit_plane);

  // Manually expand the three cases for better performance.
  // TODO(hzeller): This is a bit repetetive. Test if it pays off to just
  // pre-calc rgb mask and apply.
  if (y < rows_) {
    // Parallel chain #1
    if (y < double_rows_) {   // Upper sub-panel.
      for (int b = min_bit_plane; b < kBitPlanes; ++b) {
        const uint16_t mask = 1 << b;
        bits->bits.p0_r1 = (red & mask) == mask;
        bits->bits.p0_g1 = (green & mask) == mask;
        bits->bits.p0_b1 = (blue & mask) == mask;
        bits += columns_;
      }
    } else {
      for (int b = min_bit_plane; b < kBitPlanes; ++b) {
        const uint16_t mask = 1 << b;
        bits->bits.p0_r2 = (red & mask) == mask;
        bits->bits.p0_g2 = (green & mask) == mask;
        bits->bits.p0_b2 = (blue & mask) == mask;
        bits += columns_;
      }
    }
#ifndef ONLY_SINGLE_CHAIN
  } else if (y >= rows_ && y < 2 * rows_) {
    // Parallel chain #2
    if (y - rows_ < double_rows_) {   // Upper sub-panel.
      for (int b = min_bit_plane; b < kBitPlanes; ++b) {
        const uint16_t mask = 1 << b;
        bits->bits.p1_r1 = (red & mask) == mask;
        bits->bits.p1_g1 = (green & mask) == mask;
        bits->bits.p1_b1 = (blue & mask) == mask;
        bits += columns_;
      }
    } else {
      for (int b = min_bit_plane; b < kBitPlanes; ++b) {
        const uint16_t mask = 1 << b;
        bits->bits.p1_r2 = (red & mask) == mask;
        bits->bits.p1_g2 = (green & mask) == mask;
        bits->bits.p1_b2 = (blue & mask) == mask;
        bits += columns_;
      }
    }
  } else {
    // Parallel chain #3
    if (y - 2*rows_ < double_rows_) {   // Upper sub-panel.
      for (int b = min_bit_plane; b < kBitPlanes; ++b) {
        const uint16_t mask = 1 << b;
        bits->bits.p2_r1 = (red & mask) == mask;
        bits->bits.p2_g1 = (green & mask) == mask;
        bits->bits.p2_b1 = (blue & mask) == mask;
        bits += columns_;
      }
    } else {
      for (int b = min_bit_plane; b < kBitPlanes; ++b) {
        const uint16_t mask = 1 << b;
        bits->bits.p2_r2 = (red & mask) == mask;
        bits->bits.p2_g2 = (green & mask) == mask;
        bits->bits.p2_b2 = (blue & mask) == mask;
        bits += columns_;
      }
    }
#endif
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movl %r8d, -0x70(%rbp)
movl %ecx, %eax
movl -0x70(%rbp), %ecx
movl %eax, -0x6c(%rbp)
movl %edx, %eax
movl -0x6c(%rbp), %edx
movl %eax, -0x68(%rbp)
movl %esi, %eax
movl -0x68(%rbp), %esi
movl %eax, -0x64(%rbp)
movq %rdi, %r8
movl -0x64(%rbp), %edi
movb %r9b, %al
movq %r8, -0x8(%rbp)
movl %edi, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movb %dl, -0x11(%rbp)
movb %cl, -0x12(%rbp)
movb %al, -0x13(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpl $0x0, -0xc(%rbp)
jl 0x765c
movq -0x60(%rbp), %rcx
movl -0xc(%rbp), %eax
cmpl 0xc(%rcx), %eax
jge 0x765c
cmpl $0x0, -0x10(%rbp)
jl 0x765c
movq -0x60(%rbp), %rcx
movl -0x10(%rbp), %eax
cmpl 0x8(%rcx), %eax
jl 0x7661
jmp 0x7c36
movq -0x60(%rbp), %rdi
movzbl -0x11(%rbp), %esi
callq 0x8110
movq -0x60(%rbp), %rdi
movw %ax, -0x16(%rbp)
movzbl -0x12(%rbp), %esi
callq 0x8110
movq -0x60(%rbp), %rdi
movw %ax, -0x18(%rbp)
movzbl -0x13(%rbp), %esi
callq 0x8110
movq -0x60(%rbp), %rdi
movw %ax, -0x1a(%rbp)
movzbl 0x10(%rdi), %ecx
movl $0xb, %eax
subl %ecx, %eax
movl %eax, -0x20(%rbp)
movl -0x10(%rbp), %esi
movzbl 0x18(%rdi), %eax
andl %eax, %esi
movl -0xc(%rbp), %edx
movl -0x20(%rbp), %ecx
callq 0x81f0
movq -0x60(%rbp), %rcx
movq %rax, -0x28(%rbp)
movl -0x10(%rbp), %eax
cmpl (%rcx), %eax
jge 0x7891
movq -0x60(%rbp), %rcx
movl -0x10(%rbp), %eax
cmpl 0x14(%rcx), %eax
jge 0x77b6
movl -0x20(%rbp), %eax
movl %eax, -0x2c(%rbp)
cmpl $0xb, -0x2c(%rbp)
jge 0x77b1
movq -0x60(%rbp), %rax
movl -0x2c(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movw %cx, -0x2e(%rbp)
movzwl -0x16(%rbp), %ecx
movzwl -0x2e(%rbp), %edx
andl %edx, %ecx
movzwl -0x2e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0xb, %esi
andl $0xfffff7ff, %edx       # imm = 0xFFFFF7FF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x18(%rbp), %ecx
movzwl -0x2e(%rbp), %edx
andl %edx, %ecx
movzwl -0x2e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x1b, %esi
andl $0xf7ffffff, %edx       # imm = 0xF7FFFFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x1a(%rbp), %ecx
movzwl -0x2e(%rbp), %edx
andl %edx, %ecx
movzwl -0x2e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x7, %esi
andl $0xffffff7f, %edx       # imm = 0xFFFFFF7F
orl %esi, %edx
movl %edx, (%rcx)
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x76e3
jmp 0x788c
movl -0x20(%rbp), %eax
movl %eax, -0x34(%rbp)
cmpl $0xb, -0x34(%rbp)
jge 0x788a
movq -0x60(%rbp), %rax
movl -0x34(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movw %cx, -0x36(%rbp)
movzwl -0x16(%rbp), %ecx
movzwl -0x36(%rbp), %edx
andl %edx, %ecx
movzwl -0x36(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x8, %esi
andl $0xfffffeff, %edx       # imm = 0xFFFFFEFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x18(%rbp), %ecx
movzwl -0x36(%rbp), %edx
andl %edx, %ecx
movzwl -0x36(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x9, %esi
andl $0xfffffdff, %edx       # imm = 0xFFFFFDFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x1a(%rbp), %ecx
movzwl -0x36(%rbp), %edx
andl %edx, %ecx
movzwl -0x36(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0xa, %esi
andl $0xfffffbff, %edx       # imm = 0xFFFFFBFF
orl %esi, %edx
movl %edx, (%rcx)
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x77bc
jmp 0x788c
jmp 0x7c36
movq -0x60(%rbp), %rcx
movl -0x10(%rbp), %eax
cmpl (%rcx), %eax
jl 0x7a73
movq -0x60(%rbp), %rcx
movl -0x10(%rbp), %eax
movl (%rcx), %ecx
shll %ecx
cmpl %ecx, %eax
jge 0x7a73
movq -0x60(%rbp), %rcx
movl -0x10(%rbp), %eax
subl (%rcx), %eax
cmpl 0x14(%rcx), %eax
jge 0x7998
movl -0x20(%rbp), %eax
movl %eax, -0x3c(%rbp)
cmpl $0xb, -0x3c(%rbp)
jge 0x7993
movq -0x60(%rbp), %rax
movl -0x3c(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movw %cx, -0x3e(%rbp)
movzwl -0x16(%rbp), %ecx
movzwl -0x3e(%rbp), %edx
andl %edx, %ecx
movzwl -0x3e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0xc, %esi
andl $0xffffefff, %edx       # imm = 0xFFFFEFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x18(%rbp), %ecx
movzwl -0x3e(%rbp), %edx
andl %edx, %ecx
movzwl -0x3e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x5, %esi
andl $-0x21, %edx
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x1a(%rbp), %ecx
movzwl -0x3e(%rbp), %edx
andl %edx, %ecx
movzwl -0x3e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x6, %esi
andl $-0x41, %edx
orl %esi, %edx
movl %edx, (%rcx)
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x78cb
jmp 0x7a6e
movl -0x20(%rbp), %eax
movl %eax, -0x44(%rbp)
cmpl $0xb, -0x44(%rbp)
jge 0x7a6c
movq -0x60(%rbp), %rax
movl -0x44(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movw %cx, -0x46(%rbp)
movzwl -0x16(%rbp), %ecx
movzwl -0x46(%rbp), %edx
andl %edx, %ecx
movzwl -0x46(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x13, %esi
andl $0xfff7ffff, %edx       # imm = 0xFFF7FFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x18(%rbp), %ecx
movzwl -0x46(%rbp), %edx
andl %edx, %ecx
movzwl -0x46(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0xd, %esi
andl $0xffffdfff, %edx       # imm = 0xFFFFDFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x1a(%rbp), %ecx
movzwl -0x46(%rbp), %edx
andl %edx, %ecx
movzwl -0x46(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x14, %esi
andl $0xffefffff, %edx       # imm = 0xFFEFFFFF
orl %esi, %edx
movl %edx, (%rcx)
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x799e
jmp 0x7a6e
jmp 0x7c34
movq -0x60(%rbp), %rcx
movl -0x10(%rbp), %eax
movl (%rcx), %edx
shll %edx
subl %edx, %eax
cmpl 0x14(%rcx), %eax
jge 0x7b5c
movl -0x20(%rbp), %eax
movl %eax, -0x4c(%rbp)
cmpl $0xb, -0x4c(%rbp)
jge 0x7b57
movq -0x60(%rbp), %rax
movl -0x4c(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movw %cx, -0x4e(%rbp)
movzwl -0x16(%rbp), %ecx
movzwl -0x4e(%rbp), %edx
andl %edx, %ecx
movzwl -0x4e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0xe, %esi
andl $0xffffbfff, %edx       # imm = 0xFFFFBFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x18(%rbp), %ecx
movzwl -0x4e(%rbp), %edx
andl %edx, %ecx
movzwl -0x4e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x2, %esi
andl $-0x5, %edx
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x1a(%rbp), %ecx
movzwl -0x4e(%rbp), %edx
andl %edx, %ecx
movzwl -0x4e(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x3, %esi
andl $-0x9, %edx
orl %esi, %edx
movl %edx, (%rcx)
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x4c(%rbp)
jmp 0x7a8f
jmp 0x7c32
movl -0x20(%rbp), %eax
movl %eax, -0x54(%rbp)
cmpl $0xb, -0x54(%rbp)
jge 0x7c30
movq -0x60(%rbp), %rax
movl -0x54(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movw %cx, -0x56(%rbp)
movzwl -0x16(%rbp), %ecx
movzwl -0x56(%rbp), %edx
andl %edx, %ecx
movzwl -0x56(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x1a, %esi
andl $0xfbffffff, %edx       # imm = 0xFBFFFFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x18(%rbp), %ecx
movzwl -0x56(%rbp), %edx
andl %edx, %ecx
movzwl -0x56(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x10, %esi
andl $0xfffeffff, %edx       # imm = 0xFFFEFFFF
orl %esi, %edx
movl %edx, (%rcx)
movzwl -0x1a(%rbp), %ecx
movzwl -0x56(%rbp), %edx
andl %edx, %ecx
movzwl -0x56(%rbp), %edx
cmpl %edx, %ecx
sete %cl
andb $0x1, %cl
movzbl %cl, %esi
movq -0x28(%rbp), %rcx
movl (%rcx), %edx
andl $0x1, %esi
shll $0x15, %esi
andl $0xffdfffff, %edx       # imm = 0xFFDFFFFF
orl %esi, %edx
movl %edx, (%rcx)
movl 0xc(%rax), %ecx
movq -0x28(%rbp), %rax
movslq %ecx, %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x7b62
jmp 0x7c32
jmp 0x7c34
jmp 0x7c36
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)