GCN libgcc.
[official-gcc.git] / libgcc / config / spu / mfc_multi_tag_reserve.c
blob598c14efab567b45d04bb81f4c6245383fa97a94
1 /* Copyright (C) 2007-2019 Free Software Foundation, Inc.
3 This file is part of GCC.
5 GCC is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 3, or (at your option) any later
8 version.
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 for more details.
15 Under Section 7 of GPL version 3, you are granted additional
16 permissions described in the GCC Runtime Library Exception, version
17 3.1, as published by the Free Software Foundation.
19 You should have received a copy of the GNU General Public License and
20 a copy of the GCC Runtime Library Exception along with this program;
21 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
22 <http://www.gnu.org/licenses/>. */
24 #include <spu_mfcio.h>
25 extern vector unsigned int __mfc_tag_table;
27 /* Reserve a sequential group of tags for exclusive use. The number of
28 tags to be reserved is specified by the <number_of_tags> parameter.
29 This routine returns the first tag ID for a sequential list of
30 available tags and marks them as reserved. The reserved group
31 of tags is in the range starting from the returned tag through
32 the returned tag + <number_of_tags>-1.
34 If the number of tags requested exceeds the number of available
35 sequential tags, then MFC_DMA_TAG_INVALID is returned indicating
36 that the request could not be serviced. */
38 unsigned int
39 __mfc_multi_tag_reserve (unsigned int number_of_tags)
41 vector unsigned int table_copy;
42 vector unsigned int one = (vector unsigned int)
43 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
44 vector unsigned int count_busy, is_valid;
45 vector unsigned int count_total;
46 vector unsigned int count_avail = (vector unsigned int) { 0, 0, 0, 0 };
47 vector unsigned int index = (vector unsigned int) { 0, 0, 0, 0 };
49 table_copy = __mfc_tag_table;
52 /* count_busy: number of consecutive busy tags
53 count_avail: number of consecutive free tags
54 table_copy: temporary copy of the tag table
55 count_total: sum of count_busy and count_avail
56 index: index of the current working tag */
59 table_copy = spu_sl (table_copy, count_avail);
61 count_busy = spu_cntlz (table_copy);
62 table_copy = spu_sl (table_copy, count_busy);
63 count_avail = spu_cntlz (spu_xor(table_copy, -1));
64 count_total = spu_add (count_busy, count_avail);
65 index = spu_add (index, count_total);
67 while (spu_extract (count_avail, 0) < number_of_tags
68 && spu_extract (table_copy, 0) != 0);
70 index = spu_sub (index, count_avail);
72 /* is_valid is set to 0xFFFFFFFF if table_copy == 0, 0 otherwise. */
73 is_valid = spu_cmpeq (table_copy, 0);
74 index = spu_sel (index, is_valid, is_valid);
76 /* Now I need to actually mark the tags as used. */
77 table_copy = spu_sl (one, number_of_tags);
78 table_copy = spu_rl (table_copy, -number_of_tags - spu_extract (index, 0));
79 table_copy = spu_sel (table_copy, __mfc_tag_table, table_copy);
80 __mfc_tag_table = spu_sel (table_copy, __mfc_tag_table, is_valid);
82 return spu_extract (index, 0);