// File: /workspace/github_c_makefile_star2_O2/hamsternz[P]emulate-risc-v/uart.c
// Function: UART_get
int UART_get(struct region *r, uint32_t address, uint32_t *value) {
   uint32_t v = 0;
   char buffer[100];
   struct uart_data *data = r->data;

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

   if(address+4 > r->size) {
     fprintf(stderr,"Memory region boundary crossed at 0x%08x\n", r->base+address);
     return 0;
   }

   v = 0;

   switch(address) {
     case 0x00:
       v = (data->tx_count == UART_QUEUE_DEPTH) ? (1<<31) : 0;
       if(data->debug) {
         sprintf(buffer,"UART is %s to accept tx data",
           data->tx_count == UART_QUEUE_DEPTH ? "not ready" : "ready");
         display_log(buffer);
       }
       break;
     case 0x04:
       if(data->rx_count > 0) {
	 v = data->rx_fifo[data->rx_read_ptr];
	 data->rx_count--;
	 data->rx_read_ptr = (data->rx_read_ptr == UART_FIFO_SIZE-1) ? 0 : data->rx_read_ptr+1;

         if(data->debug) {
           sprintf(buffer,"UART rx queue read - 0x%03x", v);
	   display_log(buffer);
         }
       } else {
         v = (1<<31);
         if(data->debug) {
           display_log("UART rx queue is empty");
         }
       }
       break;
     case 0x08:
       v = 0;
       v |= data->tx_enable      ? 1 : 0;
       v |= data->stop_bits == 2 ? 2 : 0;
       v |= (data->tx_watermark << 16);
       if(data->debug) {
         sprintf(buffer,"UART get tx_enable = %i, stop_bits = %i, tx_watermark = %i",
           data->tx_enable, data->stop_bits, data->tx_watermark);
         display_log(buffer);
       }
       break;
     case 0x0C:
       v = 0;
       v |= data->rx_enable      ? 1 : 0;
       v |= (data->tx_watermark << 16);
       if(data->debug) {
         sprintf(buffer,"UART get rx_enable = %i, rx_watermark = %i",
           data->rx_enable, data->rx_watermark);
         display_log(buffer);
       }
       break;
     case 0x10:
       v = 0;
       v |= data->rx_irq_enable ? 1 : 0;
       v |= data->tx_irq_enable ? 2 : 0;
       if(data->debug) {
         sprintf(buffer,"UART get rx_irq_enable = %i, tx_irq_enable = %i",
                 data->rx_irq_enable, data->tx_irq_enable);
         display_log(buffer);
       }
       break;
     case 0x14:
       v = 0;
       v |= data->tx_count > data->tx_watermark ? 1 : 0;
       v |= data->rx_count > data->rx_watermark ? 2 : 0;
       if(data->debug) {
         sprintf(buffer,"UART get rx_irq_pending = %i, tx_irq_pending = %i",
                 v&1, v>>1);
         display_log(buffer);
       }
       break;
     case 0x18:
       v = data->divisor;
       if(data->debug) {
         sprintf(buffer,"UART get divisor = 0x%08x", v);
         display_log(buffer);
       }
       break;
     default:
       sprintf(buffer,"UART Wr unkown address 0x%08x: 0x%08x", address, v);
       display_log(buffer);
       break;
   }
   *value = v;

   return 1;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x70, %rsp
movq %rdx, %rbx
movl %esi, %edx
testb $0x3, %dl
jne 0x45d8
leal 0x4(%rdx), %eax
cmpl 0xc(%rdi), %eax
ja 0x45ee
movl %edx, %ecx
shrl $0x2, %ecx
cmpl $0x6, %ecx
ja 0x4518
movq 0x38(%rdi), %rax
leaq 0x3d3a(%rip), %rdx      # 0x8154
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movb 0xc(%rax), %cl
xorl %ebp, %ebp
cmpb $0x8, %cl
sete %bpl
shll $0x1f, %ebp
cmpb $0x0, 0x21(%rax)
je 0x45c8
cmpb $0x8, %cl
leaq 0x3eff(%rip), %rax      # 0x8345
leaq 0x3efc(%rip), %rdx      # 0x8349
cmoveq %rax, %rdx
leaq 0x3ed0(%rip), %rsi      # 0x8328
movq %rsp, %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x21f0
jmp 0x45c0
movzbl 0x1d(%rax), %edx
xorl %esi, %esi
testl %edx, %edx
setne %sil
movzbl 0x1c(%rax), %ecx
xorl %edi, %edi
testl %ecx, %ecx
setne %dil
leal (%rsi,%rdi,2), %ebp
cmpb $0x0, 0x21(%rax)
je 0x45c8
leaq 0x3f52(%rip), %rsi      # 0x83e8
jmp 0x450d
movzbl 0x1a(%rax), %edx
xorl %esi, %esi
testl %edx, %edx
setne %sil
movzbl 0x20(%rax), %ecx
xorl %edi, %edi
cmpl $0x2, %ecx
sete %dil
leal (%rsi,%rdi,2), %esi
movzbl 0x18(%rax), %r8d
movl %r8d, %ebp
shll $0x10, %ebp
orl %esi, %ebp
cmpb $0x0, 0x21(%rax)
je 0x45c8
leaq 0x3eb0(%rip), %rsi      # 0x8382
movq %rsp, %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x21f0
jmp 0x45c0
movzbl 0x1b(%rax), %edx
xorl %ecx, %ecx
testl %edx, %edx
setne %cl
movzbl 0x18(%rax), %ebp
shll $0x10, %ebp
orl %ecx, %ebp
cmpb $0x0, 0x21(%rax)
je 0x45c8
movzbl 0x19(%rax), %ecx
leaq 0x3eb0(%rip), %rsi      # 0x83bd
movq %rsp, %r14
movq %r14, %rdi
jmp 0x4598
leaq 0x3d76(%rip), %rsi      # 0x8295
xorl %ebp, %ebp
movq %rsp, %r14
movq %r14, %rdi
xorl %ecx, %ecx
jmp 0x4598
movb 0x17(%rax), %cl
testb %cl, %cl
je 0x4610
movzbl 0x15(%rax), %edx
decb %cl
leal 0x1(%rdx), %esi
xorl %edi, %edi
cmpq $0x7, %rdx
movzbl 0xd(%rax,%rdx), %ebp
movzbl %sil, %edx
cmovel %edi, %edx
movb %cl, 0x17(%rax)
movb %dl, 0x15(%rax)
cmpb $0x0, 0x21(%rax)
je 0x45c8
leaq 0x3deb(%rip), %rsi      # 0x834f
jmp 0x45b1
movb 0xc(%rax), %cl
xorl %edx, %edx
cmpb 0x18(%rax), %cl
movb 0x17(%rax), %sil
seta %dl
xorl %ecx, %ecx
cmpb 0x19(%rax), %sil
seta %cl
leal (%rdx,%rcx,2), %ebp
cmpb $0x0, 0x21(%rax)
je 0x45c8
addl %ecx, %ecx
shrl %ecx
leaq 0x3e86(%rip), %rsi      # 0x8418
movq %rsp, %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x21f0
jmp 0x45c0
movzwl (%rax), %ebp
cmpb $0x0, 0x21(%rax)
je 0x45c8
leaq 0x3e99(%rip), %rsi      # 0x844a
movq %rsp, %r14
movq %r14, %rdi
movl %ebp, %edx
xorl %eax, %eax
callq 0x21f0
movq %r14, %rdi
callq 0x4b7e
movl %ebp, (%rbx)
pushq $0x1
popq %rbx
movl %ebx, %eax
addq $0x70, %rsp
popq %rbx
popq %r14
popq %rbp
retq
movq 0x7a19(%rip), %rax      # 0xbff8
movq (%rax), %rax
addl 0x8(%rdi), %edx
leaq 0x39fc(%rip), %rsi      # 0x7fe8
jmp 0x4602
movq 0x7a03(%rip), %rax      # 0xbff8
movq (%rax), %rax
addl 0x8(%rdi), %edx
leaq 0x399d(%rip), %rsi      # 0x7f9f
xorl %ebx, %ebx
movq %rax, %rdi
xorl %eax, %eax
callq 0x2140
jmp 0x45cd
movl $0x80000000, %ebp       # imm = 0x80000000
cmpb $0x0, 0x21(%rax)
je 0x45c8
leaq 0x3d49(%rip), %rdi      # 0x836b
jmp 0x45c3