// File: /workspace/github_c_makefile_star2_O2/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 0x4308
movl %ecx, %ebx
movq 0x38(%rdi), %r15
testb $0x3, %r14b
jne 0x4339
movl %r14d, %eax
roll $0x1e, %eax
cmpl $0x6, %eax
ja 0x4214
leaq 0x3fcb(%rip), %rcx      # 0x8138
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpb $0x7, 0xc(%r15)
ja 0x42a1
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 0x42c4
movzbl %bl, %edx
leaq 0x3fe3(%rip), %rsi      # 0x819c
jmp 0x42b2
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 0x42c4
andl $0x1, %ebx
movzbl %al, %ecx
andl $0x7, %r8d
leaq 0x3fe1(%rip), %rsi      # 0x81e4
movq %rsp, %rdi
movl %ebx, %edx
xorl %eax, %eax
callq 0x21f0
jmp 0x42bc
leaq 0x407a(%rip), %rsi      # 0x8295
movq %rsp, %rdi
movl %r14d, %edx
movl %ebx, %ecx
jmp 0x4298
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 0x42c4
andl $0x1, %ebx
movzbl %al, %ecx
leaq 0x3ffb(%rip), %rsi      # 0x824a
jmp 0x4293
movw %bx, (%r15)
cmpb $0x0, 0x21(%r15)
je 0x42c4
leaq 0x4017(%rip), %rsi      # 0x827a
movq %rsp, %rdi
movl %ebx, %edx
jmp 0x42b5
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 0x42c4
andl $0x1, %ebx
andl $0x7, %ecx
leaq 0x3f8c(%rip), %rsi      # 0x821f
movq %rsp, %rdi
movl %ebx, %edx
xorl %eax, %eax
callq 0x21f0
jmp 0x42bc
cmpb $0x0, 0x21(%r15)
je 0x42c4
movzbl %bl, %edx
leaq 0x3f0d(%rip), %rsi      # 0x81bf
movq %rsp, %rdi
xorl %eax, %eax
callq 0x21f0
movq %rsp, %rdi
callq 0x4b7e
pushq $0x1
popq %rbx
cmpb $0x0, 0x1a(%r15)
je 0x432c
movb 0xc(%r15), %al
xorl %ebp, %ebp
testb %al, %al
je 0x432c
movzbl 0xa(%r15), %eax
movsbl 0x2(%r15,%rax), %edi
callq 0x4d48
movb 0xa(%r15), %cl
movb 0xc(%r15), %al
decb %al
movb %al, 0xc(%r15)
leal 0x1(%rcx), %edx
cmpb $0x7, %cl
movzbl %dl, %ecx
cmovel %ebp, %ecx
movb %cl, 0xa(%r15)
jmp 0x42d4
movq 0x7ce9(%rip), %rax      # 0xbff8
movq (%rax), %rax
addl 0x8(%rdi), %r14d
leaq 0x3c82(%rip), %rsi      # 0x7f9f
xorl %ebx, %ebx
movq %rax, %rdi
movl %r14d, %edx
xorl %eax, %eax
callq 0x2140
movl %ebx, %eax
addq $0x68, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq 0x7cb8(%rip), %rax      # 0xbff8
movq (%rax), %rax
movl 0x8(%rdi), %edx
addl %r14d, %edx
leaq 0x3c79(%rip), %rsi      # 0x7fc9
movq %rax, %rdi
xorl %eax, %eax
callq 0x2140
jmp 0x4157