// File: /workspace/github_c_makefile_star2_O3/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x68, %rsp
movl %esi, %r14d
leal 0x4(%r14), %eax
cmpl 0xc(%rdi), %eax
ja 0x44f4
movl %ecx, %ebx
movq 0x38(%rdi), %r15
testb $0x3, %r14b
jne 0x451a
movl %r14d, %eax
roll $0x1e, %eax
cmpl $0x6, %eax
ja 0x43f7
leaq 0x3de8(%rip), %rcx      # 0x8138
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpb $0x7, 0xc(%r15)
ja 0x4484
movzbl 0xb(%r15), %eax
movb %bl, 0x2(%r15,%rax)
incb 0xc(%r15)
movb 0xb(%r15), %al
leal 0x1(%rax), %ecx
xorl %edx, %edx
cmpb $0x7, %al
movzbl %cl, %eax
cmovel %edx, %eax
movb %al, 0xb(%r15)
cmpb $0x0, 0x21(%r15)
je 0x44a7
movzbl %bl, %edx
leaq 0x3e00(%rip), %rsi      # 0x819c
jmp 0x4495
movl %ebx, %eax
andb $0x1, %al
movb %al, 0x1a(%r15)
movl %ebx, %eax
andl $0x2, %eax
cmpl $0x1, %eax
movb $0x2, %al
sbbb $0x0, %al
movb %al, 0x20(%r15)
movl %ebx, %r8d
shrl $0x10, %r8d
movl %r8d, %ecx
andb $0x7, %cl
movb %cl, 0x18(%r15)
cmpb $0x0, 0x21(%r15)
je 0x44a7
andl $0x1, %ebx
movzbl %al, %ecx
andl $0x7, %r8d
leaq 0x3dfe(%rip), %rsi      # 0x81e4
movq %rsp, %rdi
movl %ebx, %edx
xorl %eax, %eax
callq 0x2210
jmp 0x449f
leaq 0x3e97(%rip), %rsi      # 0x8295
movq %rsp, %rdi
movl %r14d, %edx
movl %ebx, %ecx
jmp 0x447b
movl %ebx, %eax
andb $0x1, %al
movb %al, 0x1d(%r15)
movl %ebx, %eax
shrb %al
andb $0x1, %al
movb %al, 0x1c(%r15)
cmpb $0x0, 0x21(%r15)
je 0x44a7
andl $0x1, %ebx
movzbl %al, %ecx
leaq 0x3e18(%rip), %rsi      # 0x824a
jmp 0x4476
movw %bx, (%r15)
cmpb $0x0, 0x21(%r15)
je 0x44a7
leaq 0x3e34(%rip), %rsi      # 0x827a
movq %rsp, %rdi
movl %ebx, %edx
jmp 0x4498
movl %ebx, %eax
andb $0x1, %al
movb %al, 0x1b(%r15)
movl %ebx, %ecx
shrl $0x10, %ecx
movl %ecx, %eax
andb $0x7, %al
movb %al, 0x19(%r15)
cmpb $0x0, 0x21(%r15)
je 0x44a7
andl $0x1, %ebx
andl $0x7, %ecx
leaq 0x3da9(%rip), %rsi      # 0x821f
movq %rsp, %rdi
movl %ebx, %edx
xorl %eax, %eax
callq 0x2210
jmp 0x449f
cmpb $0x0, 0x21(%r15)
je 0x44a7
movzbl %bl, %edx
leaq 0x3d2a(%rip), %rsi      # 0x81bf
movq %rsp, %rdi
xorl %eax, %eax
callq 0x2210
movq %rsp, %rdi
callq 0x4d36
movl $0x1, %ebx
cmpb $0x0, 0x1a(%r15)
je 0x44e7
cmpb $0x0, 0xc(%r15)
je 0x44e7
movb 0xa(%r15), %al
xorl %ebp, %ebp
movzbl %al, %eax
movsbl 0x2(%r15,%rax), %edi
callq 0x4f46
movb 0xa(%r15), %al
leal 0x1(%rax), %ecx
cmpb $0x7, %al
movzbl %cl, %eax
cmovel %ebp, %eax
decb 0xc(%r15)
movb %al, 0xa(%r15)
jne 0x44c0
movl %ebx, %eax
addq $0x68, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq 0x7afd(%rip), %rax      # 0xbff8
movq (%rax), %rax
addl 0x8(%rdi), %r14d
leaq 0x3a96(%rip), %rsi      # 0x7f9f
xorl %ebx, %ebx
movq %rax, %rdi
movl %r14d, %edx
xorl %eax, %eax
callq 0x2150
jmp 0x44e7
movq 0x7ad7(%rip), %rax      # 0xbff8
movq (%rax), %rax
movl 0x8(%rdi), %edx
addl %r14d, %edx
leaq 0x3a98(%rip), %rsi      # 0x7fc9
movq %rax, %rdi
xorl %eax, %eax
callq 0x2150
jmp 0x433a