diff options
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/avx2.h | 48 | ||||
| -rw-r--r-- | src/arch/neon.h | 22 | ||||
| -rw-r--r-- | src/arch/portable.h | 14 |
3 files changed, 42 insertions, 42 deletions
diff --git a/src/arch/avx2.h b/src/arch/avx2.h index 8d53f8f..2c3371e 100644 --- a/src/arch/avx2.h +++ b/src/arch/avx2.h | |||
| @@ -1,19 +1,19 @@ | |||
| 1 | #define _co2_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x6060606060606060)) | 1 | #define CO2_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x6060606060606060)) |
| 2 | #define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x2020202020202020)) | 2 | #define COCW_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x2020202020202020)) |
| 3 | #define _cp_avx2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x0707070707070707)) | 3 | #define CP_AVX2 _mm256_set_epi64x(0, 0, 0, INT64_C(0x0707070707070707)) |
| 4 | #define _ep_avx2 \ | 4 | #define EP_AVX2 \ |
| 5 | _mm256_set_epi64x(INT64_C(0x0F0F0F0F), INT64_C(0x0F0F0F0F0F0F0F0F), 0, 0) | 5 | _mm256_set_epi64x(INT64_C(0x0F0F0F0F), INT64_C(0x0F0F0F0F0F0F0F0F), 0, 0) |
| 6 | #define _eo_avx2 \ | 6 | #define EO_AVX2 \ |
| 7 | _mm256_set_epi64x(INT64_C(0x10101010), INT64_C(0x1010101010101010), 0, 0) | 7 | _mm256_set_epi64x(INT64_C(0x10101010), INT64_C(0x1010101010101010), 0, 0) |
| 8 | 8 | ||
| 9 | #define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ | 9 | #define STATIC_CUBE(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ |
| 10 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ | 10 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ |
| 11 | _mm256_set_epi8(0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, \ | 11 | _mm256_set_epi8(0, 0, 0, 0, e_br, e_bl, e_fl, e_fr, \ |
| 12 | e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, \ | 12 | e_dr, e_dl, e_ul, e_ur, e_df, e_db, e_ub, e_uf, \ |
| 13 | 0, 0, 0, 0, 0, 0, 0, 0, \ | 13 | 0, 0, 0, 0, 0, 0, 0, 0, \ |
| 14 | c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr) | 14 | c_dbl, c_dfr, c_ubr, c_ufl, c_dbr, c_dfl, c_ubl, c_ufr) |
| 15 | #define zero _mm256_set_epi64x(0, 0, 0, 0) | 15 | #define ZERO_CUBE _mm256_set_epi64x(0, 0, 0, 0) |
| 16 | #define solved static_cube( \ | 16 | #define SOLVED_CUBE STATIC_CUBE( \ |
| 17 | 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) | 17 | 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) |
| 18 | 18 | ||
| 19 | STATIC void | 19 | STATIC void |
| @@ -43,11 +43,11 @@ invertco(cube_t c) | |||
| 43 | { | 43 | { |
| 44 | cube_t co, shleft, shright, summed, newco, cleanco, ret; | 44 | cube_t co, shleft, shright, summed, newco, cleanco, ret; |
| 45 | 45 | ||
| 46 | co = _mm256_and_si256(c, _co2_avx2); | 46 | co = _mm256_and_si256(c, CO2_AVX2); |
| 47 | shleft = _mm256_slli_epi32(co, 1); | 47 | shleft = _mm256_slli_epi32(co, 1); |
| 48 | shright = _mm256_srli_epi32(co, 1); | 48 | shright = _mm256_srli_epi32(co, 1); |
| 49 | summed = _mm256_or_si256(shleft, shright); | 49 | summed = _mm256_or_si256(shleft, shright); |
| 50 | newco = _mm256_and_si256(summed, _co2_avx2); | 50 | newco = _mm256_and_si256(summed, CO2_AVX2); |
| 51 | cleanco = _mm256_xor_si256(c, co); | 51 | cleanco = _mm256_xor_si256(c, co); |
| 52 | ret = _mm256_or_si256(cleanco, newco); | 52 | ret = _mm256_or_si256(cleanco, newco); |
| 53 | 53 | ||
| @@ -68,7 +68,7 @@ compose_epcpeo(cube_t c1, cube_t c2) | |||
| 68 | s = _mm256_andnot_si256(b, s); | 68 | s = _mm256_andnot_si256(b, s); |
| 69 | 69 | ||
| 70 | /* Change EO */ | 70 | /* Change EO */ |
| 71 | eo2 = _mm256_and_si256(c2, _eo_avx2); | 71 | eo2 = _mm256_and_si256(c2, EO_AVX2); |
| 72 | s = _mm256_xor_si256(s, eo2); | 72 | s = _mm256_xor_si256(s, eo2); |
| 73 | 73 | ||
| 74 | return s; | 74 | return s; |
| @@ -99,16 +99,16 @@ compose(cube_t c1, cube_t c2) | |||
| 99 | s = compose_epcpeo(c1, c2); | 99 | s = compose_epcpeo(c1, c2); |
| 100 | 100 | ||
| 101 | /* Change CO */ | 101 | /* Change CO */ |
| 102 | co1 = _mm256_and_si256(s, _co2_avx2); | 102 | co1 = _mm256_and_si256(s, CO2_AVX2); |
| 103 | co2 = _mm256_and_si256(c2, _co2_avx2); | 103 | co2 = _mm256_and_si256(c2, CO2_AVX2); |
| 104 | aux = _mm256_add_epi8(co1, co2); | 104 | aux = _mm256_add_epi8(co1, co2); |
| 105 | auy1 = _mm256_add_epi8(aux, _cocw_avx2); | 105 | auy1 = _mm256_add_epi8(aux, COCW_AVX2); |
| 106 | auy2 = _mm256_srli_epi32(auy1, 2); | 106 | auy2 = _mm256_srli_epi32(auy1, 2); |
| 107 | auz1 = _mm256_add_epi8(aux, auy2); | 107 | auz1 = _mm256_add_epi8(aux, auy2); |
| 108 | auz2 = _mm256_and_si256(auz1, _co2_avx2); | 108 | auz2 = _mm256_and_si256(auz1, CO2_AVX2); |
| 109 | 109 | ||
| 110 | /* Put together */ | 110 | /* Put together */ |
| 111 | s = _mm256_andnot_si256(_co2_avx2, s); | 111 | s = _mm256_andnot_si256(CO2_AVX2, s); |
| 112 | s = _mm256_or_si256(s, auz2); | 112 | s = _mm256_or_si256(s, auz2); |
| 113 | 113 | ||
| 114 | return s; | 114 | return s; |
| @@ -157,9 +157,9 @@ inverse(cube_t c) | |||
| 157 | vi = _mm256_shuffle_epi8(vi, vi); | 157 | vi = _mm256_shuffle_epi8(vi, vi); |
| 158 | vi = _mm256_shuffle_epi8(vi, c); | 158 | vi = _mm256_shuffle_epi8(vi, c); |
| 159 | 159 | ||
| 160 | vo = _mm256_and_si256(c, _mm256_or_si256(_eo_avx2, _co2_avx2)); | 160 | vo = _mm256_and_si256(c, _mm256_or_si256(EO_AVX2, CO2_AVX2)); |
| 161 | vo = _mm256_shuffle_epi8(vo, vi); | 161 | vo = _mm256_shuffle_epi8(vo, vi); |
| 162 | vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi); | 162 | vp = _mm256_andnot_si256(_mm256_or_si256(EO_AVX2, CO2_AVX2), vi); |
| 163 | ret = _mm256_or_si256(vp, vo); | 163 | ret = _mm256_or_si256(vp, vo); |
| 164 | ret = cleanaftershuffle(ret); | 164 | ret = cleanaftershuffle(ret); |
| 165 | 165 | ||
| @@ -172,7 +172,7 @@ coord_co(cube_t c) | |||
| 172 | cube_t co; | 172 | cube_t co; |
| 173 | int64_t mem[4], ret, i, p; | 173 | int64_t mem[4], ret, i, p; |
| 174 | 174 | ||
| 175 | co = _mm256_and_si256(c, _co2_avx2); | 175 | co = _mm256_and_si256(c, CO2_AVX2); |
| 176 | _mm256_storeu_si256((__m256i *)mem, co); | 176 | _mm256_storeu_si256((__m256i *)mem, co); |
| 177 | 177 | ||
| 178 | mem[0] >>= 5; | 178 | mem[0] >>= 5; |
| @@ -188,7 +188,7 @@ coord_csep(cube_t c) | |||
| 188 | cube_t cp, shifted; | 188 | cube_t cp, shifted; |
| 189 | int64_t mask; | 189 | int64_t mask; |
| 190 | 190 | ||
| 191 | cp = _mm256_and_si256(c, _cp_avx2); | 191 | cp = _mm256_and_si256(c, CP_AVX2); |
| 192 | shifted = _mm256_slli_epi32(cp, 5); | 192 | shifted = _mm256_slli_epi32(cp, 5); |
| 193 | mask = _mm256_movemask_epi8(shifted); | 193 | mask = _mm256_movemask_epi8(shifted); |
| 194 | 194 | ||
| @@ -207,7 +207,7 @@ coord_eo(cube_t c) | |||
| 207 | cube_t eo, shifted; | 207 | cube_t eo, shifted; |
| 208 | int64_t mask; | 208 | int64_t mask; |
| 209 | 209 | ||
| 210 | eo = _mm256_and_si256(c, _eo_avx2); | 210 | eo = _mm256_and_si256(c, EO_AVX2); |
| 211 | shifted = _mm256_slli_epi32(eo, 3); | 211 | shifted = _mm256_slli_epi32(eo, 3); |
| 212 | mask = _mm256_movemask_epi8(shifted); | 212 | mask = _mm256_movemask_epi8(shifted); |
| 213 | 213 | ||
| @@ -220,7 +220,7 @@ coord_esep(cube_t c) | |||
| 220 | cube_t ep; | 220 | cube_t ep; |
| 221 | int64_t e, mem[4], i, j, jj, k, l, ret1, ret2, bit1, bit2, is1; | 221 | int64_t e, mem[4], i, j, jj, k, l, ret1, ret2, bit1, bit2, is1; |
| 222 | 222 | ||
| 223 | ep = _mm256_and_si256(c, _ep_avx2); | 223 | ep = _mm256_and_si256(c, EP_AVX2); |
| 224 | _mm256_storeu_si256((__m256i *)mem, ep); | 224 | _mm256_storeu_si256((__m256i *)mem, ep); |
| 225 | 225 | ||
| 226 | mem[3] <<= 8; | 226 | mem[3] <<= 8; |
| @@ -278,7 +278,7 @@ set_eo(cube_t *cube, int64_t eo) | |||
| 278 | (eo12 & 1) << 4; | 278 | (eo12 & 1) << 4; |
| 279 | veo = _mm256_set_epi64x(eotop, eobot, 0, 0); | 279 | veo = _mm256_set_epi64x(eotop, eobot, 0, 0); |
| 280 | 280 | ||
| 281 | *cube = _mm256_andnot_si256(_eo_avx2, *cube); | 281 | *cube = _mm256_andnot_si256(EO_AVX2, *cube); |
| 282 | *cube = _mm256_or_si256(*cube, veo); | 282 | *cube = _mm256_or_si256(*cube, veo); |
| 283 | } | 283 | } |
| 284 | 284 | ||
| @@ -290,7 +290,7 @@ invcoord_esep(int64_t esep) | |||
| 290 | 290 | ||
| 291 | invcoord_esep_array(esep % 70, esep / 70, mem+16); | 291 | invcoord_esep_array(esep % 70, esep / 70, mem+16); |
| 292 | 292 | ||
| 293 | ret = solved; | 293 | ret = SOLVED_CUBE; |
| 294 | eee = _mm256_loadu_si256((__m256i_u *)&mem); | 294 | eee = _mm256_loadu_si256((__m256i_u *)&mem); |
| 295 | copy_edges(&ret, eee); | 295 | copy_edges(&ret, eee); |
| 296 | 296 | ||
diff --git a/src/arch/neon.h b/src/arch/neon.h index dee0eba..acb75c3 100644 --- a/src/arch/neon.h +++ b/src/arch/neon.h | |||
| @@ -1,21 +1,21 @@ | |||
| 1 | #define _co2_neon vdupq_n_u8(0x60) | 1 | #define CO2_NEON vdupq_n_u8(0x60) |
| 2 | #define _cocw_neon vdupq_n_u8(0x20) | 2 | #define COCW_NEON vdupq_n_u8(0x20) |
| 3 | #define _cp_neon vdupq_n_u8(0x07) | 3 | #define CP_NEON vdupq_n_u8(0x07) |
| 4 | #define _ep_neon vcombine_u8(vdupq_n_u8(0x0F), vdupq_n_u8(0x0F)) | 4 | #define EP_NEON vcombine_u8(vdupq_n_u8(0x0F), vdupq_n_u8(0x0F)) |
| 5 | #define _eo_neon vcombine_u8(vdupq_n_u8(0x10), vdupq_n_u8(0x10)) | 5 | #define EO_NEON vcombine_u8(vdupq_n_u8(0x10), vdupq_n_u8(0x10)) |
| 6 | 6 | ||
| 7 | STATIC_INLINE uint8x16_t compose_edges_slim(uint8x16_t, uint8x16_t); | 7 | STATIC_INLINE uint8x16_t compose_edges_slim(uint8x16_t, uint8x16_t); |
| 8 | STATIC_INLINE uint8x16_t compose_corners_slim(uint8x16_t, uint8x16_t); | 8 | STATIC_INLINE uint8x16_t compose_corners_slim(uint8x16_t, uint8x16_t); |
| 9 | 9 | ||
| 10 | // static cube | 10 | // static cube |
| 11 | #define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ | 11 | #define STATIC_CUBE(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ |
| 12 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ | 12 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ |
| 13 | ((cube_t){ \ | 13 | ((cube_t){ \ |
| 14 | .corner = {c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, 0, 0, 0, 0, 0, 0, 0, 0}, \ | 14 | .corner = {c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, 0, 0, 0, 0, 0, 0, 0, 0}, \ |
| 15 | .edge = {e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br, 0, 0, 0, 0}}) | 15 | .edge = {e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br, 0, 0, 0, 0}}) |
| 16 | 16 | ||
| 17 | // zero cube | 17 | // zero cube |
| 18 | #define zero \ | 18 | #define ZERO_CUBE \ |
| 19 | (cube_t) \ | 19 | (cube_t) \ |
| 20 | { \ | 20 | { \ |
| 21 | .corner = vdupq_n_u8(0), \ | 21 | .corner = vdupq_n_u8(0), \ |
| @@ -23,7 +23,7 @@ STATIC_INLINE uint8x16_t compose_corners_slim(uint8x16_t, uint8x16_t); | |||
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | // solved cube | 25 | // solved cube |
| 26 | #define solved static_cube( \ | 26 | #define SOLVED_CUBE STATIC_CUBE( \ |
| 27 | 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) | 27 | 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) |
| 28 | 28 | ||
| 29 | STATIC void | 29 | STATIC void |
| @@ -68,11 +68,11 @@ invertco(cube_t c) | |||
| 68 | cube_t ret; | 68 | cube_t ret; |
| 69 | uint8x16_t co, shleft, shright, summed, newco, cleanco; | 69 | uint8x16_t co, shleft, shright, summed, newco, cleanco; |
| 70 | 70 | ||
| 71 | co = vandq_u8(c.corner, _co2_neon); | 71 | co = vandq_u8(c.corner, CO2_NEON); |
| 72 | shleft = vshlq_n_u8(co, 1); | 72 | shleft = vshlq_n_u8(co, 1); |
| 73 | shright = vshrq_n_u8(co, 1); | 73 | shright = vshrq_n_u8(co, 1); |
| 74 | summed = vorrq_u8(shleft, shright); | 74 | summed = vorrq_u8(shleft, shright); |
| 75 | newco = vandq_u8(summed, _co2_neon); | 75 | newco = vandq_u8(summed, CO2_NEON); |
| 76 | cleanco = veorq_u8(c.corner, co); | 76 | cleanco = veorq_u8(c.corner, co); |
| 77 | ret.corner = vorrq_u8(cleanco, newco); | 77 | ret.corner = vorrq_u8(cleanco, newco); |
| 78 | ret.edge = c.edge; | 78 | ret.edge = c.edge; |
| @@ -323,7 +323,7 @@ invcoord_esep(int64_t esep) | |||
| 323 | 323 | ||
| 324 | invcoord_esep_array(esep % 70, esep / 70, mem); | 324 | invcoord_esep_array(esep % 70, esep / 70, mem); |
| 325 | 325 | ||
| 326 | ret = solved; | 326 | ret = SOLVED_CUBE; |
| 327 | ret.edge = vld1q_u8(mem); | 327 | ret.edge = vld1q_u8(mem); |
| 328 | 328 | ||
| 329 | return ret; | 329 | return ret; |
diff --git a/src/arch/portable.h b/src/arch/portable.h index fdadb02..e9a8dd0 100644 --- a/src/arch/portable.h +++ b/src/arch/portable.h | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | #define static_cube(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ | 1 | #define STATIC_CUBE(c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl, \ |
| 2 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ | 2 | e_uf, e_ub, e_db, e_df, e_ur, e_ul, e_dl, e_dr, e_fr, e_fl, e_bl, e_br) \ |
| 3 | ((cube_t) { \ | 3 | ((cube_t) { \ |
| 4 | .corner = { c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl }, \ | 4 | .corner = { c_ufr, c_ubl, c_dfl, c_dbr, c_ufl, c_ubr, c_dfr, c_dbl }, \ |
| 5 | .edge = { e_uf, e_ub, e_db, e_df, e_ur, e_ul, \ | 5 | .edge = { e_uf, e_ub, e_db, e_df, e_ur, e_ul, \ |
| 6 | e_dl, e_dr, e_fr, e_fl, e_bl, e_br } }) | 6 | e_dl, e_dr, e_fr, e_fl, e_bl, e_br } }) |
| 7 | #define zero static_cube( \ | 7 | #define ZERO_CUBE STATIC_CUBE( \ |
| 8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | 8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) |
| 9 | #define solved static_cube( \ | 9 | #define SOLVED_CUBE STATIC_CUBE( \ |
| 10 | 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) | 10 | 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) |
| 11 | 11 | ||
| 12 | STATIC void | 12 | STATIC void |
| @@ -80,7 +80,7 @@ compose_corners_inplace(cube_t c1, cube_t c2, cube_t *ret) | |||
| 80 | STATIC_INLINE cube_t | 80 | STATIC_INLINE cube_t |
| 81 | compose_edges(cube_t c1, cube_t c2) | 81 | compose_edges(cube_t c1, cube_t c2) |
| 82 | { | 82 | { |
| 83 | cube_t ret = zero; | 83 | cube_t ret = ZERO_CUBE; |
| 84 | 84 | ||
| 85 | compose_edges_inplace(c1, c2, &ret); | 85 | compose_edges_inplace(c1, c2, &ret); |
| 86 | 86 | ||
| @@ -90,7 +90,7 @@ compose_edges(cube_t c1, cube_t c2) | |||
| 90 | STATIC_INLINE cube_t | 90 | STATIC_INLINE cube_t |
| 91 | compose_corners(cube_t c1, cube_t c2) | 91 | compose_corners(cube_t c1, cube_t c2) |
| 92 | { | 92 | { |
| 93 | cube_t ret = zero; | 93 | cube_t ret = ZERO_CUBE; |
| 94 | 94 | ||
| 95 | compose_corners_inplace(c1, c2, &ret); | 95 | compose_corners_inplace(c1, c2, &ret); |
| 96 | 96 | ||
| @@ -100,7 +100,7 @@ compose_corners(cube_t c1, cube_t c2) | |||
| 100 | STATIC_INLINE cube_t | 100 | STATIC_INLINE cube_t |
| 101 | compose(cube_t c1, cube_t c2) | 101 | compose(cube_t c1, cube_t c2) |
| 102 | { | 102 | { |
| 103 | cube_t ret = zero; | 103 | cube_t ret = ZERO_CUBE; |
| 104 | 104 | ||
| 105 | compose_edges_inplace(c1, c2, &ret); | 105 | compose_edges_inplace(c1, c2, &ret); |
| 106 | compose_corners_inplace(c1, c2, &ret); | 106 | compose_corners_inplace(c1, c2, &ret); |
| @@ -244,7 +244,7 @@ invcoord_esep(int64_t esep) | |||
| 244 | { | 244 | { |
| 245 | cube_t ret; | 245 | cube_t ret; |
| 246 | 246 | ||
| 247 | ret = solved; | 247 | ret = SOLVED_CUBE; |
| 248 | invcoord_esep_array(esep % 70, esep / 70, ret.edge); | 248 | invcoord_esep_array(esep % 70, esep / 70, ret.edge); |
| 249 | 249 | ||
| 250 | return ret; | 250 | return ret; |
