OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [sh/] [sync.md] - Blame information for rev 717

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;; GCC machine description for SH synchronization instructions.
2
;; Copyright (C) 2011
3
;; Free Software Foundation, Inc.
4
;;
5
;; This file is part of GCC.
6
;;
7
;; GCC is free software; you can redistribute it and/or modify
8
;; it under the terms of the GNU General Public License as published by
9
;; the Free Software Foundation; either version 3, or (at your option)
10
;; any later version.
11
;;
12
;; GCC is distributed in the hope that it will be useful,
13
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
;; GNU General Public License for more details.
16
;;
17
;; You should have received a copy of the GNU General Public License
18
;; along with GCC; see the file COPYING3.  If not see
19
;; .
20
;;
21
;;
22
;; Atomic integer operations for the Renesas / SuperH SH CPUs.
23
;;
24
;; On single-core systems there can only be one execution context running
25
;; at a given point in time.  This allows the usage of rewindable atomic
26
;; sequences, which effectively emulate locked-load / conditional-store
27
;; operations.
28
;; When an execution context is interrupted while it is an atomic
29
;; sequence, the interrupted context's PC is rewound to the beginning of
30
;; the atomic sequence by the interrupt / exception handling code, before
31
;; transferring control to another execution context.  This is done by
32
;; something like...
33
;;
34
;;      if (interrupted_context_in_atomic_sequence
35
;;          && interrupted_pc < atomic_exitpoint)
36
;;        interrupted_pc = atomic_entrypoint;
37
;;
38
;; This method is also known as gUSA ("g" User Space Atomicity) and the
39
;; Linux kernel for SH3/SH4 implements support for such software
40
;; atomic sequences.  However, it can also be implemented in freestanding
41
;; environments.
42
;;
43
;; For this the following atomic sequence ABI is used.
44
;;
45
;; r15 >= 0:    Execution context is not in an atomic sequence.
46
;;
47
;; r15  < 0:    Execution context is in an atomic sequence and r15
48
;;              holds the negative byte length of the atomic sequence.
49
;;              In this case the following applies:
50
;;
51
;;              r0:     PC of the first instruction after the atomic
52
;;                      write-back instruction (exit point).
53
;;                      The entry point PC of the atomic sequence can be
54
;;                      determined by doing r0 + r15.
55
;;
56
;;              r1:     Saved r15 stack pointer before entering the
57
;;                      atomic sequence.
58
;;
59
;; An example atomic add sequence would look like:
60
;;
61
;;      mova    .Lend,r0                ! .Lend must be 4-byte aligned.
62
;;      mov     r15,r1
63
;;      .align 2                        ! Insert aligning nop if needed.
64
;;      mov     #(.Lstart - .Lend),r15  ! Enter atomic sequence
65
;;.Lstart:
66
;;      mov.l   @r4,r2                  ! read value
67
;;      add     r2,r5                   ! modify value
68
;;      mov.l   r5,@r4                  ! write-back
69
;;.Lend:
70
;;      mov     r1,r15                  ! Exit atomic sequence
71
;;                                      ! r2 holds the previous value.
72
;;                                      ! r5 holds the new value.
73
;;
74
;; Notice that due to the restrictions of the mova instruction, the .Lend
75
;; label must always be 4-byte aligned.  Aligning the .Lend label would
76
;; potentially insert a nop after the write-back instruction which could
77
;; make the sequence to be rewound, although it has already passed the
78
;; write-back instruction.  This would make it execute twice.
79
;; For correct operation the atomic sequences must not be rewound after
80
;; they have passed the write-back instruction.
81
;;
82
;; The current implementation is limited to QImode, HImode and SImode
83
;; atomic operations.  DImode operations could also be implemented but
84
;; would require some ABI modifications to support multiple-instruction
85
;; write-back.  This is because SH1/SH2/SH3/SH4 does not have a DImode
86
;; store instruction.  DImode stores must be split into two SImode stores.
87
;;
88
;; For some operations it would be possible to use insns with an immediate
89
;; operand such as add #imm,Rn.  However, since the original value before
90
;; the operation also needs to be available, this is not so handy.
91
 
