-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cmd/internal/obj/x86: add AVX2 gather and VSIB
Enables AVX2 gather instructions and VSIB support, which makes vm32{x,y} vm64{x,y} operands encodable. AXXX constants placed with respect to sorting order. New VEX optabs inserted near non-VEX entries to simplify potential transition to auto-generated VSIB optabs. Tests go into new AMD64 encoder test file (amd64enc_extra.s) to avoid unnecessary interactions with auto-generated "amd64enc.s". Side note: x86avxgen did not produced these instructions because x86.v0.2.csv misses them. This also explains why x86 test suite have no AVX2 gather instructions tests. List of new instructions: VGATHERPDP VGATHERDPS VGATHERQPD VGATHERQPS VPGATHERDD VPGATHERDQ VPGATHERQD VPGATHERQQ Change-Id: Iac852f3c5016523670bd99de6bec6a48f66fb4f6 Reviewed-on: https://go-review.googlesource.com/77970 Run-TryBot: Iskander Sharipov <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ilya Tocar <[email protected]>
- Loading branch information
Showing
6 changed files
with
423 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
// Copyright 2017 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// This input extends auto-generated amd64enc.s test suite | ||
// with manually added tests. | ||
|
||
#include "../../../../../runtime/textflag.h" | ||
|
||
TEXT asmtest(SB),DUPOK|NOSPLIT,$0 | ||
// AVX2GATHER: basic combinations. | ||
VPGATHERDQ Y2, (BP)(X7*2), Y1 // c4e2ed904c7d00 | ||
VPGATHERDQ X12, (R13)(X14*2), X11 // c40299905c7500 | ||
VPGATHERDQ Y12, (R13)(X14*2), Y11 // c4029d905c7500 | ||
VPGATHERDQ Y0, 8(X4*1), Y6 // c4e2fd90342508000000 | ||
VPGATHERDQ Y0, -8(X4*1), Y6 // c4e2fd903425f8ffffff | ||
VPGATHERDQ Y0, 0(X4*1), Y6 // c4e2fd90342500000000 | ||
VPGATHERDQ Y0, 664(X4*1), Y6 // c4e2fd90342598020000 | ||
VPGATHERDQ Y0, 8(X4*8), Y6 // c4e2fd9034e508000000 | ||
VPGATHERDQ Y0, -8(X4*8), Y6 // c4e2fd9034e5f8ffffff | ||
VPGATHERDQ Y0, 0(X4*8), Y6 // c4e2fd9034e500000000 | ||
VPGATHERDQ Y0, 664(X4*8), Y6 // c4e2fd9034e598020000 | ||
VPGATHERDQ Y0, 8(X14*1), Y6 // c4a2fd90343508000000 | ||
VPGATHERDQ Y0, -8(X14*1), Y6 // c4a2fd903435f8ffffff | ||
VPGATHERDQ Y0, 0(X14*1), Y6 // c4a2fd90343500000000 | ||
VPGATHERDQ Y0, 664(X14*1), Y6 // c4a2fd90343598020000 | ||
VPGATHERDQ Y0, 8(X14*8), Y6 // c4a2fd9034f508000000 | ||
VPGATHERDQ Y0, -8(X14*8), Y6 // c4a2fd9034f5f8ffffff | ||
VPGATHERDQ Y0, 0(X14*8), Y6 // c4a2fd9034f500000000 | ||
VPGATHERDQ Y0, 664(X14*8), Y6 // c4a2fd9034f598020000 | ||
VPGATHERDQ X2, (BP)(X7*2), X1 // c4e2e9904c7d00 | ||
VPGATHERDQ Y2, (BP)(X7*2), Y1 // c4e2ed904c7d00 | ||
VPGATHERDQ X12, (R13)(X14*2), X11 // c40299905c7500 | ||
VPGATHERDQ Y12, (R13)(X14*2), Y11 // c4029d905c7500 | ||
VPGATHERDQ Y0, 8(X4*1), Y6 // c4e2fd90342508000000 | ||
VPGATHERDQ Y0, -8(X4*1), Y6 // c4e2fd903425f8ffffff | ||
VPGATHERDQ Y0, 0(X4*1), Y6 // c4e2fd90342500000000 | ||
VPGATHERDQ Y0, 664(X4*1), Y6 // c4e2fd90342598020000 | ||
VPGATHERDQ Y0, 8(X4*8), Y6 // c4e2fd9034e508000000 | ||
VPGATHERDQ Y0, -8(X4*8), Y6 // c4e2fd9034e5f8ffffff | ||
VPGATHERDQ Y0, 0(X4*8), Y6 // c4e2fd9034e500000000 | ||
VPGATHERDQ Y0, 664(X4*8), Y6 // c4e2fd9034e598020000 | ||
VPGATHERDQ Y0, 8(X14*1), Y6 // c4a2fd90343508000000 | ||
VPGATHERDQ Y0, -8(X14*1), Y6 // c4a2fd903435f8ffffff | ||
VPGATHERDQ Y0, 0(X14*1), Y6 // c4a2fd90343500000000 | ||
VPGATHERDQ Y0, 664(X14*1), Y6 // c4a2fd90343598020000 | ||
VPGATHERDQ Y0, 8(X14*8), Y6 // c4a2fd9034f508000000 | ||
VPGATHERDQ Y0, -8(X14*8), Y6 // c4a2fd9034f5f8ffffff | ||
VPGATHERDQ Y0, 0(X14*8), Y6 // c4a2fd9034f500000000 | ||
VPGATHERDQ Y0, 664(X14*8), Y6 // c4a2fd9034f598020000 | ||
VPGATHERQQ X2, (BP)(X7*2), X1 // c4e2e9914c7d00 | ||
VPGATHERQQ Y2, (BP)(Y7*2), Y1 // c4e2ed914c7d00 | ||
VPGATHERQQ X12, (R13)(X14*2), X11 // c40299915c7500 | ||
VPGATHERQQ Y12, (R13)(Y14*2), Y11 // c4029d915c7500 | ||
VPGATHERQQ X2, (BP)(X7*2), X1 // c4e2e9914c7d00 | ||
VPGATHERQQ Y2, (BP)(Y7*2), Y1 // c4e2ed914c7d00 | ||
VPGATHERQQ X12, (R13)(X14*2), X11 // c40299915c7500 | ||
VPGATHERQQ Y12, (R13)(Y14*2), Y11 // c4029d915c7500 | ||
VGATHERDPD X2, (BP)(X7*2), X1 // c4e2e9924c7d00 | ||
VGATHERDPD Y2, (BP)(X7*2), Y1 // c4e2ed924c7d00 | ||
VGATHERDPD X12, (R13)(X14*2), X11 // c40299925c7500 | ||
VGATHERDPD Y12, (R13)(X14*2), Y11 // c4029d925c7500 | ||
VGATHERDPD Y0, 8(X4*1), Y6 // c4e2fd92342508000000 | ||
VGATHERDPD Y0, -8(X4*1), Y6 // c4e2fd923425f8ffffff | ||
VGATHERDPD Y0, 0(X4*1), Y6 // c4e2fd92342500000000 | ||
VGATHERDPD Y0, 664(X4*1), Y6 // c4e2fd92342598020000 | ||
VGATHERDPD Y0, 8(X4*8), Y6 // c4e2fd9234e508000000 | ||
VGATHERDPD Y0, -8(X4*8), Y6 // c4e2fd9234e5f8ffffff | ||
VGATHERDPD Y0, 0(X4*8), Y6 // c4e2fd9234e500000000 | ||
VGATHERDPD Y0, 664(X4*8), Y6 // c4e2fd9234e598020000 | ||
VGATHERDPD Y0, 8(X14*1), Y6 // c4a2fd92343508000000 | ||
VGATHERDPD Y0, -8(X14*1), Y6 // c4a2fd923435f8ffffff | ||
VGATHERDPD Y0, 0(X14*1), Y6 // c4a2fd92343500000000 | ||
VGATHERDPD Y0, 664(X14*1), Y6 // c4a2fd92343598020000 | ||
VGATHERDPD Y0, 8(X14*8), Y6 // c4a2fd9234f508000000 | ||
VGATHERDPD Y0, -8(X14*8), Y6 // c4a2fd9234f5f8ffffff | ||
VGATHERDPD Y0, 0(X14*8), Y6 // c4a2fd9234f500000000 | ||
VGATHERDPD Y0, 664(X14*8), Y6 // c4a2fd9234f598020000 | ||
VGATHERDPD X2, (BP)(X7*2), X1 // c4e2e9924c7d00 | ||
VGATHERDPD Y2, (BP)(X7*2), Y1 // c4e2ed924c7d00 | ||
VGATHERDPD X12, (R13)(X14*2), X11 // c40299925c7500 | ||
VGATHERDPD Y12, (R13)(X14*2), Y11 // c4029d925c7500 | ||
VGATHERDPD Y0, 8(X4*1), Y6 // c4e2fd92342508000000 | ||
VGATHERDPD Y0, -8(X4*1), Y6 // c4e2fd923425f8ffffff | ||
VGATHERDPD Y0, 0(X4*1), Y6 // c4e2fd92342500000000 | ||
VGATHERDPD Y0, 664(X4*1), Y6 // c4e2fd92342598020000 | ||
VGATHERDPD Y0, 8(X4*8), Y6 // c4e2fd9234e508000000 | ||
VGATHERDPD Y0, -8(X4*8), Y6 // c4e2fd9234e5f8ffffff | ||
VGATHERDPD Y0, 0(X4*8), Y6 // c4e2fd9234e500000000 | ||
VGATHERDPD Y0, 664(X4*8), Y6 // c4e2fd9234e598020000 | ||
VGATHERDPD Y0, 8(X14*1), Y6 // c4a2fd92343508000000 | ||
VGATHERDPD Y0, -8(X14*1), Y6 // c4a2fd923435f8ffffff | ||
VGATHERDPD Y0, 0(X14*1), Y6 // c4a2fd92343500000000 | ||
VGATHERDPD Y0, 664(X14*1), Y6 // c4a2fd92343598020000 | ||
VGATHERDPD Y0, 8(X14*8), Y6 // c4a2fd9234f508000000 | ||
VGATHERDPD Y0, -8(X14*8), Y6 // c4a2fd9234f5f8ffffff | ||
VGATHERDPD Y0, 0(X14*8), Y6 // c4a2fd9234f500000000 | ||
VGATHERDPD Y0, 664(X14*8), Y6 // c4a2fd9234f598020000 | ||
VGATHERQPD X2, (BP)(X7*2), X1 // c4e2e9934c7d00 | ||
VGATHERQPD Y2, (BP)(Y7*2), Y1 // c4e2ed934c7d00 | ||
VGATHERQPD X12, (R13)(X14*2), X11 // c40299935c7500 | ||
VGATHERQPD Y12, (R13)(Y14*2), Y11 // c4029d935c7500 | ||
VGATHERQPD X2, (BP)(X7*2), X1 // c4e2e9934c7d00 | ||
VGATHERQPD Y2, (BP)(Y7*2), Y1 // c4e2ed934c7d00 | ||
VGATHERQPD X12, (R13)(X14*2), X11 // c40299935c7500 | ||
VGATHERQPD Y12, (R13)(Y14*2), Y11 // c4029d935c7500 | ||
VGATHERDPS X2, (BP)(X7*2), X1 // c4e269924c7d00 | ||
VGATHERDPS Y2, (BP)(Y7*2), Y1 // c4e26d924c7d00 | ||
VGATHERDPS X12, (R13)(X14*2), X11 // c40219925c7500 | ||
VGATHERDPS Y12, (R13)(Y14*2), Y11 // c4021d925c7500 | ||
VGATHERDPS X3, 8(X4*1), X6 // c4e26192342508000000 | ||
VGATHERDPS X3, -8(X4*1), X6 // c4e261923425f8ffffff | ||
VGATHERDPS X3, 0(X4*1), X6 // c4e26192342500000000 | ||
VGATHERDPS X3, 664(X4*1), X6 // c4e26192342598020000 | ||
VGATHERDPS X3, 8(X4*8), X6 // c4e2619234e508000000 | ||
VGATHERDPS X3, -8(X4*8), X6 // c4e2619234e5f8ffffff | ||
VGATHERDPS X3, 0(X4*8), X6 // c4e2619234e500000000 | ||
VGATHERDPS X3, 664(X4*8), X6 // c4e2619234e598020000 | ||
VGATHERDPS X3, 8(X14*1), X6 // c4a26192343508000000 | ||
VGATHERDPS X3, -8(X14*1), X6 // c4a261923435f8ffffff | ||
VGATHERDPS X3, 0(X14*1), X6 // c4a26192343500000000 | ||
VGATHERDPS X3, 664(X14*1), X6 // c4a26192343598020000 | ||
VGATHERDPS X3, 8(X14*8), X6 // c4a2619234f508000000 | ||
VGATHERDPS X3, -8(X14*8), X6 // c4a2619234f5f8ffffff | ||
VGATHERDPS X3, 0(X14*8), X6 // c4a2619234f500000000 | ||
VGATHERDPS X3, 664(X14*8), X6 // c4a2619234f598020000 | ||
VGATHERDPS X2, (BP)(X7*2), X1 // c4e269924c7d00 | ||
VGATHERDPS Y2, (BP)(Y7*2), Y1 // c4e26d924c7d00 | ||
VGATHERDPS X12, (R13)(X14*2), X11 // c40219925c7500 | ||
VGATHERDPS Y12, (R13)(Y14*2), Y11 // c4021d925c7500 | ||
VGATHERDPS X5, 8(X4*1), X6 // c4e25192342508000000 | ||
VGATHERDPS X3, -8(X4*1), X6 // c4e261923425f8ffffff | ||
VGATHERDPS X3, 0(X4*1), X6 // c4e26192342500000000 | ||
VGATHERDPS X3, 664(X4*1), X6 // c4e26192342598020000 | ||
VGATHERDPS X3, 8(X4*8), X6 // c4e2619234e508000000 | ||
VGATHERDPS X3, -8(X4*8), X6 // c4e2619234e5f8ffffff | ||
VGATHERDPS X3, 0(X4*8), X6 // c4e2619234e500000000 | ||
VGATHERDPS X3, 664(X4*8), X6 // c4e2619234e598020000 | ||
VGATHERDPS X3, 8(X14*1), X6 // c4a26192343508000000 | ||
VGATHERDPS X3, -8(X14*1), X6 // c4a261923435f8ffffff | ||
VGATHERDPS X3, 0(X14*1), X6 // c4a26192343500000000 | ||
VGATHERDPS X3, 664(X14*1), X6 // c4a26192343598020000 | ||
VGATHERDPS X3, 8(X14*8), X6 // c4a2619234f508000000 | ||
VGATHERDPS X3, -8(X14*8), X6 // c4a2619234f5f8ffffff | ||
VGATHERDPS X3, 0(X14*8), X6 // c4a2619234f500000000 | ||
VGATHERDPS X3, 664(X14*8), X6 // c4a2619234f598020000 | ||
VGATHERQPS X2, (BP)(X7*2), X1 // c4e269934c7d00 | ||
VGATHERQPS X2, (BP)(Y7*2), X1 // c4e26d934c7d00 | ||
VGATHERQPS X12, (R13)(X14*2), X11 // c40219935c7500 | ||
VGATHERQPS X12, (R13)(Y14*2), X11 // c4021d935c7500 | ||
VGATHERQPS X2, (BP)(X7*2), X1 // c4e269934c7d00 | ||
VGATHERQPS X2, (BP)(Y7*2), X1 // c4e26d934c7d00 | ||
VGATHERQPS X12, (R13)(X14*2), X11 // c40219935c7500 | ||
VGATHERQPS X12, (R13)(Y14*2), X11 // c4021d935c7500 | ||
VPGATHERDD X2, (BP)(X7*2), X1 // c4e269904c7d00 | ||
VPGATHERDD Y2, (BP)(Y7*2), Y1 // c4e26d904c7d00 | ||
VPGATHERDD X12, (R13)(X14*2), X11 // c40219905c7500 | ||
VPGATHERDD Y12, (R13)(Y14*2), Y11 // c4021d905c7500 | ||
VPGATHERDD X3, 8(X4*1), X6 // c4e26190342508000000 | ||
VPGATHERDD X3, -8(X4*1), X6 // c4e261903425f8ffffff | ||
VPGATHERDD X3, 0(X4*1), X6 // c4e26190342500000000 | ||
VPGATHERDD X3, 664(X4*1), X6 // c4e26190342598020000 | ||
VPGATHERDD X3, 8(X4*8), X6 // c4e2619034e508000000 | ||
VPGATHERDD X3, -8(X4*8), X6 // c4e2619034e5f8ffffff | ||
VPGATHERDD X3, 0(X4*8), X6 // c4e2619034e500000000 | ||
VPGATHERDD X3, 664(X4*8), X6 // c4e2619034e598020000 | ||
VPGATHERDD X3, 8(X14*1), X6 // c4a26190343508000000 | ||
VPGATHERDD X3, -8(X14*1), X6 // c4a261903435f8ffffff | ||
VPGATHERDD X3, 0(X14*1), X6 // c4a26190343500000000 | ||
VPGATHERDD X3, 664(X14*1), X6 // c4a26190343598020000 | ||
VPGATHERDD X3, 8(X14*8), X6 // c4a2619034f508000000 | ||
VPGATHERDD X3, -8(X14*8), X6 // c4a2619034f5f8ffffff | ||
VPGATHERDD X3, 0(X14*8), X6 // c4a2619034f500000000 | ||
VPGATHERDD X3, 664(X14*8), X6 // c4a2619034f598020000 | ||
VPGATHERDD X2, (BP)(X7*2), X1 // c4e269904c7d00 | ||
VPGATHERDD Y2, (BP)(Y7*2), Y1 // c4e26d904c7d00 | ||
VPGATHERDD X12, (R13)(X14*2), X11 // c40219905c7500 | ||
VPGATHERDD Y12, (R13)(Y14*2), Y11 // c4021d905c7500 | ||
VPGATHERDD X3, 8(X4*1), X6 // c4e26190342508000000 | ||
VPGATHERDD X3, -8(X4*1), X6 // c4e261903425f8ffffff | ||
VPGATHERDD X3, 0(X4*1), X6 // c4e26190342500000000 | ||
VPGATHERDD X3, 664(X4*1), X6 // c4e26190342598020000 | ||
VPGATHERDD X3, 8(X4*8), X6 // c4e2619034e508000000 | ||
VPGATHERDD X3, -8(X4*8), X6 // c4e2619034e5f8ffffff | ||
VPGATHERDD X3, 0(X4*8), X6 // c4e2619034e500000000 | ||
VPGATHERDD X3, 664(X4*8), X6 // c4e2619034e598020000 | ||
VPGATHERDD X3, 8(X14*1), X6 // c4a26190343508000000 | ||
VPGATHERDD X3, -8(X14*1), X6 // c4a261903435f8ffffff | ||
VPGATHERDD X3, 0(X14*1), X6 // c4a26190343500000000 | ||
VPGATHERDD X3, 664(X14*1), X6 // c4a26190343598020000 | ||
VPGATHERDD X3, 8(X14*8), X6 // c4a2619034f508000000 | ||
VPGATHERDD X3, -8(X14*8), X6 // c4a2619034f5f8ffffff | ||
VPGATHERDD X3, 0(X14*8), X6 // c4a2619034f500000000 | ||
VPGATHERDD X3, 664(X14*8), X6 // c4a2619034f598020000 | ||
VPGATHERQD X2, (BP)(X7*2), X1 // c4e269914c7d00 | ||
VPGATHERQD X2, (BP)(Y7*2), X1 // c4e26d914c7d00 | ||
VPGATHERQD X12, (R13)(X14*2), X11 // c40219915c7500 | ||
VPGATHERQD X12, (R13)(Y14*2), X11 // c4021d915c7500 | ||
VPGATHERQD X2, (BP)(X7*2), X1 // c4e269914c7d00 | ||
VPGATHERQD X2, (BP)(Y7*2), X1 // c4e26d914c7d00 | ||
VPGATHERQD X12, (R13)(X14*2), X11 // c40219915c7500 | ||
VPGATHERQD X12, (R13)(Y14*2), X11 // c4021d915c7500 | ||
VPGATHERQQ X0, 0(X1*1), X2 // c4e2f991140d00000000 | ||
VPGATHERQQ Y0, 0(Y1*1), Y2 // c4e2fd91140d00000000 | ||
VPGATHERQQ X8, 0(X9*1), X10 // c422b991140d00000000 | ||
VPGATHERQQ Y8, 0(Y9*1), Y10 // c422bd91140d00000000 | ||
VPGATHERQQ X0, 0(X1*4), X2 // c4e2f991148d00000000 | ||
VPGATHERQQ Y0, 0(Y1*4), Y2 // c4e2fd91148d00000000 | ||
VPGATHERQQ X8, 0(X9*4), X10 // c422b991148d00000000 | ||
VPGATHERQQ Y8, 0(Y9*4), Y10 // c422bd91148d00000000 | ||
// AVX2GATHER: test SP/BP base with different displacements. | ||
VPGATHERQQ X0, (SP)(X1*1), X2 // c4e2f991140c | ||
VPGATHERQQ X0, 16(SP)(X1*1), X2 // c4e2f991540c10 | ||
VPGATHERQQ X0, 512(SP)(X1*1), X2 // c4e2f991940c00020000 | ||
VPGATHERQQ X0, (R12)(X1*1), X2 // c4c2f991140c | ||
VPGATHERQQ X0, 16(R12)(X1*1), X2 // c4c2f991540c10 | ||
VPGATHERQQ X0, 512(R12)(X1*1), X2 // c4c2f991940c00020000 | ||
VPGATHERQQ X0, (BP)(X1*1), X2 // c4e2f991540d00 | ||
VPGATHERQQ X0, 16(BP)(X1*1), X2 // c4e2f991540d10 | ||
VPGATHERQQ X0, 512(BP)(X1*1), X2 // c4e2f991940d00020000 | ||
VPGATHERQQ X0, (R13)(X1*1), X2 // c4c2f991540d00 | ||
VPGATHERQQ X0, 16(R13)(X1*1), X2 // c4c2f991540d10 | ||
VPGATHERQQ X0, 512(R13)(X1*1), X2 // c4c2f991940d00020000 | ||
VPGATHERQQ Y0, (SP)(Y1*1), Y2 // c4e2fd91140c | ||
VPGATHERQQ Y0, 16(SP)(Y1*1), Y2 // c4e2fd91540c10 | ||
VPGATHERQQ Y0, 512(SP)(Y1*1), Y2 // c4e2fd91940c00020000 | ||
VPGATHERQQ Y0, (R12)(Y1*1), Y2 // c4c2fd91140c | ||
VPGATHERQQ Y0, 16(R12)(Y1*1), Y2 // c4c2fd91540c10 | ||
VPGATHERQQ Y0, 512(R12)(Y1*1), Y2 // c4c2fd91940c00020000 | ||
VPGATHERQQ Y0, (BP)(Y1*1), Y2 // c4e2fd91540d00 | ||
VPGATHERQQ Y0, 16(BP)(Y1*1), Y2 // c4e2fd91540d10 | ||
VPGATHERQQ Y0, 512(BP)(Y1*1), Y2 // c4e2fd91940d00020000 | ||
VPGATHERQQ Y0, (R13)(Y1*1), Y2 // c4c2fd91540d00 | ||
VPGATHERQQ Y0, 16(R13)(Y1*1), Y2 // c4c2fd91540d10 | ||
VPGATHERQQ Y0, 512(R13)(Y1*1), Y2 // c4c2fd91940d00020000 | ||
// End of tests. | ||
RET |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.