github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/internal/reg/reg16.go (about)

     1  // https://github.com/usbarmory/tamago
     2  //
     3  // Copyright (c) WithSecure Corporation
     4  // https://foundry.withsecure.com
     5  //
     6  // Use of this source code is governed by the license
     7  // that can be found in the LICENSE file.
     8  
     9  package reg
    10  
    11  import (
    12  	"runtime"
    13  	"time"
    14  	"unsafe"
    15  )
    16  
    17  // As sync/atomic does not provide 16-bit support, note that these functions do
    18  // not necessarily enforce memory ordering.
    19  
    20  func Get16(addr uint32, pos int, mask int) uint16 {
    21  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    22  	return (*reg >> pos) & uint16(mask)
    23  }
    24  
    25  func Set16(addr uint32, pos int) {
    26  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    27  	*reg |= (1 << pos)
    28  }
    29  
    30  func Clear16(addr uint32, pos int) {
    31  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    32  	*reg &= ^(1 << pos)
    33  }
    34  
    35  func SetTo16(addr uint32, pos int, val bool) {
    36  	if val {
    37  		Set16(addr, pos)
    38  	} else {
    39  		Clear16(addr, pos)
    40  	}
    41  }
    42  
    43  func SetN16(addr uint32, pos int, mask int, val uint16) {
    44  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    45  	*reg = (*reg & (^(uint16(mask) << pos))) | (val << pos)
    46  }
    47  
    48  func ClearN16(addr uint32, pos int, mask int) {
    49  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    50  	*reg &= ^(uint16(mask) << pos)
    51  }
    52  
    53  func Read16(addr uint32) uint16 {
    54  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    55  	return *reg
    56  }
    57  
    58  func Write16(addr uint32, val uint16) {
    59  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    60  	*reg = val
    61  }
    62  
    63  func WriteBack16(addr uint32) {
    64  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    65  	*reg |= *reg
    66  }
    67  
    68  func Or16(addr uint32, val uint16) {
    69  	reg := (*uint16)(unsafe.Pointer(uintptr(addr)))
    70  	*reg |= val
    71  }
    72  
    73  // Wait16 waits for a specific register bit to match a value. This function
    74  // cannot be used before runtime initialization with `GOOS=tamago`.
    75  func Wait16(addr uint32, pos int, mask int, val uint16) {
    76  	for Get16(addr, pos, mask) != val {
    77  		// tamago is single-threaded, give other goroutines a chance
    78  		runtime.Gosched()
    79  	}
    80  }
    81  
    82  // WaitFor16 waits, until a timeout expires, for a specific register bit to match
    83  // a value. The return boolean indicates whether the wait condition was checked
    84  // (true) or if it timed out (false). This function cannot be used before
    85  // runtime initialization with `GOOS=tamago`.
    86  func WaitFor16(timeout time.Duration, addr uint32, pos int, mask int, val uint16) bool {
    87  	start := time.Now()
    88  
    89  	for Get16(addr, pos, mask) != val {
    90  		// tamago is single-threaded, give other goroutines a chance
    91  		runtime.Gosched()
    92  
    93  		if time.Since(start) >= timeout {
    94  			return false
    95  		}
    96  	}
    97  
    98  	return true
    99  }