92
(define_c_enum "unspec" [
93
  UNSPEC_ATOMIC
94
])
95
 
96
(define_c_enum "unspecv" [
97
  UNSPECV_CMPXCHG_1
98
  UNSPECV_CMPXCHG_2
99
  UNSPECV_CMPXCHG_3
100
])
101
 
102
(define_mode_iterator I124 [QI HI SI])
103
 
104
(define_mode_attr i124suffix [(QI "b") (HI "w") (SI "l")])
105
(define_mode_attr i124extend_insn [(QI "exts.b") (HI "exts.w") (SI "mov")])
106
 
107
(define_code_iterator FETCHOP [plus minus ior xor and])
108
(define_code_attr fetchop_name
109
  [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
110
 
111
(define_expand "atomic_compare_and_swap"
112
  [(match_operand:QI 0 "register_operand" "")           ;; bool success output
113
   (match_operand:I124 1 "register_operand" "")         ;; oldval output
114
   (match_operand:I124 2 "memory_operand" "")           ;; memory
115
   (match_operand:I124 3 "register_operand" "")         ;; expected input
116
   (match_operand:I124 4 "register_operand" "")         ;; newval input
117
   (match_operand:SI 5 "const_int_operand" "")          ;; is_weak
118
   (match_operand:SI 6 "const_int_operand" "")          ;; success model
119
   (match_operand:SI 7 "const_int_operand" "")]         ;; failure model
120
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
121
{
122
  rtx addr;
123
 
124
  addr = force_reg (Pmode, XEXP (operands[2], 0));
125
  emit_insn (gen_atomic_compare_and_swap_soft
126
             (gen_lowpart (SImode, operands[1]), addr, operands[3],
127
              operands[4]));
128
  if (mode == QImode)
129
    emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[1]),
130
                                     operands[1]));
131
  else if (mode == HImode)
132
    emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[1]),
133
                                     operands[1]));
134
  emit_insn (gen_movqi (operands[0], gen_rtx_REG (QImode, T_REG)));
135
  DONE;
136
})
137
 
138
(define_insn "atomic_compare_and_swap_soft"
139
  [(set (match_operand:SI 0 "register_operand" "=&u")
140
        (unspec_volatile:SI
141
          [(mem:I124 (match_operand:SI 1 "register_operand" "u"))
142
           (match_operand:I124 2 "register_operand" "u")
143
           (match_operand:I124 3 "register_operand" "u")]
144
          UNSPECV_CMPXCHG_1))
145
   (set (mem:I124 (match_dup 1))
146
        (unspec_volatile:I124 [(const_int 0)] UNSPECV_CMPXCHG_2))
147
   (set (reg:QI T_REG)
148
        (unspec_volatile:QI [(const_int 0)] UNSPECV_CMPXCHG_3))
149
   (clobber (match_scratch:SI 4 "=&u"))
150
   (clobber (reg:SI R0_REG))
151
   (clobber (reg:SI R1_REG))]
152
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
153
{
154
  return "mova  1f,r0"                          "\n"
155
         "              %2,%4"  "\n"
156
         "      .align 2"                       "\n"
157
         "      mov     r15,r1"                 "\n"
158
         "      mov     #(0f-1f),r15"           "\n"
159
         "0:    mov.    @%1,%0" "\n"
160
         "      cmp/eq  %0,%4"                  "\n"
161
         "      bf      1f"                     "\n"
162
         "      mov.    %3,@%1" "\n"
163
         "1:    mov     r1,r15";
164
}
165
  [(set_attr "length" "20")])
166
 
167
(define_expand "atomic_fetch_"
168
  [(set (match_operand:I124 0 "register_operand" "")
169
        (match_operand:I124 1 "memory_operand" ""))
170
   (set (match_dup 1)
171
        (unspec:I124
172
          [(FETCHOP:I124 (match_dup 1)
173
             (match_operand:I124 2 "register_operand" ""))]
174
          UNSPEC_ATOMIC))
175
   (match_operand:SI 3 "const_int_operand" "")]
176
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
177
{
178
  rtx addr;
179
 
180
  addr = force_reg (Pmode, XEXP (operands[1], 0));
181
  emit_insn (gen_atomic_fetch__soft
182
             (operands[0], addr, operands[2]));
183
  if (mode == QImode)
184
    emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
185
                                     operands[0]));
