// File: /workspace/github_c_makefile_star2_O0/hamsternz[P]emulate-risc-v/uart.c
// Function: UART_set
int UART_set(struct region *r, uint32_t address, uint8_t mask, uint32_t value) {
   char buffer[100];
   struct uart_data *data = r->data;
   if(address+4 > r->size) {
     fprintf(stderr,"Memory region boundary crossed at 0x%08x\n", r->base+address);
     return 0;
   }

   if((address & 3) != 0) {
     fprintf(stderr,"Unaligned memory write 0x%08x\n", r->base+address);
   }


   switch(address) {
     case 0x00: // TRANSMIT DATA REGISTER
	 if(data->tx_count < UART_FIFO_SIZE) {
	   data->tx_fifo[data->tx_write_ptr] = value & 0xFF;
	   data->tx_count++;
           data->tx_write_ptr = (data->tx_write_ptr == UART_FIFO_SIZE-1) ? 0 : data->tx_write_ptr+1;

	   if(data->debug) {
             sprintf(buffer,"UART data added to tx queue 0x%02x", value & 0xff);
             display_log(buffer);
	   }
         } else {
           if(data->debug) {
             sprintf(buffer,"UART tx queue overflow adding 0x%02x", value & 0xff);
             display_log(buffer);
           }
	 }
	 break;    
     case 0x04:
	 break;
     case 0x08:
	 data->tx_enable    = (value  &  1) ? 1 : 0;
	 data->stop_bits    = (value  &  2) ? 2 : 1;
	 data->tx_watermark = (value >> 16) & 0x7;
         if(data->debug) {
           sprintf(buffer,"UART set tx_enable = %i, stop_bits = %i, tx_watermark = %i",
		data->tx_enable, data->stop_bits, data->tx_watermark);
           display_log(buffer);
         }
	 break;
     case 0x0C:
	 data->rx_enable    = (value  &  1) ? 1 : 0;
	 data->rx_watermark = (value >> 16) & 0x7;
         if(data->debug) {
           sprintf(buffer,"UART set rx_enable = %i, rx_watermark = %i",
		data->rx_enable, data->rx_watermark);
           display_log(buffer);
         }
	 break;
     case 0x10:
	 data->rx_irq_enable = (value  &  1) ? 1 : 0;
	 data->tx_irq_enable = (value  &  2) ? 1 : 0;
         if(data->debug) {
           sprintf(buffer,"UART set rx_irq_enable = %i, tx_irq_enable = %i",
                 data->rx_irq_enable, data->tx_irq_enable);
           display_log(buffer);
         }
	 break;
     case 0x14:
	 break;
     case 0x18:
	 data->divisor = value & 0xFFFF;
	 if(data->debug) {
           sprintf(buffer,"UART Divisor set to 0x%08x", value);
           display_log(buffer);
	 }
	 break;
     default:
         sprintf(buffer,"UART Wr unkown address 0x%08x: 0x%08x", address, value);
         display_log(buffer);
	 break;
   }

   // SHould I flush the queue? 
   if(data->tx_enable) {
     while(data->tx_count > 0) {
       display_uart_write(data->tx_fifo[data->tx_read_ptr] & 0xFF);
       data->tx_count--;
       data->tx_read_ptr = (data->tx_read_ptr == UART_FIFO_SIZE-1) ? 0 : data->tx_read_ptr+1;
     }
   }
   return 1;
}

