summaryrefslogtreecommitdiff
path: root/cesar/lib/src/read_word.c
blob: 27145c91af9dcc03a1f8b1abaa8c9eb844208bb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* Cesar project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    lib/src/read_word.c
 * \brief   Read a word from the memory aligned on an integer address.
 * \ingroup lib
 * 
 * Allows the system to get a value from the memory reading it word by word
 * and returning the value request from the user.
 * 
 * Exemple : we need to get a 4 bytes word from the address 503 on the 
 * memory it will calculate the address from the one it should start reading
 * the data to be aligned.
 * So it will read a word from the address 500 and the next one from the @
 * 504, it will take the last byte of the first word and concatante it with
 * the three bytes in the last word.
 * result = word2 << 24 | word1
 * 
 */

/**
 * Read the necessary words from the memory and return the data requested.
 * Aware : if less than a word is request, it will need to be masqued to
 * desable the bytes which are note necessary.
 * Example : if you only need the two first bytes you should request:
 *   read_bytes_from_word (addr, 2) & 0xFFFF
 */

#include "common/std.h"
#include "lib/read_word.h"

/**
 * Read u64 from two words.
 * 
 * \param  addr  the address to read the next two 48 bits.
 * \return u64 masked on 48 bits.
 */
u64 read_u64_from_word (u8 *addr)
{
    u64 data;

    data = read_u32_from_word (addr) 
            | ((u64)read_u32_from_word(addr + sizeof(uint)) << 32);

    return data;
}


/**
 * Read u56 from two words.
 * 
 * \param  addr  the address to read the next two 48 bits.
 * \return u64 masked on 48 bits.
 */
u64 read_u56_from_word (u8 *addr)
{
    u64 data;

    data = read_u32_from_word (addr) 
            | ((u64)read_u24_from_word(addr + sizeof(uint)) << 32);

    return data;
}


/**
 * Read u48 from two words.
 * 
 * \param  addr  the address to read the next two 48 bits.
 * \return u64 masked on 48 bits.
 */
u64 read_u48_from_word (u8 *addr)
{
    u64 data;

    data = read_u32_from_word (addr) 
            | ((u64)read_u16_from_word(addr + sizeof(uint)) << 32);

    return data;
}

/**
 * Read 32 bits from the word.
 * 
 * \param  addr the address from the one the value should be read.
 * \return  the u32
 */
uint read_u32_from_word (u8 *addr)
{
    return read_bytes_from_word(addr, 4);
}

/**
 * Reads 24 bits from the word.
 * 
 * \param  addr the address from the one the value should be read.
 * \return  the u32 with the last byte set to 0
 */
uint read_u24_from_word (u8 *addr)
{
    return read_bytes_from_word (addr, 3) & 0x00FFFFFF;
}

/**
 * Read 16 bits from the word.
 * 
 * \param  addr the address from the one the value should be read.
 * \return  the u32 with the last byte set to 0
 */
uint read_u16_from_word (u8 *addr)
{
    return read_bytes_from_word (addr, 2) & 0x0000FFFF;
}

/**
 * Read 8 bits from the word.
 * 
 * \param  addr the address from the one the value should be read.
 * \return  uint with only one byte filled.
 */
uint read_u8_from_word (u8 *addr)
{
    return read_bytes_from_word (addr, 1) & 0x000000FF;
}