186
  else if (mode == HImode)
187
    emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
188
                                     operands[0]));
189
  DONE;
190
})
191
 
192
(define_insn "atomic_fetch__soft"
193
  [(set (match_operand:I124 0 "register_operand" "=&u")
194
        (mem:I124 (match_operand:SI 1 "register_operand" "u")))
195
   (set (mem:I124 (match_dup 1))
196
        (unspec:I124
197
          [(FETCHOP:I124 (mem:I124 (match_dup 1))
198
             (match_operand:I124 2 "register_operand" "u"))]
199
          UNSPEC_ATOMIC))
200
   (clobber (match_scratch:I124 3 "=&u"))
201
   (clobber (reg:SI R0_REG))
202
   (clobber (reg:SI R1_REG))]
203
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
204
{
205
  return "mova  1f,r0"                          "\n"
206
         "      .align 2"                       "\n"
207
         "      mov     r15,r1"                 "\n"
208
         "      mov     #(0f-1f),r15"           "\n"
209
         "0:    mov.    @%1,%0" "\n"
210
         "      mov     %0,%3"                  "\n"
211
         "              %2,%3"          "\n"
212
         "      mov.    %3,@%1" "\n"
213
         "1:    mov     r1,r15";
214
}
215
  [(set_attr "length" "18")])
216
 
217
(define_expand "atomic_fetch_nand"
218
  [(set (match_operand:I124 0 "register_operand" "")
219
        (match_operand:I124 1 "memory_operand" ""))
220
   (set (match_dup 1)
221
        (unspec:I124
222
          [(not:I124 (and:I124 (match_dup 1)
223
             (match_operand:I124 2 "register_operand" "")))]
224
          UNSPEC_ATOMIC))
225
   (match_operand:SI 3 "const_int_operand" "")]
226
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
227
{
228
  rtx addr;
229
 
230
  addr = force_reg (Pmode, XEXP (operands[1], 0));
231
  emit_insn (gen_atomic_fetch_nand_soft
232
             (operands[0], addr, operands[2]));
233
  if (mode == QImode)
234
    emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
235
                                     operands[0]));
236
  else if (mode == HImode)
237
    emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
238
                                     operands[0]));
239
  DONE;
240
})
241
 
242
(define_insn "atomic_fetch_nand_soft"
243
  [(set (match_operand:I124 0 "register_operand" "=&u")
244
        (mem:I124 (match_operand:SI 1 "register_operand" "u")))
245
   (set (mem:I124 (match_dup 1))
246
        (unspec:I124
247
          [(not:I124 (and:I124 (mem:I124 (match_dup 1))
248
             (match_operand:I124 2 "register_operand" "u")))]
249
          UNSPEC_ATOMIC))
250
   (clobber (match_scratch:I124 3 "=&u"))
251
   (clobber (reg:SI R0_REG))
252
   (clobber (reg:SI R1_REG))]
253
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
254
{
255
  return "mova  1f,r0"                          "\n"
256
         "      mov     r15,r1"                 "\n"
257
         "      .align 2"                       "\n"
258
         "      mov     #(0f-1f),r15"           "\n"
259
         "0:    mov.    @%1,%0" "\n"
260
         "      mov     %2,%3"                  "\n"
261
         "      and     %0,%3"                  "\n"
262
         "      not     %3,%3"                  "\n"
263
         "      mov.    %3,@%1" "\n"
264
         "1:    mov     r1,r15";
265
}
266
  [(set_attr "length" "20")])
267
 
