// File: AndreRenaud[P]simple_uart/simple_uart.c
// Function: simple_uart_set_config
static int simple_uart_set_config(struct simple_uart *sc, int speed, const char *mode_string) // Linux Port config
{
    struct termios options; // Linux options handle
    speed_t sp = B0;        // Default linux speed
#ifdef __linux__
    int non_standard = 0;
#else // __APPLE__ type casting
    speed_t mac_speed = speed;
#endif

    /* Select Baudrate */
    switch (speed) {
    case 1200: sp = B1200; break;
    case 2400: sp = B2400; break;
    case 4800: sp = B4800; break;
    case 9600: sp = B9600; break;
    case 19200: sp = B19200; break;
    case 38400: sp = B38400; break;
    case 57600: sp = B57600; break;
    case 115200: sp = B115200; break;
    case 230400: sp = B230400; break;
#ifdef __linux__
    case 460800: sp = B460800; break;
    case 500000: sp = B500000; break;
    case 576000: sp = B576000; break;
    case 921600: sp = B921600; break;
    case 1000000: sp = B1000000; break;
    case 1152000: sp = B1152000; break;
    case 1500000: sp = B1500000; break;
    case 2000000: sp = B2000000; break;
    case 2500000: sp = B2500000; break;
    case 3000000: sp = B3000000; break;
    case 3500000: sp = B3500000; break;
    case 4000000: sp = B4000000; break;
    default: sp = B38400; non_standard = 1;
#else // __APPLE__ only
    // The IOSSIOSPEED ioctl can be used to set arbitrary baud rates
    // other than those specified by POSIX. The driver for the underlying serial hardware
    // ultimately determines which baud rates can be used. This ioctl sets both the input
    // and output speed.
    default: {
        int r = ioctl(sc->fd, IOSSIOSPEED, &mac_speed);
        if (r < 0 && errno != ENOTTY)
            return -errno;
    }
#endif
    }
    /* Accquire current port config */
    if (tcgetattr(sc->fd, &options) < 0)
        return -errno;

    if (sp != 0) {
        cfsetospeed(&options, sp);
        cfsetispeed(&options, sp);
    }

    options.c_cflag &= (tcflag_t) ~(HUPCL);

    options.c_cflag |= CREAD | CLOCAL;

    // parity
    if (HAS_OPTION('N'))
        options.c_cflag &= (tcflag_t)~PARENB;
    else if (HAS_OPTION('E')) {
        options.c_cflag |= PARENB;
        options.c_cflag &= (tcflag_t)~PARODD;
    } else if (HAS_OPTION('O')) {
        options.c_cflag |= PARENB;
        options.c_cflag |= PARODD;
    }
    // stop bits
    if (HAS_OPTION('2'))
        options.c_cflag |= CSTOPB;
    else
        options.c_cflag &= (tcflag_t)~CSTOPB;
    /* Flush data on each write */
    if (HAS_OPTION('W'))
        options.c_lflag |= NOFLSH;

    // Character size
    options.c_cflag &= (tcflag_t)~CSIZE;
    if (HAS_OPTION('8'))
        options.c_cflag |= CS8;
    else if (HAS_OPTION('7'))
        options.c_cflag |= CS7;
    else if (HAS_OPTION('6'))
        options.c_cflag |= CS6;
    else if (HAS_OPTION('5'))
        options.c_cflag |= CS5;

    /* Flow control */
    if (HAS_OPTION('F'))
        options.c_cflag |= CRTSCTS;
    else
        options.c_cflag &= ~CRTSCTS;

    // raw input mode
    options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ISIG);

    // disable software flow control
    options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY);

    // maintain carriage return on input, and don't translate it
    options.c_iflag &= (tcflag_t) ~(IGNCR | ICRNL | INLCR);

    // raw output mode
    options.c_oflag &= (tcflag_t)~OPOST;

    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 0;
    tcflush(sc->fd, TCIOFLUSH);
    if (tcsetattr(sc->fd, TCSANOW, &options) < 0)
        return -errno;

#ifdef __linux__
    if (HAS_OPTION('R')) {
        struct serial_rs485 rs485;
        rs485.flags = SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | SER_RS485_RTS_ON_SEND;
        if (ioctl(sc->fd, TIOCSRS485, &rs485) < 0)
            return -errno;
    }

    if (non_standard) {
        struct serial_struct ss;

        /* Get current settings */
        if (ioctl(sc->fd, TIOCGSERIAL, &ss) < 0)
            return -errno;
        /* Check we can divide down */
        if ((ss.baud_base / speed) == 0)
            return -EINVAL;
        ss.flags &= (int)~(ASYNC_SPD_MASK);
        ss.flags |= (int)ASYNC_SPD_CUST;
        ss.custom_divisor = ss.baud_base / speed;
        if (ioctl(sc->fd, TIOCSSERIAL, &ss) < 0)
            return -errno;
    }