// Assembly:
subq $0xa8, %rsp
movb %dl, %al
movq %rdi, 0x98(%rsp)
movl %esi, 0x94(%rsp)
movb %al, 0x93(%rsp)
movl %ecx, 0x8c(%rsp)
movq 0x98(%rsp), %rax
movq 0x38(%rax), %rax
movq %rax, 0x18(%rsp)
movl 0x94(%rsp), %eax
addl $0x4, %eax
movq 0x98(%rsp), %rcx
cmpl 0xc(%rcx), %eax
jbe 0x5878
movq 0x87b3(%rip), %rax      # 0xdff8
movq (%rax), %rdi
movq 0x98(%rsp), %rax
movl 0x8(%rax), %edx
addl 0x94(%rsp), %edx
leaq 0x56d0(%rip), %rsi      # 0xaf31
movb $0x0, %al
callq 0x2130
movl $0x0, 0xa4(%rsp)
jmp 0x5c63
movl 0x94(%rsp), %eax
andl $0x3, %eax
cmpl $0x0, %eax
je 0x58b1
movq 0x876a(%rip), %rax      # 0xdff8
movq (%rax), %rdi
movq 0x98(%rsp), %rax
movl 0x8(%rax), %edx
addl 0x94(%rsp), %edx
leaq 0x56b1(%rip), %rsi      # 0xaf5b
movb $0x0, %al
callq 0x2130
movl 0x94(%rsp), %eax
movq %rax, 0x10(%rsp)
subq $0x18, %rax
ja 0x5bac
movq 0x10(%rsp), %rax
leaq 0x57f9(%rip), %rcx      # 0xb0cc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x18(%rsp), %rax
movzbl 0xc(%rax), %eax
cmpl $0x8, %eax
jge 0x5987
movl 0x8c(%rsp), %eax
andl $0xff, %eax
movb %al, %dl
movq 0x18(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl 0xb(%rcx), %ecx
movb %dl, 0x2(%rax,%rcx)
movq 0x18(%rsp), %rax
movb 0xc(%rax), %cl
addb $0x1, %cl
movb %cl, 0xc(%rax)
movq 0x18(%rsp), %rax
movzbl 0xb(%rax), %eax
cmpl $0x7, %eax
jne 0x5932
xorl %eax, %eax
movl %eax, 0xc(%rsp)
jmp 0x5942
movq 0x18(%rsp), %rax
movzbl 0xb(%rax), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0xb(%rax)
movq 0x18(%rsp), %rax
cmpb $0x0, 0x21(%rax)
je 0x5985
leaq 0x20(%rsp), %rdi
movl 0x8c(%rsp), %edx
andl $0xff, %edx
leaq 0x584c(%rip), %rsi      # 0xb1c0
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
jmp 0x59be
movq 0x18(%rsp), %rax
cmpb $0x0, 0x21(%rax)
je 0x59bc
leaq 0x20(%rsp), %rdi
movl 0x8c(%rsp), %edx
andl $0xff, %edx
leaq 0x5838(%rip), %rsi      # 0xb1e3
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
jmp 0x59be
jmp 0x5bd7
jmp 0x5bd7
movl 0x8c(%rsp), %edx
andl $0x1, %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x1a(%rax)
movl 0x8c(%rsp), %edx
andl $0x2, %edx
movl $0x1, %eax
movl $0x2, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x20(%rax)
movl 0x8c(%rsp), %eax
shrl $0x10, %eax
andl $0x7, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x18(%rax)
movq 0x18(%rsp), %rax
cmpb $0x0, 0x21(%rax)
je 0x5a68
leaq 0x20(%rsp), %rdi
movq 0x18(%rsp), %rax
movzbl 0x1a(%rax), %edx
movq 0x18(%rsp), %rax
movzbl 0x20(%rax), %ecx
movq 0x18(%rsp), %rax
movzbl 0x18(%rax), %r8d
leaq 0x57b1(%rip), %rsi      # 0xb208
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
jmp 0x5bd7
movl 0x8c(%rsp), %edx
andl $0x1, %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x1b(%rax)
movl 0x8c(%rsp), %eax
shrl $0x10, %eax
andl $0x7, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x19(%rax)
movq 0x18(%rsp), %rax
cmpb $0x0, 0x21(%rax)
je 0x5adf
leaq 0x20(%rsp), %rdi
movq 0x18(%rsp), %rax
movzbl 0x1b(%rax), %edx
movq 0x18(%rsp), %rax
movzbl 0x19(%rax), %ecx
leaq 0x5775(%rip), %rsi      # 0xb243
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
jmp 0x5bd7
movl 0x8c(%rsp), %edx
andl $0x1, %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x1d(%rax)
movl 0x8c(%rsp), %edx
andl $0x2, %edx
xorl %eax, %eax
movl $0x1, %ecx
cmpl $0x0, %edx
cmovnel %ecx, %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0x1c(%rax)
movq 0x18(%rsp), %rax
cmpb $0x0, 0x21(%rax)
je 0x5b60
leaq 0x20(%rsp), %rdi
movq 0x18(%rsp), %rax
movzbl 0x1d(%rax), %edx
movq 0x18(%rsp), %rax
movzbl 0x1c(%rax), %ecx
leaq 0x571f(%rip), %rsi      # 0xb26e
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
jmp 0x5bd7
jmp 0x5bd7
movl 0x8c(%rsp), %eax
andl $0xffff, %eax           # imm = 0xFFFF
movw %ax, %cx
movq 0x18(%rsp), %rax
movw %cx, (%rax)
movq 0x18(%rsp), %rax
cmpb $0x0, 0x21(%rax)
je 0x5baa
leaq 0x20(%rsp), %rdi
movl 0x8c(%rsp), %edx
leaq 0x5705(%rip), %rsi      # 0xb29e
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
jmp 0x5bd7
leaq 0x20(%rsp), %rdi
movl 0x94(%rsp), %edx
movl 0x8c(%rsp), %ecx
leaq 0x56f3(%rip), %rsi      # 0xb2b9
movb $0x0, %al
callq 0x21e0
leaq 0x20(%rsp), %rdi
callq 0x6b20
movq 0x18(%rsp), %rax
cmpb $0x0, 0x1a(%rax)
je 0x5c58
jmp 0x5be4
movq 0x18(%rsp), %rax
movzbl 0xc(%rax), %eax
cmpl $0x0, %eax
jle 0x5c56
movq 0x18(%rsp), %rax
movq 0x18(%rsp), %rcx
movzbl 0xa(%rcx), %ecx
movzbl 0x2(%rax,%rcx), %eax
andl $0xff, %eax
movsbl %al, %edi
callq 0x6e80
movq 0x18(%rsp), %rax
movb 0xc(%rax), %cl
addb $-0x1, %cl
movb %cl, 0xc(%rax)
movq 0x18(%rsp), %rax
movzbl 0xa(%rax), %eax
cmpl $0x7, %eax
jne 0x5c36
xorl %eax, %eax
movl %eax, 0x8(%rsp)
jmp 0x5c46
movq 0x18(%rsp), %rax
movzbl 0xa(%rax), %eax
addl $0x1, %eax
movl %eax, 0x8(%rsp)
movl 0x8(%rsp), %eax
movb %al, %cl
movq 0x18(%rsp), %rax
movb %cl, 0xa(%rax)
jmp 0x5be4
jmp 0x5c58
movl $0x1, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
addq $0xa8, %rsp
retq
nopw %cs:(%rax,%rax)