blob: cf49c36bd2cf4884c74f5fb554e229c3da89b8a1 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_BASE_MEMORY_H_
#define OPENTITAN_SW_DEVICE_LIB_BASE_MEMORY_H_
#include <stdalign.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdnoreturn.h>
#include "sw/device/lib/base/stdasm.h"
/**
* Load a word from memory directly, bypassing aliasing rules.
*
* ISO C forbids, in general, casting a pointer to non-character types and
* reading them, though it is frequently necessary to read exactly one word out
* of a |void *|. This function performs that action in a manner which is
* well-defined.
*
* Of course, |ptr| must point to word-aligned memory that is at least one word
* wide. To do otherwise is Undefined Behavior. It goes eithout saying that the
* memory this function intents to read must be initialized.
*
* This function has reordering properties as weak as a normal, non-atomic,
* non-volatile load.
*
* @param ptr a word-aligned pointer pointed to at least four bytes of memory.
* @return the word |ptr| points to.
*/
inline uint32_t read_32(const void *ptr) {
// Both GCC and Clang optimize the code below into a single word-load on most
// platforms. It is necessary and sufficient to indicate to the compiler that
// the pointer points to four bytes of four-byte-aligned memory.
//
// Failing to get that particular codegen in either GCC or Clang with -O2 or
// -Os set shall be considred a bug in this function. The same applies to
// |write32()|.
ptr = __builtin_assume_aligned(ptr, alignof(uint32_t));
uint32_t val;
__builtin_memcpy(&val, ptr, sizeof(uint32_t));
return val;
}
/**
* Store a word to memory directly, bypassing aliasing rules.
*
* ISO C forbids, in general, casting a pointer to non-character types and
* reading them, though it is frequently necessary to write exactly one word to
* a |void *|. This function performs that action in a manner which is
* well-defined.
*
* Of course, |ptr| must point to word-aligned memory that is at least one word
* wide. To do otherwise is Undefined Behavior.
*
* This function has reordering properties as weak as a normal, non-atomic,
* non-volatile load.
*
* @param value the value to store.
* @param ptr a word-aligned pointer pointed to at least four bytes of memory.
*/
inline void write_32(uint32_t value, void *ptr) {
// Both GCC and Clang optimize the code below into a single word-store on most
// platforms. See the comment in |read_32()| for more implementation-private
// information.
ptr = __builtin_assume_aligned(ptr, alignof(uint32_t));
__builtin_memcpy(ptr, &value, sizeof(uint32_t));
}
/**
* Copy memory between non-overlapping regions.
*
* This function conforms to the semantics defined in ISO C11 S7.23.2.1.
*
* @param dest the region to copy to.
* @param src the region to copy from.
* @param len the number of bytes to copy.
* @return the value of |dest|.
*/
void *memcpy(void *restrict dest, const void *restrict src, size_t len);
/**
* Set a region of memory to a particular byte value.
*
* This function conforms to the semantics defined in ISO C11 S7.23.6.1.
*
* @param dest the region to write to.
* @param value the value, converted to a byte, to write to each byte cell.
* @param len the number of bytes to write.
* #return the value of |dest|.
*/
void *memset(void *dest, int value, size_t len);
#endif // OPENTITAN_SW_DEVICE_LIB_BASE_MEMORY_H_