#endif
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movl $0x0, -0x60(%rbp)
movl $0x0, -0x64(%rbp)
movl -0x14(%rbp), %eax
movl %eax, -0xd4(%rbp)
subl $0x4b0, %eax            # imm = 0x4B0
je 0x6d29
jmp 0x6baa
movl -0xd4(%rbp), %eax
subl $0x960, %eax            # imm = 0x960
je 0x6d35
jmp 0x6bbd
movl -0xd4(%rbp), %eax
subl $0x12c0, %eax           # imm = 0x12C0
je 0x6d41
jmp 0x6bd0
movl -0xd4(%rbp), %eax
subl $0x2580, %eax           # imm = 0x2580
je 0x6d4d
jmp 0x6be3
movl -0xd4(%rbp), %eax
subl $0x4b00, %eax           # imm = 0x4B00
je 0x6d59
jmp 0x6bf6
movl -0xd4(%rbp), %eax
subl $0x9600, %eax           # imm = 0x9600
je 0x6d65
jmp 0x6c09
movl -0xd4(%rbp), %eax
subl $0xe100, %eax           # imm = 0xE100
je 0x6d71
jmp 0x6c1c
movl -0xd4(%rbp), %eax
subl $0x1c200, %eax          # imm = 0x1C200
je 0x6d7d
jmp 0x6c2f
movl -0xd4(%rbp), %eax
subl $0x38400, %eax          # imm = 0x38400
je 0x6d89
jmp 0x6c42
movl -0xd4(%rbp), %eax
subl $0x70800, %eax          # imm = 0x70800
je 0x6d92
jmp 0x6c55
movl -0xd4(%rbp), %eax
subl $0x7a120, %eax          # imm = 0x7A120
je 0x6d9b
jmp 0x6c68
movl -0xd4(%rbp), %eax
subl $0x8ca00, %eax          # imm = 0x8CA00
je 0x6da4
jmp 0x6c7b
movl -0xd4(%rbp), %eax
subl $0xe1000, %eax          # imm = 0xE1000
je 0x6dad
jmp 0x6c8e
movl -0xd4(%rbp), %eax
subl $0xf4240, %eax          # imm = 0xF4240
je 0x6db6
jmp 0x6ca1
movl -0xd4(%rbp), %eax
subl $0x119400, %eax         # imm = 0x119400
je 0x6dbf
jmp 0x6cb4
movl -0xd4(%rbp), %eax
subl $0x16e360, %eax         # imm = 0x16E360
je 0x6dc8
jmp 0x6cc7
movl -0xd4(%rbp), %eax
subl $0x1e8480, %eax         # imm = 0x1E8480
je 0x6dd1
jmp 0x6cda
movl -0xd4(%rbp), %eax
subl $0x2625a0, %eax         # imm = 0x2625A0
je 0x6dda
jmp 0x6ced
movl -0xd4(%rbp), %eax
subl $0x2dc6c0, %eax         # imm = 0x2DC6C0
je 0x6de3
jmp 0x6d00
movl -0xd4(%rbp), %eax
subl $0x3567e0, %eax         # imm = 0x3567E0
je 0x6dec
jmp 0x6d13
movl -0xd4(%rbp), %eax
subl $0x3d0900, %eax         # imm = 0x3D0900
je 0x6df5
jmp 0x6dfe
movl $0x9, -0x60(%rbp)
jmp 0x6e0c
movl $0xb, -0x60(%rbp)
jmp 0x6e0c
movl $0xc, -0x60(%rbp)
jmp 0x6e0c
movl $0xd, -0x60(%rbp)
jmp 0x6e0c
movl $0xe, -0x60(%rbp)
jmp 0x6e0c
movl $0xf, -0x60(%rbp)
jmp 0x6e0c
movl $0x1001, -0x60(%rbp)    # imm = 0x1001
jmp 0x6e0c
movl $0x1002, -0x60(%rbp)    # imm = 0x1002
jmp 0x6e0c
movl $0x1003, -0x60(%rbp)    # imm = 0x1003
jmp 0x6e0c
movl $0x1004, -0x60(%rbp)    # imm = 0x1004
jmp 0x6e0c
movl $0x1005, -0x60(%rbp)    # imm = 0x1005
jmp 0x6e0c
movl $0x1006, -0x60(%rbp)    # imm = 0x1006
jmp 0x6e0c
movl $0x1007, -0x60(%rbp)    # imm = 0x1007
jmp 0x6e0c
movl $0x1008, -0x60(%rbp)    # imm = 0x1008
jmp 0x6e0c
movl $0x1009, -0x60(%rbp)    # imm = 0x1009
jmp 0x6e0c
movl $0x100a, -0x60(%rbp)    # imm = 0x100A
jmp 0x6e0c
movl $0x100b, -0x60(%rbp)    # imm = 0x100B
jmp 0x6e0c
movl $0x100c, -0x60(%rbp)    # imm = 0x100C
jmp 0x6e0c
movl $0x100d, -0x60(%rbp)    # imm = 0x100D
jmp 0x6e0c
movl $0x100e, -0x60(%rbp)    # imm = 0x100E
jmp 0x6e0c
movl $0x100f, -0x60(%rbp)    # imm = 0x100F
jmp 0x6e0c
movl $0xf, -0x60(%rbp)
movl $0x1, -0x64(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %edi
leaq -0x5c(%rbp), %rsi
callq 0x22e0
cmpl $0x0, %eax
jge 0x6e34
callq 0x2050
movq %rax, %rcx
xorl %eax, %eax
subl (%rcx), %eax
movl %eax, -0x4(%rbp)
jmp 0x7323
cmpl $0x0, -0x60(%rbp)
je 0x6e52
movl -0x60(%rbp), %esi
leaq -0x5c(%rbp), %rdi
callq 0x2120
movl -0x60(%rbp), %esi
leaq -0x5c(%rbp), %rdi
callq 0x2320
movl -0x54(%rbp), %eax
andl $0xfffffbff, %eax       # imm = 0xFFFFFBFF
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %eax
orl $0x880, %eax            # imm = 0x880
movl %eax, -0x54(%rbp)
movq -0x20(%rbp), %rdi
movl $0x4e, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x6ea5
movq -0x20(%rbp), %rax
movq %rax, -0xe0(%rbp)
movl $0x4e, %edi
callq 0x2280
movq -0xe0(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x6eb5
movl -0x54(%rbp), %eax
andl $0xfffffeff, %eax       # imm = 0xFFFFFEFF
movl %eax, -0x54(%rbp)
jmp 0x6f61
movq -0x20(%rbp), %rdi
movl $0x45, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x6ef2
movq -0x20(%rbp), %rax
movq %rax, -0xe8(%rbp)
movl $0x45, %edi
callq 0x2280
movq -0xe8(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x6f0a
movl -0x54(%rbp), %eax
orl $0x100, %eax            # imm = 0x100
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %eax
andl $0xfffffdff, %eax       # imm = 0xFFFFFDFF
movl %eax, -0x54(%rbp)
jmp 0x6f5f
movq -0x20(%rbp), %rdi
movl $0x4f, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x6f47
movq -0x20(%rbp), %rax
movq %rax, -0xf0(%rbp)
movl $0x4f, %edi
callq 0x2280
movq -0xf0(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x6f5d
movl -0x54(%rbp), %eax
orl $0x100, %eax            # imm = 0x100
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %eax
orl $0x200, %eax            # imm = 0x200
movl %eax, -0x54(%rbp)
jmp 0x6f5f
jmp 0x6f61
movq -0x20(%rbp), %rdi
movl $0x32, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x6f9e
movq -0x20(%rbp), %rax
movq %rax, -0xf8(%rbp)
movl $0x32, %edi
callq 0x2280
movq -0xf8(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x6fa9
movl -0x54(%rbp), %eax
orl $0x40, %eax
movl %eax, -0x54(%rbp)
jmp 0x6fb2
movl -0x54(%rbp), %eax
andl $-0x41, %eax
movl %eax, -0x54(%rbp)
movq -0x20(%rbp), %rdi
movl $0x57, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x6fef
movq -0x20(%rbp), %rax
movq %rax, -0x100(%rbp)
movl $0x57, %edi
callq 0x2280
movq -0x100(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x6ffa
movl -0x50(%rbp), %eax
orl $0x80, %eax
movl %eax, -0x50(%rbp)
movl -0x54(%rbp), %eax
andl $-0x31, %eax
movl %eax, -0x54(%rbp)
movq -0x20(%rbp), %rdi
movl $0x38, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x7040
movq -0x20(%rbp), %rax
movq %rax, -0x108(%rbp)
movl $0x38, %edi
callq 0x2280
movq -0x108(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x704e
movl -0x54(%rbp), %eax
orl $0x30, %eax
movl %eax, -0x54(%rbp)
jmp 0x712d
movq -0x20(%rbp), %rdi
movl $0x37, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x708b
movq -0x20(%rbp), %rax
movq %rax, -0x110(%rbp)
movl $0x37, %edi
callq 0x2280
movq -0x110(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x7099
movl -0x54(%rbp), %eax
orl $0x20, %eax
movl %eax, -0x54(%rbp)
jmp 0x712b
movq -0x20(%rbp), %rdi
movl $0x36, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x70d6
movq -0x20(%rbp), %rax
movq %rax, -0x118(%rbp)
movl $0x36, %edi
callq 0x2280
movq -0x118(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x70e1
movl -0x54(%rbp), %eax
orl $0x10, %eax
movl %eax, -0x54(%rbp)
jmp 0x7129
movq -0x20(%rbp), %rdi
movl $0x35, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x711e
movq -0x20(%rbp), %rax
movq %rax, -0x120(%rbp)
movl $0x35, %edi
callq 0x2280
movq -0x120(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x7127
movl -0x54(%rbp), %eax
orl $0x0, %eax
movl %eax, -0x54(%rbp)
jmp 0x7129
jmp 0x712b
jmp 0x712d
movq -0x20(%rbp), %rdi
movl $0x46, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x716a
movq -0x20(%rbp), %rax
movq %rax, -0x128(%rbp)
movl $0x46, %edi
callq 0x2280
movq -0x128(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x7177
movl -0x54(%rbp), %eax
orl $0x80000000, %eax       # imm = 0x80000000
movl %eax, -0x54(%rbp)
jmp 0x7182
movl -0x54(%rbp), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, -0x54(%rbp)
movl -0x50(%rbp), %eax
andl $-0x1c, %eax
movl %eax, -0x50(%rbp)
movl -0x5c(%rbp), %eax
andl $0xffffe3ff, %eax       # imm = 0xFFFFE3FF
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
andl $0xfffffe3f, %eax       # imm = 0xFFFFFE3F
movl %eax, -0x5c(%rbp)
movl -0x58(%rbp), %eax
andl $-0x2, %eax
movl %eax, -0x58(%rbp)
movb $0x0, -0x46(%rbp)
movb $0x0, -0x45(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %edi
movl $0x2, %esi
callq 0x2140
movq -0x10(%rbp), %rax
movl (%rax), %edi
xorl %esi, %esi
leaq -0x5c(%rbp), %rdx
callq 0x22f0
cmpl $0x0, %eax
jge 0x71ec
callq 0x2050
movq %rax, %rcx
xorl %eax, %eax
subl (%rcx), %eax
movl %eax, -0x4(%rbp)
jmp 0x7323
movq -0x20(%rbp), %rdi
movl $0x52, %esi
callq 0x2150
cmpq $0x0, %rax
jne 0x7229
movq -0x20(%rbp), %rax
movq %rax, -0x130(%rbp)
movl $0x52, %edi
callq 0x2280
movq -0x130(%rbp), %rdi
movl %eax, %esi
callq 0x2150
cmpq $0x0, %rax
je 0x7267
movl $0x13, -0x84(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %edi
movl $0x542f, %esi           # imm = 0x542F
leaq -0x84(%rbp), %rdx
movb $0x0, %al
callq 0x21a0
cmpl $0x0, %eax
jge 0x7265
callq 0x2050
movq %rax, %rcx
xorl %eax, %eax
subl (%rcx), %eax
movl %eax, -0x4(%rbp)
jmp 0x7323
jmp 0x7267
cmpl $0x0, -0x64(%rbp)
je 0x731c
movq -0x10(%rbp), %rax
movl (%rax), %edi
movl $0x541e, %esi           # imm = 0x541E
leaq -0xd0(%rbp), %rdx
movb $0x0, %al
callq 0x21a0
cmpl $0x0, %eax
jge 0x72a3
callq 0x2050
movq %rax, %rcx
xorl %eax, %eax
subl (%rcx), %eax
movl %eax, -0x4(%rbp)
jmp 0x7323
movl -0xb4(%rbp), %eax
cltd
idivl -0x14(%rbp)
cmpl $0x0, %eax
jne 0x72bb
movl $0xffffffea, -0x4(%rbp) # imm = 0xFFFFFFEA
jmp 0x7323
movl -0xc0(%rbp), %eax
andl $0xffffefcf, %eax       # imm = 0xFFFFEFCF
movl %eax, -0xc0(%rbp)
movl -0xc0(%rbp), %eax
orl $0x30, %eax
movl %eax, -0xc0(%rbp)
movl -0xb4(%rbp), %eax
cltd
idivl -0x14(%rbp)
movl %eax, -0xb8(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %edi
movl $0x541f, %esi           # imm = 0x541F
leaq -0xd0(%rbp), %rdx
movb $0x0, %al
callq 0x21a0
cmpl $0x0, %eax
jge 0x731a
callq 0x2050
movq %rax, %rcx
xorl %eax, %eax
subl (%rcx), %eax
movl %eax, -0x4(%rbp)
jmp 0x7323
jmp 0x731c
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nop