// File: /workspace/github_c_makefile_star2_O1/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 0x3240
movl %eax, %r13d
callq 0x31b0
movl %eax, %r15d
movl %r13d, %edi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x3420
leaq 0xecd3(%rip), %rsi      # 0x1744f
leaq 0xc(%rsp), %rdx
movq %r14, %rdi
xorl %eax, %eax
callq 0x33e0
cmpl $0x1, %eax
jne 0x87ab
movl 0xc(%rsp), %edx
decl %edx
leaq 0xca0e(%rip), %rsi      # 0x151ab
leaq 0x60(%rsp), %rdi
xorl %eax, %eax
callq 0x3540
jmp 0x87b8
leaq 0x60(%rsp), %rdi
movq %r14, %rsi
callq 0x30d0
leaq 0x60(%rsp), %rdi
movl $0x902, %esi            # imm = 0x902
xorl %eax, %eax
callq 0x34b0
movl %eax, (%rbx)
testl %eax, %eax
jns 0x87e2
leaq 0xc9e1(%rip), %rdi      # 0x151b7
leaq 0x60(%rsp), %rsi
xorl %eax, %eax
callq 0xa2ef
movl %r15d, %edi
movl %r13d, %esi
callq 0x3420
movl (%rbx), %edi
leaq 0x23c(%rbx), %r14
movq %r14, %rsi
callq 0x3490
testl %eax, %eax
je 0x8815
leaq 0xc9c2(%rip), %rdi      # 0x151cb
leaq 0x60(%rsp), %rsi
xorl %eax, %eax
callq 0xa2ef
movups (%r14), %xmm0
movups 0x10(%r14), %xmm1
movups 0x20(%r14), %xmm2
movups 0x2c(%r14), %xmm3
movaps %xmm0, 0x10(%rsp)
movups %xmm3, 0x3c(%rsp)
andl $0xffffc000, 0x10(%rsp) # imm = 0xFFFFC000
movaps %xmm2, 0x30(%rsp)
movaps %xmm1, 0x20(%rsp)
movzwl 0x16(%rsp), %eax
shll $0x10, %eax
movl %eax, 0x14(%rsp)
movl $0x7fffe000, %eax       # imm = 0x7FFFE000
andl 0x18(%rsp), %eax
leal 0x880(%rax), %r14d
movl %r14d, 0x18(%rsp)
cmpl $0x5, %r12d
je 0x888d
cmpl $0x7, %r12d
je 0x887e
cmpl $0x6, %r12d
jne 0x8885
orl $0x890, %eax            # imm = 0x890
jmp 0x888a
orl $0x8a0, %eax            # imm = 0x8A0
jmp 0x888a
orl $0x8b0, %eax            # imm = 0x8B0
movl %eax, %r14d
movl %r14d, 0x18(%rsp)
callq 0x3030
movq (%rax), %rax
movsbq 0x8(%rsp), %rcx
movl (%rax,%rcx,4), %eax
cmpl $0x4f, %eax
je 0x88bd
andl $0x7ffffcff, %r14d      # imm = 0x7FFFFCFF
cmpl $0x45, %eax
jne 0x88ce
orl $0x100, %r14d           # imm = 0x100
jmp 0x88c4
orl $0x300, %r14d           # imm = 0x300
movl %r14d, 0x18(%rsp)
incl 0x8(%rbx)
jmp 0x88d3
movl %r14d, 0x18(%rsp)
cmpl $0x2, 0x58(%rsp)
jne 0x88df
orb $0x40, 0x18(%rsp)
andl $0xffff6404, 0x1c(%rsp) # imm = 0xFFFF6404
movw $0x100, 0x26(%rsp)      # imm = 0x100
movl (%rbx), %edi
xorl %esi, %esi
callq 0x31c0
movl $0x2dc6c0, %ecx         # imm = 0x2DC6C0
leaq 0xc955(%rip), %rax      # 0x15258
cmpl %ebp, %ecx
je 0x8914
movl (%rax), %ecx
addq $0x8, %rax
cmpl $-0x1, %ecx
jne 0x8903
jmp 0x893c
cmpl $-0x1, -0x4(%rax)
je 0x893c
movl $0x2dc6c0, %ecx         # imm = 0x2DC6C0
leaq 0xc932(%rip), %rax      # 0x15258
cmpl %ebp, %ecx
je 0x894e
movl (%rax), %ecx
addq $0x8, %rax
cmpl $-0x1, %ecx
jne 0x8926
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
jmp 0x8951
leaq 0xc8a1(%rip), %rdi      # 0x151e4
movl %ebp, %esi
xorl %eax, %eax
callq 0xa054
jmp 0x898a
movl -0x4(%rax), %esi
leaq 0x10(%rsp), %rdi
callq 0x34d0
movl $0x2dc6c0, %ecx         # imm = 0x2DC6C0
leaq 0xc8f1(%rip), %rax      # 0x15258
cmpl %ebp, %ecx
je 0x897d
movl (%rax), %ecx
addq $0x8, %rax
cmpl $-0x1, %ecx
jne 0x8967
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
jmp 0x8980
movl -0x4(%rax), %esi
leaq 0x10(%rsp), %rdi
callq 0x3180
movl (%rbx), %edi
xorl %ebp, %ebp
leaq 0x10(%rsp), %rdx
xorl %esi, %esi
callq 0x34a0
movl (%rbx), %edi
movl $0x4, %esi
movl $0x800, %edx            # imm = 0x800
xorl %eax, %eax
callq 0x3130
cmpl $-0x1, %eax
jne 0x89c0
leaq 0xc86e(%rip), %rdi      # 0x15227
xorl %eax, %eax
callq 0xa054
movl (%rbx), %edi
movl $0x1, %esi
callq 0x31c0
movl %ebp, 0x128(%rbx)
leaq 0x20(%rbx), %rax
movq %rax, 0x120(%rbx)
movl (%rbx), %edi
xorl %esi, %esi
callq 0x31c0
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