aboutsummaryrefslogtreecommitdiff
path: root/target-arm/op_mem.h
blob: f11c4982133d77246a77cfa4ae1b9bb6e4bfac2c (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
/* ARM memory operations.  */

/* Swap T0 with memory at address T1.  */
/* ??? Is this exception safe?  */
#define MEM_SWP_OP(name, lname) \
void OPPROTO glue(op_swp##name,MEMSUFFIX)(void) \
{ \
    uint32_t tmp; \
    cpu_lock(); \
    tmp = glue(ld##lname,MEMSUFFIX)(T1); \
    glue(st##name,MEMSUFFIX)(T1, T0); \
    T0 = tmp; \
    cpu_unlock(); \
    FORCE_RET(); \
}

MEM_SWP_OP(b, ub)
MEM_SWP_OP(l, l)

#undef MEM_SWP_OP

/* Load-locked, store exclusive.  */
#define EXCLUSIVE_OP(suffix, ldsuffix) \
void OPPROTO glue(op_ld##suffix##ex,MEMSUFFIX)(void) \
{ \
    cpu_lock(); \
    helper_mark_exclusive(env, T1); \
    T0 = glue(ld##ldsuffix,MEMSUFFIX)(T1); \
    cpu_unlock(); \
    FORCE_RET(); \
} \
 \
void OPPROTO glue(op_st##suffix##ex,MEMSUFFIX)(void) \
{ \
    int failed; \
    cpu_lock(); \
    failed = helper_test_exclusive(env, T1); \
    /* ??? Is it safe to hold the cpu lock over a store?  */ \
    if (!failed) { \
        glue(st##suffix,MEMSUFFIX)(T1, T0); \
    } \
    T0 = failed; \
    cpu_unlock(); \
    FORCE_RET(); \
}

EXCLUSIVE_OP(b, ub)
EXCLUSIVE_OP(w, uw)
EXCLUSIVE_OP(l, l)

#undef EXCLUSIVE_OP

/* Load exclusive T0:T1 from address T1.  */
void OPPROTO glue(op_ldqex,MEMSUFFIX)(void)
{
    cpu_lock();
    helper_mark_exclusive(env, T1);
    T0 = glue(ldl,MEMSUFFIX)(T1);
    T1 = glue(ldl,MEMSUFFIX)((T1 + 4));
    cpu_unlock();
    FORCE_RET();
}

/* Store exclusive T0:T2 to address T1.  */
void OPPROTO glue(op_stqex,MEMSUFFIX)(void)
{
    int failed;
    cpu_lock();
    failed = helper_test_exclusive(env, T1);
    /* ??? Is it safe to hold the cpu lock over a store?  */
    if (!failed) {
        glue(stl,MEMSUFFIX)(T1, T0);
        glue(stl,MEMSUFFIX)((T1 + 4), T2);
    }
    T0 = failed;
    cpu_unlock();
    FORCE_RET();
}

/* Floating point load/store.  Address is in T1 */
#define VFP_MEM_OP(p, w) \
void OPPROTO glue(op_vfp_ld##p,MEMSUFFIX)(void) \
{ \
    FT0##p = glue(ldf##w,MEMSUFFIX)(T1); \
    FORCE_RET(); \
} \
void OPPROTO glue(op_vfp_st##p,MEMSUFFIX)(void) \
{ \
    glue(stf##w,MEMSUFFIX)(T1, FT0##p); \
    FORCE_RET(); \
}

VFP_MEM_OP(s,l)
VFP_MEM_OP(d,q)

#undef VFP_MEM_OP

/* iwMMXt load/store.  Address is in T1 */
#define MMX_MEM_OP(name, ldname) \
void OPPROTO glue(op_iwmmxt_ld##name,MEMSUFFIX)(void) \
{ \
    M0 = glue(ld##ldname,MEMSUFFIX)(T1); \
    FORCE_RET(); \
} \
void OPPROTO glue(op_iwmmxt_st##name,MEMSUFFIX)(void) \
{ \
    glue(st##name,MEMSUFFIX)(T1, M0); \
    FORCE_RET(); \
}

MMX_MEM_OP(b, ub)
MMX_MEM_OP(w, uw)
MMX_MEM_OP(l, l)
MMX_MEM_OP(q, q)

#undef MMX_MEM_OP

#undef MEMSUFFIX