268
(define_expand "atomic__fetch"
269
  [(set (match_operand:I124 0 "register_operand" "")
270
        (FETCHOP:I124
271
          (match_operand:I124 1 "memory_operand" "")
272
          (match_operand:I124 2 "register_operand" "")))
273
   (set (match_dup 1)
274
        (unspec:I124
275
          [(FETCHOP:I124 (match_dup 1) (match_dup 2))]
276
          UNSPEC_ATOMIC))
277
   (match_operand:SI 3 "const_int_operand" "")]
278
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
279
{
280
  rtx addr;
281
 
282
  addr = force_reg (Pmode, XEXP (operands[1], 0));
283
  emit_insn (gen_atomic__fetch_soft
284
             (operands[0], addr, operands[2]));
285
  if (mode == QImode)
286
    emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
287
                                     operands[0]));
288
  else if (mode == HImode)
289
    emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
290
                                     operands[0]));
291
  DONE;
292
})
293
 
294
(define_insn "atomic__fetch_soft"
295
  [(set (match_operand:I124 0 "register_operand" "=&u")
296
        (FETCHOP:I124
297
          (mem:I124 (match_operand:SI 1 "register_operand" "u"))
298
          (match_operand:I124 2 "register_operand" "u")))
299
   (set (mem:I124 (match_dup 1))
300
        (unspec:I124
301
          [(FETCHOP:I124 (mem:I124 (match_dup 1)) (match_dup 2))]
302
          UNSPEC_ATOMIC))
303
   (clobber (reg:SI R0_REG))
304
   (clobber (reg:SI R1_REG))]
305
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
306
{
307
  return "mova  1f,r0"                          "\n"
308
         "      mov     r15,r1"                 "\n"
309
         "      .align 2"                       "\n"
310
         "      mov     #(0f-1f),r15"           "\n"
311
         "0:    mov.    @%1,%0" "\n"
312
         "              %2,%0"          "\n"
313
         "      mov.    %0,@%1" "\n"
314
         "1:    mov     r1,r15";
315
}
316
  [(set_attr "length" "16")])
317
 
318
(define_expand "atomic_nand_fetch"
319
  [(set (match_operand:I124 0 "register_operand" "")
320
        (not:I124 (and:I124
321
          (match_operand:I124 1 "memory_operand" "")
322
          (match_operand:I124 2 "register_operand" ""))))
323
   (set (match_dup 1)
324
        (unspec:I124
325
          [(not:I124 (and:I124 (match_dup 1) (match_dup 2)))]
326
          UNSPEC_ATOMIC))
327
   (match_operand:SI 3 "const_int_operand" "")]
328
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
329
{
330
  rtx addr;
331
 
332
  addr = force_reg (Pmode, XEXP (operands[1], 0));
333
  emit_insn (gen_atomic_nand_fetch_soft
334
             (operands[0], addr, operands[2]));
335
  if (mode == QImode)
336
    emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
337
                                     operands[0]));
338
  else if (mode == HImode)
339
    emit_insn (gen_zero_extendhisi2 (gen_lowpart (SImode, operands[0]),
340
                                     operands[0]));
341
  DONE;
342
})
343
 
344
(define_insn "atomic_nand_fetch_soft"
345
  [(set (match_operand:I124 0 "register_operand" "=&u")
346
        (not:I124 (and:I124
347
          (mem:I124 (match_operand:SI 1 "register_operand" "u"))
348
          (match_operand:I124 2 "register_operand" "u"))))
349
   (set (mem:I124 (match_dup 1))
350
        (unspec:I124
351
          [(not:I124 (and:I124 (mem:I124 (match_dup 1)) (match_dup 2)))]
352
          UNSPEC_ATOMIC))
353
   (clobber (reg:SI R0_REG))
354
   (clobber (reg:SI R1_REG))]
355
  "TARGET_SOFT_ATOMIC && !TARGET_SHMEDIA"
356
{
357
  return "mova  1f,r0"                          "\n"
358
         "      .align 2"                       "\n"
359
         "      mov     r15,r1"                 "\n"
360
         "      mov     #(0f-1f),r15"           "\n"
361
         "0:    mov.    @%1,%0" "\n"
362
         "      and     %2,%0"                  "\n"
363
         "      not     %0,%0"                  "\n"
364
         "      mov.    %0,@%1" "\n"
365
         "1:    mov     r1,r15";
366
}
367
  [(set_attr "length" "18")])

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.