Advertisement
cr88192

TK C library extension, _memlzcpy

Oct 5th, 2022
851
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.22 KB | None | 0 0
  1. /*
  2. Just some stuff copy/pasted from my C library...
  3.  
  4. _memlzcpy: Perform an "LZ style" copy operation.
  5. Non-overlapping cases will copy the memory "as usual".
  6. Backwards copies will behave like memmove.
  7. Short forwards copies will generate a repeating pattern of bytes.
  8.  
  9. _memlzcpyf: Faster version, gains some speed by allowing the copy to "run past the end" by a small amount.
  10.  
  11. Tries to avoid byte-for-byte copy, because this is slow...
  12.  
  13. _memset16 / _memset32 / _memset64: Fill a block of memory with a 16/32/64 bit quantity.
  14.  
  15. This omits the code for "normal" memcpy and memset (this involves a bit more ASM).
  16.  
  17. Note regarding the significant abuse of pointers:
  18. The target in question (BJX2) allows fully unaligned access for 16/32/64 bit values;
  19. Also the compiler does not do "Strict Aliasing" / TBAA by default.
  20.  
  21. I "could" fix this up some (using get/set wrappers/intrinsics), but it is "as it is" for the time being.
  22.  */
  23.  
  24. #if 1
  25. uint8_t *MemLzCpy_MatchCopy2(uint8_t *dst, long sz, long d)
  26. {
  27.     uint8_t *cs, *ct, *cte;
  28.     uint64_t *ctl, *csl;
  29.     uint64_t v, v0, v1, v2, v3;
  30.     int step;
  31.    
  32.     if(d<8)
  33.     {
  34.         if(d==1)
  35.         {
  36.             v=*(dst-d);
  37.             v=v|(v<<8);
  38.             v=v|(v<<16);
  39.             v=v|(v<<32);
  40.             step=8;
  41.         }else
  42.             if(d==2)
  43.         {
  44.             v=*(uint16_t *)(dst-d);
  45.             v=v|(v<<16);
  46.             v=v|(v<<32);
  47.             step=8;
  48.         }else
  49.             if(d==4)
  50.         {
  51.             v=*(uint32_t *)(dst-d);
  52.             v=v|(v<<32);
  53.             step=8;
  54.         }else
  55.             if(d==8)
  56.         {
  57.             v=*(uint64_t *)(dst-d);
  58.             step=8;
  59.         }else
  60.         {
  61.             v=*(uint64_t *)(dst-d);
  62.             step=d;
  63.             if(step<=4)
  64.             {
  65.                 *(uint64_t *)dst=v;
  66.                 v=*(uint64_t *)(dst-d);
  67.                 step+=step;
  68.             }
  69.         }
  70.  
  71.         ct=dst; cte=dst+sz;
  72.         if(step==8)
  73.         {
  74. #if 1
  75.             while((ct+64)<cte)
  76.             {
  77.                 ctl=(uint64_t *)ct;
  78.                 ctl[0]=v;   ctl[1]=v;
  79.                 ctl[2]=v;   ctl[3]=v;
  80.                 ctl[4]=v;   ctl[5]=v;
  81.                 ctl[6]=v;   ctl[7]=v;
  82.                 ct+=64;
  83.             }
  84. #endif
  85.  
  86.             while(ct<cte)
  87.             {
  88.                 *(uint64_t *)ct=v;
  89.                 ct+=8;
  90.             }
  91.         }else
  92.         {
  93. #if 1
  94.             while((ct+64)<cte)
  95.             {
  96.                 *(uint64_t *)ct=v;  ct+=step;
  97.                 *(uint64_t *)ct=v;  ct+=step;
  98.                 *(uint64_t *)ct=v;  ct+=step;
  99.                 *(uint64_t *)ct=v;  ct+=step;
  100.                 *(uint64_t *)ct=v;  ct+=step;
  101.                 *(uint64_t *)ct=v;  ct+=step;
  102.             }
  103. #endif
  104.  
  105.             while(ct<cte)
  106.             {
  107.                 *(uint64_t *)ct=v;
  108.                 ct+=step;
  109.             }
  110.         }
  111.     }else
  112.         if(sz<=16)
  113.     {
  114.         cs=dst-d;
  115.         ((uint64_t *)dst)[0]=((uint64_t *)cs)[0];
  116.         ((uint64_t *)dst)[1]=((uint64_t *)cs)[1];
  117.         ct=dst+16;
  118.     }else
  119.         if(sz<=32)
  120.     {
  121.         cs=dst-d;
  122.         ((uint64_t *)dst)[0]=((uint64_t *)cs)[0];
  123.         ((uint64_t *)dst)[1]=((uint64_t *)cs)[1];
  124.         ((uint64_t *)dst)[2]=((uint64_t *)cs)[2];
  125.         ((uint64_t *)dst)[3]=((uint64_t *)cs)[3];
  126.         ct=dst+32;
  127.     }else
  128.         if(d<32)
  129. //      if(1)
  130.     {
  131.         cs=dst-d;
  132.         ct=dst; cte=dst+sz;
  133.  
  134. #if 1
  135.         while((ct+64)<cte)
  136.         {
  137.             csl=(uint64_t *)cs;
  138.             ctl=(uint64_t *)ct;
  139.             ctl[0]=csl[0];  ctl[1]=csl[1];
  140.             ctl[2]=csl[2];  ctl[3]=csl[3];
  141.             ctl[4]=csl[4];  ctl[5]=csl[5];
  142.             ctl[6]=csl[6];  ctl[7]=csl[7];
  143.             ct+=64; cs+=64;
  144.         }
  145. #endif
  146.  
  147.         while(ct<cte)
  148.         {
  149.             ((uint64_t *)ct)[0]=((uint64_t *)cs)[0];
  150.             ((uint64_t *)ct)[1]=((uint64_t *)cs)[1];
  151.             ct+=16; cs+=16;
  152.         }
  153.     }else
  154.     {
  155.         cs=dst-d;
  156.         ct=dst; cte=dst+sz;
  157.  
  158.         while((ct+64)<cte)
  159.         {
  160.             csl=(uint64_t *)cs;
  161.             ctl=(uint64_t *)ct;
  162.            
  163.             v0=csl[0];  v1=csl[1];
  164.             v2=csl[2];  v3=csl[3];
  165.             ctl[0]=v0;  ctl[1]=v1;
  166.             ctl[2]=v2;  ctl[3]=v3;
  167.  
  168.             v0=csl[4];  v1=csl[5];
  169.             v2=csl[6];  v3=csl[7];
  170.             ctl[4]=v0;  ctl[5]=v1;
  171.             ctl[6]=v2;  ctl[7]=v3;
  172.            
  173.             ct+=64; cs+=64;
  174.         }
  175.  
  176.         while(ct<cte)
  177.         {
  178.             v0=((uint64_t *)cs)[0]; v1=((uint64_t *)cs)[1];
  179.             ((uint64_t *)ct)[0]=v0; ((uint64_t *)ct)[1]=v1;
  180.             ct+=16; cs+=16;
  181.         }
  182.     }
  183.     return(ct);
  184. }
  185.  
  186. uint8_t *MemLzCpy_MatchCopy2S(uint8_t *dst, long sz, long d)
  187. {
  188.     uint8_t *cs, *ct, *cte;
  189.  
  190.     cs=dst-d;
  191.     ct=dst; cte=dst+sz;
  192.  
  193.     while((ct+4)<=cte)
  194.     {   *ct++=*cs++;    *ct++=*cs++;
  195.         *ct++=*cs++;    *ct++=*cs++;    }
  196.  
  197.     while(ct<cte)
  198.         { *ct++=*cs++; }
  199.     return(ct);
  200. }
  201.  
  202. #endif
  203.  
  204. #if 1
  205. /** Do an "LZ style" copy.
  206.   * This version will copy an exact number of bytes.
  207.   */
  208. void *_memlzcpy(void *dst, void *src, size_t n)
  209. {
  210.     void *ct1, *cte;
  211.     long d, b, n1, n1f;
  212.    
  213.     cte=((uint8_t *)dst)+n;
  214.     d=((char *)dst)-((char *)src);
  215.     if(d<=0)
  216.     {
  217.         /* Copying backwards, use normal copy. */
  218.         if((-d)>=n)
  219.             { memcpy(dst, src, n); }
  220.         else if(d!=0)
  221.             { memmove(dst, src, n); }
  222.     }else if(d>=n)
  223.     {
  224.         /* No overlap, use memcpy. */
  225.         memcpy(dst, src, n);
  226.     }else
  227.     {
  228.         b=(long)src;
  229.         if((d<=8) && !(b&15) && !(n&15))
  230.         {
  231.             /* If aligned, try to turn it into a memset. */
  232.             if(d==1)
  233.             {
  234.                 memset(src, *(uint8_t *)src, n+1);
  235.                 return(cte);
  236.             }else
  237.                 if(d==2)
  238.             {
  239.                 _memset16(src, *(uint16_t *)(src), (n+3)>>1);
  240.                 return(cte);
  241.             }
  242.             else
  243.                 if(d==4)
  244.             {
  245.                 _memset32(src, *(uint32_t *)(src), (n+7)>>2);
  246.                 return(cte);
  247.             }else
  248.                 if(d==8)
  249.             {
  250.                 _memset64(src, *(uint64_t *)(src), (n+15)>>3);
  251.                 return(cte);
  252.             }
  253.         }
  254.  
  255.         if(1)
  256.         {
  257.             n1=n&(~15);
  258.            
  259.             if((d<8) && (d&(d-1)))
  260.             {
  261.                 /* NPOT step, so use relative margin. */
  262.                 n1=n-16;
  263.                 if(n1<0)
  264.                     n1=0;
  265.             }
  266.  
  267.             ct1=dst;
  268.  
  269.             if(n1>0)
  270.             {
  271.                 /* Copy bulk portion. */
  272.                 ct1=MemLzCpy_MatchCopy2(dst, n1, d);
  273.             }
  274.  
  275. //          n1f=n-(((char *)ct1)-((char *)dst));
  276.             n1f=cte-ct1;
  277.            
  278. //          if(n1f<0)
  279. //              { __debugbreak(); }
  280.            
  281.             if(n1f>0)
  282.             {
  283.                 /* Copy remainder, safer byte-for-byte copy. */
  284.                 ct1=MemLzCpy_MatchCopy2S(ct1, n1f, d);
  285.             }
  286.             return(cte);
  287.         }
  288.     }
  289.     return(cte);
  290. }
  291.  
  292. /** Do an "LZ style" copy.
  293.   * Fast version may run past the end by a small amoumt.
  294.   */
  295. void *_memlzcpyf(void *dst, void *src, size_t n)
  296. {
  297.     void *cte;
  298.     uint64_t v0, v1;
  299.     long d, b;
  300.    
  301.     cte=((uint8_t *)dst)+n;
  302.     d=((char *)dst)-((char *)src);
  303.     if(d<=0)
  304.     {
  305.         /* Copying backwards, use normal copy. */
  306.         if(n<=16)
  307.         {
  308.             /* Small copy. */
  309.             v0=((uint64_t *)src)[0];
  310.             v1=((uint64_t *)src)[1];
  311.             ((uint64_t *)dst)[0]=v0;
  312.             ((uint64_t *)dst)[1]=v1;
  313.         }else
  314.             if((-d)>=n)
  315.         {
  316.             memcpy(dst, src, n);
  317.         }
  318.         else if(d!=0)
  319.         {
  320.             memmove(dst, src, n);
  321.         }
  322.     }else if(d>=n)
  323.     {
  324.         /* No overlap, use memcpy. */
  325.         if(n<=16)
  326.         {
  327.             /* Small copy. */
  328.             v0=((uint64_t *)src)[0];
  329.             v1=((uint64_t *)src)[1];
  330.             ((uint64_t *)dst)[0]=v0;
  331.             ((uint64_t *)dst)[1]=v1;
  332.         }else
  333.         {
  334.             memcpy(dst, src, n);
  335.         }
  336.     }else
  337.     {
  338.         b=(long)src;
  339. //      if(d<8)
  340. //      if((d<8) && !(b&15))
  341.         if((d<=8) && !(b&15) && !(n&15))
  342. //      if(0)
  343.         {
  344.             /* If aligned, try to turn it into a memset. */
  345.             if(d==1)
  346.             {
  347.                 memset(src, *(uint8_t *)src, n+1);
  348. //              return(cte);
  349.             }else
  350. #if 1
  351.                 if(d==2)
  352.             {
  353.                 _memset16(src, *(uint16_t *)(src), (n+3)>>1);
  354. //              return(cte);
  355.             }
  356.             else
  357. #endif
  358. #if 1
  359.                 if(d==4)
  360.             {
  361.                 _memset32(src, *(uint32_t *)(src), (n+7)>>2);
  362.             }else
  363. #endif
  364. #if 1
  365.                 if(d==8)
  366.             {
  367.                 _memset64(src, *(uint64_t *)(src), (n+15)>>3);
  368.             }else
  369. #endif
  370.             {
  371.                 MemLzCpy_MatchCopy2(dst, n, d);
  372.             }
  373.         }else
  374.         {
  375.             MemLzCpy_MatchCopy2(dst, n, d);
  376.         }
  377.     }
  378.     return(cte);
  379. }
  380. #endif
  381.  
  382. #if 1
  383. int _memlzcmp(void *dst, void *src, size_t n)
  384. {
  385.     uint8_t *cs, *ct, *cse;
  386.    
  387.     cs=src;
  388.     ct=dst;
  389.     cse=cs+n;
  390.    
  391.     while((cs+8)<=cse)
  392.     {
  393.         if((*(uint64_t *)cs)!=(*(uint64_t *)ct))
  394.             break;
  395.         cs+=8;  ct+=8;
  396.     }
  397.  
  398.     while(cs<cse)
  399.     {
  400.         if(*cs!=*ct)
  401.             break;
  402.         cs++;   ct++;
  403.     }
  404.     return(cs-((uint8_t *)src));
  405. }
  406. #endif
  407.  
  408.  
  409. #if defined(__BJX2__) && !defined(__ADDR_X96__)
  410. // #if 0
  411. void memset_movx(void *s, int c, size_t n);
  412. void memset_filx(void *s, uint64_t c, size_t n);
  413.  
  414. __asm {
  415. memset_movx:
  416.  
  417. .ifarch bjx2_movx
  418.     PSHUF.B     R5, 0, R7
  419.     PSHUF.W     R7, 0, R20
  420.     MOV     R20, R22    |   MOV     R20, R23
  421.     MOV     R20, R21    |   CMPGT   32, R6
  422.     BF      .L1
  423.     .L0:
  424.     MOV.X   R20, (R4,  0)
  425.     ADD     -32, R6
  426.     MOV.X   R22, (R4, 16)
  427.     ADD     32, R4      |   CMPGT   32, R6
  428.     BT      .L0
  429.     .L1:
  430. .else
  431.     EXTU.B      R5, R20
  432.     SHLD.Q      R5, 8, R7
  433.     OR          R7, R20
  434.     SHLD.Q      R5, 16, R7
  435.     OR          R7, R20
  436.     SHLD.Q      R5, 32, R7
  437.     OR          R7, R20
  438. .endif
  439.  
  440. .ifarch bjx2_wex
  441.     CMPGE   8, R6
  442.     BF      .L3
  443.     .L2:
  444.     ADD     -8, R6      |   MOV.Q   R20, (R4)
  445.     ADD     8, R4       |   CMPGE   8, R6
  446.     BT      .L2
  447.     .L3:
  448. .else
  449.     CMPGE   8, R6
  450.     BF      .L3
  451.     .L2:
  452.     ADD     -8, R6
  453.     MOV.Q   R20, (R4)
  454.     ADD     8, R4
  455.     CMPGE   8, R6
  456.     BT      .L2
  457.     .L3:
  458. .endif
  459.  
  460.     RTSU
  461.  
  462.  
  463. memset_filx:
  464.  
  465. .ifarch bjx2_movx
  466.     MOV     R5,  R20
  467.     MOV     R20, R22    |   MOV     R20, R23
  468.     MOV     R20, R21    |   CMPGT   32, R6
  469.     BF      .L1
  470.     .L0:
  471.     MOV.X   R20, (R4,  0)
  472.     ADD     -32, R6
  473.     MOV.X   R22, (R4, 16)
  474.     ADD     32, R4      |   CMPGT   32, R6
  475.     BT      .L0
  476.     .L1:
  477. .else
  478.     MOV     R5,  R20
  479. .endif
  480.  
  481. .ifarch bjx2_wex
  482.     CMPGE   8, R6
  483.     BF      .L3
  484.     .L2:
  485.     ADD     -8, R6      |   MOV.Q   R20, (R4)
  486.     ADD     8, R4       |   CMPGE   8, R6
  487.     BT      .L2
  488.     .L3:
  489. .else
  490.     CMPGE   8, R6
  491.     BF      .L3
  492.     .L2:
  493.     ADD     -8, R6
  494.     MOV.Q   R20, (R4)
  495.     ADD     8, R4
  496.     CMPGE   8, R6
  497.     BT      .L2
  498.     .L3:
  499. .endif
  500.  
  501.     RTSU
  502. }
  503. #endif
  504.  
  505. __PDPCLIB_API__ void *_memset64(void *s, uint64_t v, size_t n)
  506. {
  507.     uint64_t *ct, *cte, *cte0;
  508.     uint64_t v1;
  509.     int a, n1;
  510.  
  511. #if defined(__BJX2__) && !defined(__ADDR_X96__)
  512.     n1=n<<3;
  513.     a=(int)(((long)s)|n1);
  514.     if(!(a&15))
  515.     {
  516.         memset_filx(s, v, n1);
  517.         return(s);
  518.     }
  519. #endif
  520.  
  521.     ct=s; cte=ct+n;
  522.     while((ct+8)<=cte)
  523.     {
  524.         ct[0]=v;    ct[1]=v;
  525.         ct[2]=v;    ct[3]=v;
  526.         ct[4]=v;    ct[5]=v;
  527.         ct[6]=v;    ct[7]=v;
  528.         ct+=8;
  529.     }
  530.  
  531.     while(ct<cte)
  532.         { *ct++=v; }
  533.     return(s);
  534. }
  535.  
  536. __PDPCLIB_API__ void *_memset32(void *s, uint32_t v, size_t n)
  537. {
  538.     uint32_t *ct, *cte, *cte0;
  539.     uint64_t v1;
  540.     int a, n1;
  541.  
  542.     v1=(((uint64_t)v)<<32)|(v);
  543.  
  544. #if 1
  545. #if defined(__BJX2__) && !defined(__ADDR_X96__)
  546.     n1=n<<2;
  547.     a=(int)(((long)s)|n1);
  548.     if(!(a&15))
  549.     {
  550.         memset_filx(s, v1, n1);
  551.         return(s);
  552.     }
  553. #endif
  554.  
  555.     if(!(n&1))
  556.     {
  557.         return(_memset64(s, v1, n>>1));
  558.     }
  559. #endif
  560.  
  561.     ct=s; cte=ct+n;
  562.  
  563. #if 1
  564.     while((ct+8)<=cte)
  565.     {
  566.         ((uint64_t *)ct)[0]=v1;
  567.         ((uint64_t *)ct)[1]=v1;
  568.         ((uint64_t *)ct)[2]=v1;
  569.         ((uint64_t *)ct)[3]=v1;
  570.         ct+=8;
  571.     }
  572. #endif
  573.  
  574.     while(ct<cte)
  575.         { *ct++=v; }
  576.     return(s);
  577. }
  578.  
  579. __PDPCLIB_API__ void *_memset16(void *s, uint16_t v, size_t n)
  580. {
  581.     uint16_t *ct, *cte, *cte0;
  582.     uint64_t *ctl;
  583.     uint64_t v1;
  584.     int a, n1;
  585.  
  586.     v1=(((uint64_t)v)<<16)|(v);
  587.     v1=(v1<<32)|v1;
  588.  
  589. #if 1
  590. #if defined(__BJX2__) && !defined(__ADDR_X96__)
  591.     n1=n<<1;
  592.     a=(int)(((long)s)|n1);
  593.     if(!(a&15))
  594.     {
  595.         memset_filx(s, v1, n1);
  596.         return(s);
  597.     }
  598. #endif
  599.  
  600.     if(!(n&1))
  601.     {
  602.         return(_memset32(s, v1, n>>1));
  603.     }
  604. #endif
  605.  
  606.     ct=s; cte=ct+n;
  607.  
  608. #if 1
  609.     while((ct+16)<=cte)
  610.     {
  611.         ctl=(uint64_t *)ct;
  612.         ctl[0]=v1;  ctl[1]=v1;
  613.         ctl[2]=v1;  ctl[3]=v1;
  614.         ct+=16;
  615.     }
  616. #endif
  617.  
  618.     while(ct<cte)
  619.         { *ct++=v; }
  620.     return(s);
  621. }
  622.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement