// File: /workspace/github_c_makefile_star2_O3/j-hoppe[P]tu58fs/serial.c
// Function: serial_devinit
void serial_devinit(serial_device_t *serial, char *port, int32_t speed, int32_t databits,
		char parity, int32_t stopbits) {
	serial->rx_lasttime_ms = 0;
	serial->tx_lasttime_ms = 0;

	// init unix serial port mode
	struct termios line;
	char name[64];
	unsigned int n;

	serial->baudrate = speed;
	serial->bitcount = 1 + databits + stopbits; // total bit count

	// open serial port
	int32_t euid = geteuid();
	int32_t uid = getuid();
	setreuid(euid, -1);
	if (sscanf(port, "%u", &n) == 1)
		sprintf(name, "/dev/ttyS%u", n - 1);
	else
		strcpy(name, port);
	if ((serial->fd = open(name, O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
		fatal("no serial line [%s]", name);
	setreuid(uid, euid);

	// get current line params, error if not a serial port
	if (tcgetattr(serial->fd, &serial->lineSave))
		fatal("not a serial device [%s]", name);

	// copy current parameters
	line = serial->lineSave;

	// input param
	line.c_iflag &= ~( IGNBRK | BRKINT | IMAXBEL | INPCK | ISTRIP |
	INLCR | IGNCR | ICRNL | IXON | IXOFF |
	IUCLC | IXANY | PARMRK | IGNPAR);
	line.c_iflag |= (0);

	// output param
	line.c_oflag &= ~( OPOST | OLCUC | OCRNL | ONLCR | ONOCR |
	ONLRET | OFILL | CRDLY | NLDLY | BSDLY |
	TABDLY | VTDLY | FFDLY | OFDEL);
	line.c_oflag |= (0);

	// control param
	line.c_cflag &= ~( CBAUD | CSIZE | CSTOPB | PARENB | PARODD |
	HUPCL | CRTSCTS | CLOCAL | CREAD);
	line.c_cflag |= ( CLOCAL | CREAD);

	// explicitly set size
	switch (databits) {
	case 5: // who needs this?
		line.c_cflag |= CS5;
		break;
	case 6: // who needs this?
		line.c_cflag |= CS6;
		break;
	case 7:
		line.c_cflag |= CS7;
		break;
	default:
		line.c_cflag |= CS8;
		break;
	}

	// explicitly set parity
	switch (toupper(parity)) {
	case 'E':
		line.c_cflag |= PARENB;
		line.c_cflag &= ~PARODD;
		serial->bitcount++; // one extra bit
		break;
	case 'O':
		line.c_cflag |= PARENB;
		line.c_cflag |= PARODD;
		serial->bitcount++; // one extra bit
		break;
	default: // no parity
		line.c_cflag &= ~PARENB;
		line.c_cflag &= ~PARODD;
	}

	// set two stop bits if requested, else default to one
	if (stopbits == 2)
		line.c_cflag |= CSTOPB;

	// local param
	line.c_lflag &= ~( ISIG | ICANON | ECHO | ECHOE | ECHOK |
	ECHONL | NOFLSH | TOSTOP | IEXTEN | FLUSHO |
	ECHOKE | ECHOCTL);
	line.c_lflag |= (0);

	// timing/read param
	line.c_cc[VMIN] = 1; // return a min of 1 chars
	line.c_cc[VTIME] = 0; // no timer

	// flush all existing input data
	tcflush(serial->fd, TCIFLUSH);

	// set baud rate, if it is legal
	if (devbaud(speed) == -1) {
		error("illegal serial speed %d., ignoring", speed);
	} else {
		cfsetispeed(&line, devbaud(speed));
		cfsetospeed(&line, devbaud(speed));
	}

	// set new device parameters
	tcsetattr(serial->fd, TCSANOW, &line);

	// and non-blocking also
	if (fcntl(serial->fd, F_SETFL, FNDELAY) == -1)
		error("failed to set non-blocking read");

	// zap current data, if any
	serial_devtxinit(serial);
	serial_devrxinit(serial);

	return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl %r8d, 0x8(%rsp)
movl %ecx, %r12d
movl %edx, %ebp
movq %rsi, %r14
movq %rdi, %rbx
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rdi)
movl %edx, 0x4(%rdi)
movq %r9, 0x58(%rsp)
leal (%r12,%r9), %eax
incl %eax
movl %eax, 0x8(%rdi)
callq 0x3230
movl %eax, %r13d
callq 0x31a0
movl %eax, %r15d
movl %r13d, %edi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x3410
leaq 0xee0d(%rip), %rsi      # 0x174e7
leaq 0xc(%rsp), %rdx
movq %r14, %rdi
xorl %eax, %eax
callq 0x33d0
cmpl $0x1, %eax
jne 0x8709
movl 0xc(%rsp), %edx
decl %edx
leaq 0xca88(%rip), %rsi      # 0x15183
leaq 0x60(%rsp), %rdi
xorl %eax, %eax
callq 0x3530
jmp 0x8716
leaq 0x60(%rsp), %rdi
movq %r14, %rsi
callq 0x30c0
leaq 0x60(%rsp), %rdi
movl $0x902, %esi            # imm = 0x902
xorl %eax, %eax
callq 0x34a0
movl %eax, (%rbx)
testl %eax, %eax
jns 0x8740
leaq 0xca5b(%rip), %rdi      # 0x1518f
leaq 0x60(%rsp), %rsi
xorl %eax, %eax
callq 0xa2d7
movl %r15d, %edi
movl %r13d, %esi
callq 0x3410
movl (%rbx), %edi
leaq 0x23c(%rbx), %r14
movq %r14, %rsi
callq 0x3480
testl %eax, %eax
je 0x8773
leaq 0xca3c(%rip), %rdi      # 0x151a3
leaq 0x60(%rsp), %rsi
xorl %eax, %eax
callq 0xa2d7
movups (%r14), %xmm0
movups 0x10(%r14), %xmm1
movups 0x20(%r14), %xmm2
movups 0x2c(%r14), %xmm3
movaps %xmm0, 0x10(%rsp)
movups %xmm3, 0x3c(%rsp)
movaps %xmm2, 0x30(%rsp)
movaps %xmm1, 0x20(%rsp)
movabsq $-0xffff00004000, %rax  # imm = 0xFFFF0000FFFFC000
andq %rax, 0x10(%rsp)
movl $0x7fffe000, %r14d      # imm = 0x7FFFE000
andl 0x18(%rsp), %r14d
cmpl $0x5, %r12d
je 0x87d8
cmpl $0x7, %r12d
je 0x87cf
cmpl $0x6, %r12d
jne 0x87e1
orl $0x890, %r14d           # imm = 0x890
jmp 0x87e8
orl $0x8a0, %r14d           # imm = 0x8A0
jmp 0x87e8
orl $0x880, %r14d           # imm = 0x880
jmp 0x87e8
orl $0x8b0, %r14d           # imm = 0x8B0
callq 0x3030
movq (%rax), %rax
movsbq 0x8(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl $0x4f, %eax
je 0x8813
andl $0x7ffffcff, %r14d      # imm = 0x7FFFFCFF
cmpl $0x45, %eax
jne 0x8824
orl $0x100, %r14d           # imm = 0x100
jmp 0x881a
orl $0x300, %r14d           # imm = 0x300
movl %r14d, 0x18(%rsp)
incl 0x8(%rbx)
jmp 0x8829
movl %r14d, 0x18(%rsp)
cmpl $0x2, 0x58(%rsp)
jne 0x8839
orl $0x40, %r14d
movl %r14d, 0x18(%rsp)
andl $0xffff6404, 0x1c(%rsp) # imm = 0xFFFF6404
movw $0x100, 0x26(%rsp)      # imm = 0x100
movl (%rbx), %edi
xorl %esi, %esi
callq 0x31b0
movl $0x2dc6c0, %ecx         # imm = 0x2DC6C0
leaq 0xc9cb(%rip), %rax      # 0x15228
cmpl %ebp, %ecx
je 0x886e
movl (%rax), %ecx
addq $0x8, %rax
cmpl $-0x1, %ecx
jne 0x885d
jmp 0x8896
cmpl $-0x1, -0x4(%rax)
je 0x8896
movl $0x2dc6c0, %ecx         # imm = 0x2DC6C0
leaq 0xc9a8(%rip), %rax      # 0x15228
cmpl %ebp, %ecx
je 0x88a8
movl (%rax), %ecx
addq $0x8, %rax
cmpl $-0x1, %ecx
jne 0x8880
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
jmp 0x88ab
leaq 0xc91f(%rip), %rdi      # 0x151bc
movl %ebp, %esi
xorl %eax, %eax
callq 0xa03c
jmp 0x88e4
movl -0x4(%rax), %esi
leaq 0x10(%rsp), %rdi
callq 0x34c0
movl $0x2dc6c0, %ecx         # imm = 0x2DC6C0
leaq 0xc967(%rip), %rax      # 0x15228
cmpl %ebp, %ecx
je 0x88d7
movl (%rax), %ecx
addq $0x8, %rax
cmpl $-0x1, %ecx
jne 0x88c1
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
jmp 0x88da
movl -0x4(%rax), %esi
leaq 0x10(%rsp), %rdi
callq 0x3170
movl (%rbx), %edi
xorl %ebp, %ebp
leaq 0x10(%rsp), %rdx
xorl %esi, %esi
callq 0x3490
movl (%rbx), %edi
movl $0x4, %esi
movl $0x800, %edx            # imm = 0x800
xorl %eax, %eax
callq 0x3120
cmpl $-0x1, %eax
jne 0x891a
leaq 0xc8ec(%rip), %rdi      # 0x151ff
xorl %eax, %eax
callq 0xa03c
movl (%rbx), %edi
movl $0x1, %esi
callq 0x31b0
movl %ebp, 0x128(%rbx)
leaq 0x20(%rbx), %rax
movq %rax, 0x120(%rbx)
movl (%rbx), %edi
xorl %esi, %esi
callq 0x31b0
movl %ebp, 0x238(%rbx)
leaq 0x12c(%rbx), %rax
movq %rax, 0x230(%rbx)
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq