home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / intrin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  19.9 KB  |  702 lines

  1. #include "c.h"
  2. enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };
  3.  
  4. typedef struct tagIntrinsics {
  5.     char *Name;
  6.     short NrOfArgs;
  7.     short Flags;
  8.     void (*fn)(Node p);
  9.     Symbol (*argsFn)(Node p);
  10. } INTRINSICS;
  11. //static Symbol Arg0,Arg1;
  12. static Node ArgumentsTab[10];
  13. static int ArgumentsNts[10];
  14. static int ArgumentsIndex;
  15. static int labelIdx=1;
  16. extern unsigned (*emitter)(Node, int);
  17. extern Symbol intreg[];
  18. static void fsincos(Node p)
  19. {
  20.     if (p->x.nestedCall) {
  21.         print("\tfldl\t(%%esp)\n\tfsincos\n\taddl\t$8,%%esp\n\tpop\t%%eax\n");
  22.         print("\tfstpl\t(%%eax");
  23.     }
  24.     else {
  25.         print("\tfsincos\n\tfstpl\t(%%eax");
  26.     }
  27.     print(")\n");
  28. }
  29.  
  30. static void bswap(Node p)    {    print("\tbswap\t%%eax\n");        }
  31. static void carry(Node p)    {    print("\tsbb\t%%eax,%%eax\n");    }
  32. static void bsf(Node p)        {    print("\tbsf\t%%eax,%%eax\n");    }
  33. static void bsr(Node p)        {    print("\tbsr\t%%eax,%%eax\n");    }
  34.  
  35. static Symbol bswapArgs(Node p)
  36. {
  37.     return intreg[EAX];
  38. }
  39.  
  40. static void fistp(Node p)
  41. {
  42.     print("\tpushl\t%%eax\n");
  43.     print("\tfistps\t(%%esp)\n\tpopl\t%%eax\n");
  44. }
  45. static void fbld(Node p)
  46. {
  47.     print("\tfbld\t(%%eax)\n");
  48. }
  49. static void Fabs(Node p)    {    print("\tfabs\n");    }
  50. static void fldpi(Node p)    {    print("\tfldpi\n");    }
  51. static void fldl2e(Node p)    {    print("\tfldl2e\n");}
  52. static void fldlg2(Node p)    {    print("\tfldlg2\n");}
  53. static void fldln2(Node p)    {    print("\tfldln2\n");}
  54. static void f2xm1(Node p)    {    print("\tf2xm1\n");    }
  55. static void popNestedCall(Node p)
  56. {
  57.     if (p->x.nestedCall) {
  58.         print("\tpopl\t%%eax\n\tpopl\t%%edx\n\tpopl\t%%ecx\n");
  59.     }
  60. }
  61.  
  62. static void mmxVectCallN(Node p,char *op,int negate)
  63. {
  64.     popNestedCall(p);
  65.     print("\torl\t%%ecx,%%ecx\n\tje\t_$LM%d\n",labelIdx+1);
  66.     if (negate) {
  67.         print("\tpcmpeqb\t%%mm2,%%mm2\n");
  68.     }
  69.     print("_$LM%d:\n",labelIdx);
  70.     print("\tdecl\t%%ecx\n");
  71.     print("\tmovq\t(%%edx,%%ecx,8),%%mm0\n");
  72.     if (op) {
  73.         print("\t");
  74.         outs(op);
  75.         print("\t(%%eax,%%ecx,8),%%mm0\n");
  76.         if (negate) {
  77.             print("\tpxor\t%%mm2,%%mm0\n");
  78.         }
  79.  
  80.     }
  81.     print("\tmovq\t%%mm0,(%%eax,%%ecx,8)\n");
  82.     print("\tjne\t_$LM%d\n",labelIdx);
  83.     print("_$LM%d:\n",labelIdx+1);
  84.     labelIdx += 2;
  85. }
  86. static void mmxVectCall(Node p,char *op)
  87. {
  88.     mmxVectCallN(p,op,0);
  89. }
  90. static void rdtsc(Node p)
  91. {
  92.     print("\trdtsc\n");
  93. }
  94.  
  95. static void mmxImmCallN(Node p,char *op,int negate)
  96. {
  97.     popNestedCall(p);
  98.     print("\torl\t%%ecx,%%ecx\n\tje\t_$LM%d\n",labelIdx+1);
  99.     print("\tmovq\t(%%edx),%%mm1\n");
  100.     if (negate) {
  101.         print("\tpcmpeqb\t%%mm2,%%mm2\n");
  102.     }
  103.     print("_$LM%d:\n",labelIdx);
  104.     print("\tdecl\t%%ecx\n");
  105.     print("\tmovq\t%%mm1,%%mm0\n\t");
  106.     outs(op);
  107.     print("\t(%%eax,%%ecx,8),%%mm0\n");
  108.     if (negate) {
  109.         print("\tpxor\t%%mm2,%%mm0\n");
  110.     }
  111.     print("\tmovq\t%%mm0,(%%eax,%%ecx,8)\n");
  112.     print("\tjne\t_$LM%d\n",labelIdx);
  113.     print("_$LM%d:\n",labelIdx+1);
  114.     labelIdx += 2;
  115. }
  116.  
  117. static void reduceCall(Node p,char *op,int negate)
  118. {
  119.     if (p->x.nestedCall) {
  120.         if (op == NULL)
  121.             print("\tpopl\t%%eax\n\tpopl\t%%ecx\n");
  122.         else
  123.             popNestedCall(p);
  124.     }
  125.     if (op) {
  126.         print("\tmovq\t(%%edx),%%mm4\n");
  127.     }
  128.     print("\tmovl\t$0x01010101,%%edx\n\tpushl\t%%edx\n\tpushl\t%%edx\n");
  129.     print("\tmovq\t(%%esp),%%mm1\n\txor\t%%edx,%%edx\n");
  130.     print("\tmovb\t$0xFF,%%dl\n\tpushl\t%%edx\n\tpushl\t%%edx\n");
  131.     print("\tmovq\t(%%esp),%%mm2\n\tpxor\t%%mm7,%%mm7\n\taddl\t$16,%%esp\n");
  132.     print("\torl\t%%ecx,%%ecx\n\tje\t_$LM%d\n",labelIdx+1);
  133.     if (negate) {
  134.         print("\tpcmpeqb\t%%mm5,%%mm5\n");
  135.     }
  136.     print("_$LM%d:\n",labelIdx);
  137.     print("\tdecl\t%%ecx\n");
  138.     print("\tmovq\t(%%eax,%%ecx,8),%%mm0\n");
  139.     if (op) {
  140.         print("\t");
  141.         outs(op);
  142.         print("\t%%mm4,%%mm0\n");
  143.     }
  144.     if (negate) {
  145.         print("\tpandn\t%%mm5,%%mm0\n");
  146.     }
  147.     print("\tpand\t%%mm1,%%mm0\n");
  148.     print("\tmovq\t%%mm0,%%mm3\n");
  149.  
  150.     print("\tpsrlq\t$8,%%mm3\n");
  151.     print("\tpaddb\t%%mm3,%%mm0\n");
  152.  
  153.     print("\tpsrlq\t$8,%%mm3\n");
  154.     print("\tpaddb\t%%mm3,%%mm0\n");
  155.  
  156.     print("\tpsrlq\t$8,%%mm3\n");
  157.     print("\tpaddb\t%%mm3,%%mm0\n");
  158.  
  159.     print("\tpand\t%%mm2,%%mm0\n");
  160.     print("\tpaddd\t%%mm0,%%mm7\n");
  161.     print("\tjne\t_$LM%d\n",labelIdx);
  162.     print("_$LM%d:\n\tmovd\t%%mm7,%%eax\n",labelIdx+1);
  163.     print("\tpsrlq\t$32,%%mm7\n\tmovd\t%%mm7,%%ecx\n\taddl\t%%ecx,%%eax\n");
  164.     labelIdx += 2;
  165. }
  166.  
  167. static void mmxImmCall(Node p,char *op)
  168. {
  169.     mmxImmCallN(p,op,0);
  170. }
  171.  
  172. static Symbol paddArgs(Node p)
  173. {
  174.     Symbol r=NULL;
  175.  
  176.     FunctionInfo.mmxCalls = 1;
  177.     switch (ArgumentsIndex) {
  178.     case 0:
  179.         if (p->x.nestedCall == 0) {
  180.             r = intreg[ECX];
  181.             p->kids[0]->syms[2] = r;
  182.         }
  183.         break;
  184.     case 1:
  185.         if (p->x.nestedCall == 0) {
  186.             r = intreg[EDX];
  187.             p->kids[0]->syms[2] = r;
  188.         }
  189.         break;
  190.     case 2:
  191.         if (p->x.nestedCall == 0) {
  192.             r = intreg[EAX];
  193.             p->kids[0]->syms[2] = r;
  194.         }
  195.         break;
  196.     default:
  197.         assert(0);
  198.         break;
  199.     }
  200.     ArgumentsIndex++;
  201.     if (p->x.nestedCall == 0)
  202.         p->syms[2] = r;
  203.     if (ArgumentsIndex == 3)
  204.         ArgumentsIndex = 0;
  205.     return r;
  206. }
  207.  
  208. static void itobcd(Node p)
  209. {
  210.     if (p->x.nestedCall) {
  211.         print("\tpopl\t%%edx\n");
  212.         print("\tfildl\t(%%esp)\n\tfbstp\t(%%edx)\n\taddl\t$4,%%esp\n");
  213.     }
  214.     else {
  215.         print("\tpushl\t%%ecx\n\tfildl\t(%%esp)\n");
  216.         print("\tfbstp\t(%%edx)\n\taddl\t$4,%%esp\n");
  217.     }
  218. }
  219.  
  220. static Symbol itobcdArgs(Node p)
  221. {
  222.     Symbol r=NULL;
  223.  
  224.     switch (ArgumentsIndex) {
  225.     case 0:
  226.         if (p->x.nestedCall == 0) {
  227.             r = intreg[ECX];
  228.             p->kids[0]->syms[2] = r;
  229.         }
  230.         break;
  231.     case 1:
  232.         if (p->x.nestedCall == 0) {
  233.             r = intreg[EDX];
  234.             p->kids[0]->syms[2] = r;
  235.         }
  236.         break;
  237.     }
  238.     ArgumentsIndex++;
  239.     if (p->x.nestedCall == 0)
  240.         p->syms[2] = r;
  241.     if (ArgumentsIndex == 2)
  242.         ArgumentsIndex = 0;
  243.     return r;
  244. }
  245. static Symbol reduceArgs(Node p)
  246. {
  247.     Symbol r=NULL;
  248.  
  249.     switch (ArgumentsIndex) {
  250.     case 0:
  251.         if (p->x.nestedCall == 0) {
  252.             r = intreg[ECX];
  253.             p->kids[0]->syms[2] = r;
  254.         }
  255.         break;
  256.     case 1:
  257.         if (p->x.nestedCall == 0) {
  258.             r = intreg[EAX];
  259.             p->kids[0]->syms[2] = r;
  260.         }
  261.         break;
  262.     }
  263.     ArgumentsIndex++;
  264.     if (p->x.nestedCall == 0)
  265.         p->syms[2] = r;
  266.     if (ArgumentsIndex == 2)
  267.         ArgumentsIndex = 0;
  268.     return r;
  269. }
  270.  
  271. #if 0
  272. static Symbol memopArgs(Node p)
  273. {
  274.     Symbol r=NULL;
  275.     Value v;
  276.  
  277.     FunctionInfo.memmove = 1;
  278.     switch (ArgumentsIndex) {
  279.     case 0:
  280.         Arg0 = NULL;
  281.         if (p->x.nestedCall == 0 ) {
  282.             r = intreg[ECX];
  283.             p->kids[0]->syms[2] = r;
  284.             if (generic(p->kids[0]->op) == CNST) {
  285.                 Arg0 = p->kids[0]->syms[0];
  286.                 v.u = p->kids[0]->syms[0]->u.value/4;
  287.                 p->kids[0]->syms[0] = constant(inttype,v);
  288.                 ArgumentsTab[0] = p->kids[0];
  289.             }
  290.         }
  291.         break;
  292.     case 1:
  293.         if (p->x.nestedCall == 0) {
  294.             r = intreg[EAX];
  295.             p->kids[0]->syms[2] = r;
  296.         }
  297.         if (generic(p->kids[0]->op) == CNST)
  298.             Arg1 = p->kids[0]->syms[0];
  299.         else {
  300.             Arg1 = NULL;
  301.             if (Arg0) {
  302.                 ArgumentsTab[0]->syms[0] = Arg0;
  303.                 Arg0 = NULL;
  304.             }
  305.         }
  306.         break;
  307.     case 2:
  308.         if (p->x.nestedCall == 0) {
  309.             if ((freemask[0] & (1 << EDI)) == 0)
  310.                 r = intreg[EDX];
  311.             else
  312.                 r = intreg[EDI];
  313.             p->kids[0]->syms[2] = r;
  314.         }
  315.         break;
  316.     default:
  317.         assert(0);
  318.         break;
  319.     }
  320.     ArgumentsIndex++;
  321.     if (p->x.nestedCall == 0)
  322.         p->syms[2] = r;
  323.     if (ArgumentsIndex == 3)
  324.         ArgumentsIndex = 0;
  325.     return r;
  326. }
  327. static void imemset(Node p)
  328. {
  329.     int qty;
  330.  
  331.     if (p->x.nestedCall) {
  332.         print("\tpop\t%%edx\n\tpop\t%%eax\n\tpop\t%%ecx\n");
  333.     }
  334.     if ((freemask[0] & (1 << EDI)) == 0)
  335.         print("\txchg\t%%edi,%%edx\n");
  336.     if (Arg0 && Arg1 && Arg1->u.value == 0 && Arg1->name[0] == '0') {
  337.         qty = Arg0->u.value;
  338.         qty -= 4*(qty/4);
  339.         print("\trep\n\tmovsl\n");
  340.         if (qty > 0) {
  341.             if (qty >= 2) {
  342.                 print("\tmovsw\n");
  343.                 qty -= 2;
  344.             }
  345.             if (qty)
  346.                     print("\tmovsb\n");
  347.         }
  348.     }
  349.     else print("\trep\n\tstosb\n");
  350.     if ((freemask[0] & (1 << EDI)) == 0)
  351.         print("\txchg\t%%edi,%%edx\n");
  352. }
  353. #endif
  354. static void repldwordi(char *reg)
  355. {
  356.     print("\tmovl\t%s,(%%edx)\n\tmovl\t%s,4(%%edx)\n",reg,reg);
  357. }
  358. static void replword(Node p)
  359. {
  360.     print("\tmovw\t%%cx,%%ax\n\tshll\t$16,%%eax\n\tmovw\t%%cx,%%ax\n");
  361.     repldwordi("%eax");
  362. }
  363. static void replbyte(Node p)
  364. {
  365.     print("\tmovb\t%%cl,%%ch\n");
  366.     replword(p);
  367. }
  368.  
  369. static void repldword(Node p)
  370. {
  371.     repldwordi("%ecx");
  372. }
  373.  
  374. static void packsswb(Node p)    {    mmxVectCall(p,"packsswb");}
  375. static void packsswbi(Node p)    {    mmxImmCall(p,"packsswb");}
  376. static void packssdw(Node p)    {    mmxVectCall(p,"packssdw");}
  377. static void packssdwi(Node p)    {    mmxImmCall(p,"packssdw");}
  378.  
  379. static void packuswb(Node p)    {    mmxVectCall(p,"packuswb");}
  380. static void packuswbi(Node p)    {    mmxImmCall(p,"packuswb");}
  381.  
  382.  
  383. static void paddd(Node p)    {    mmxVectCall(p,"paddd");        }
  384. static void padddi(Node p)    {    mmxImmCall(p,"paddd");        }
  385. static void paddw(Node p)    {    mmxVectCall(p,"paddw");        }
  386. static void paddwi(Node p)    {    mmxImmCall(p,"paddw");        }
  387. static void paddb(Node p)    {    mmxVectCall(p,"paddb");        }
  388. static void paddbi(Node p)    {    mmxImmCall(p,"paddb");        }
  389. static void paddsb(Node p)    {    mmxVectCall(p,"paddsb");    }
  390. static void paddsbi(Node p)    {    mmxImmCall(p,"paddsb");    }
  391. static void paddsw(Node p)    {    mmxVectCall(p,"paddsw");    }
  392. static void paddswi(Node p)    {    mmxImmCall(p,"paddsw");    }
  393.  
  394. static void paddusw(Node p)    {    mmxVectCall(p,"paddusw");    }
  395. static void padduswi(Node p){    mmxImmCall(p,"paddusw");    }
  396. static void paddusb(Node p)    {    mmxVectCall(p,"paddusb");    }
  397. static void paddusbi(Node p){    mmxImmCall(p,"paddusb");    }
  398.  
  399. static void psubd(Node p)    {    mmxVectCall(p,"psubd");        }
  400. static void psubdi(Node p)    {    mmxImmCall(p,"psubd");        }
  401. static void psubw(Node p)    {    mmxVectCall(p,"psubw");        }
  402. static void psubwi(Node p)    {    mmxImmCall(p,"psubw");        }
  403. static void psubb(Node p)    {    mmxVectCall(p,"psubb");        }
  404. static void psubbi(Node p)    {    mmxImmCall(p,"psubb");        }
  405.  
  406. static void psubsb(Node p)    {    mmxVectCall(p,"psubsb");    }
  407. static void psubsbi(Node p)    {    mmxImmCall(p,"psubsb");        }
  408. static void psubsw(Node p)    {    mmxVectCall(p,"psubsw");    }
  409. static void psubswi(Node p)    {    mmxImmCall(p,"psubsw");        }
  410.  
  411. static void pand(Node p)    {    mmxVectCall(p,"pand");        }
  412. static void pandi(Node p)    {    mmxImmCall(p,"pand");        }
  413. static void pandn(Node p)    {    mmxVectCall(p,"pandn");        }
  414. static void pandni(Node p)    {    mmxImmCall(p,"pandn");        }
  415.  
  416. static void pcmeqb(Node p)    {    mmxVectCall(p,"pcmpeqb");    }
  417. static void pcmeqbi(Node p)    {    mmxImmCall(p,"pcmpeqb");    }
  418. static void pcmeqw(Node p)    {    mmxVectCall(p,"pcmpeqw");    }
  419. static void pcmeqwi(Node p)    {    mmxImmCall(p,"pcmpeqw");    }
  420. static void pcmeqd(Node p)    {    mmxVectCall(p,"pcmpeqd");    }
  421. static void pcmeqdi(Node p)    {    mmxImmCall(p,"pcmpeqd");    }
  422.  
  423. static void pcmpgtb(Node p)    {    mmxVectCall(p,"pcmpeqb");    }
  424. static void pcmpgtbi(Node p){    mmxImmCall(p,"pcmpeqb");    }
  425. static void pcmpgtw(Node p)    {    mmxVectCall(p,"pcmpeqw");    }
  426. static void pcmpgtwi(Node p){    mmxImmCall(p,"pcmpeqw");    }
  427. static void pcmpgtd(Node p)    {    mmxVectCall(p,"pcmpeqd");    }
  428. static void pcmpgtdi(Node p){    mmxImmCall(p,"pcmpeqd");    }
  429.  
  430. static void pmaddwd(Node p){    mmxVectCall(p,"pmaddwd");    }
  431. static void pmaddwdi(Node p){    mmxImmCall(p,"pmaddwd");    }
  432. static void pmulhw(Node p)    {    mmxVectCall(p,"pmulhw");    }
  433. static void pmulhwi(Node p){    mmxImmCall(p,"pmmulhw");    }
  434.  
  435. static void pmullw(Node p)    {    mmxVectCall(p,"pmmullw");    }
  436. static void pmullwi(Node p)    {    mmxImmCall(p,"pmmullw");    }
  437. static void por(Node p)        {    mmxVectCall(p,"por");        }
  438. static void pori(Node p)    {    mmxImmCall(p,"por");        }
  439. static void pslw(Node p)    {    mmxVectCall(p,"pslw");        }
  440. static void pslwi(Node p)    {    mmxImmCall(p,"pslw");        }
  441. static void psld(Node p)    {    mmxVectCall(p,"psld");        }
  442. static void psldi(Node p)    {    mmxImmCall(p,"psld");        }
  443. static void pslq(Node p)    {    mmxVectCall(p,"pslq");        }
  444. static void pslqi(Node p)    {    mmxImmCall(p,"pslq");        }
  445. static void psraw(Node p)    {    mmxVectCall(p,"psraw");        }
  446. static void psrawi(Node p)    {    mmxImmCall(p,"psraw");        }
  447. static void psrad(Node p)    {    mmxVectCall(p,"psrad");        }
  448. static void psradi(Node p)    {    mmxImmCall(p,"psrad");        }
  449.  
  450. static void psrlw(Node p)    {    mmxVectCall(p,"psrlw");        }
  451. static void psrlwi(Node p)    {    mmxImmCall(p,"psrlw");        }
  452. static void psrld(Node p)    {    mmxVectCall(p,"psrld");        }
  453. static void psrldi(Node p)    {    mmxImmCall(p,"psrld");        }
  454. static void psrlq(Node p)    {    mmxVectCall(p,"psrlq");        }
  455. static void psrlqi(Node p)    {    mmxImmCall(p,"psrlq");        }
  456.  
  457. static void punpckhbw(Node p){    mmxVectCall(p,"punpckhbw");    }
  458. static void punpckhbwi(Node p){    mmxImmCall(p,"punpckhbw");    }
  459. static void punpckhwd(Node p){    mmxVectCall(p,"punpckhwd");    }
  460. static void punpckhwdi(Node p){    mmxImmCall(p,"punpckhwd");    }
  461. static void punpckhdq(Node p){    mmxVectCall(p,"punpckhwq");    }
  462. static void punpckhdqi(Node p){    mmxImmCall(p,"punpckhwq");    }
  463.  
  464. static void punpcklbw(Node p){    mmxVectCall(p,"punpcklbw");    }
  465. static void punpcklbwi(Node p){    mmxImmCall(p,"punpcklbw");    }
  466. static void punpcklwd(Node p){    mmxVectCall(p,"punpcklwd");    }
  467. static void punpcklwdi(Node p){    mmxImmCall(p,"punpcklwd");    }
  468. static void punpckldq(Node p){    mmxVectCall(p,"punpcklwq");    }
  469. static void punpckldqi(Node p){    mmxImmCall(p,"punpcklwq");    }
  470.  
  471. static void pxor(Node p)    {    mmxVectCall(p,"pxor");        }
  472. static void pxori(Node p)    {    mmxImmCall(p,"pxor");        }
  473. static void pmemmove(Node p){    mmxVectCall(p,NULL);        }
  474. static void emms(Node p)    {    print("\temms\n");            }
  475.  
  476. static void pcmpneqb(Node p)    {    mmxVectCallN(p,"pcmpeqb",1);}
  477. static void pcmpneqbi(Node p){    mmxImmCallN(p,"pcmpeqb",1);    }
  478. static void pcmpneqw(Node p)    {    mmxVectCallN(p,"pcmpeqw",1);}
  479. static void pcmpneqwi(Node p){    mmxImmCallN(p,"pcmpeqw",1);    }
  480. static void pcmpneqd(Node p)    {    mmxVectCallN(p,"pcmpeqd",1);}
  481. static void pcmpneqdi(Node p){    mmxImmCallN(p,"pcmpeqd",1);    }
  482. static void redBoolean(Node p){ reduceCall(p,NULL,0);            }
  483. static void redCmpEqb(Node p) {    reduceCall(p,"pcmpeqb",0);    }
  484. static void redCmpGtb(Node p) {    reduceCall(p,"pcmpgtb",0);    }
  485. static void redCmpLtb(Node p) {    reduceCall(p,"pcmpgtb",1);    }
  486.  
  487.  
  488. #define OPTIMIZERONLY    1
  489.  
  490. static INTRINSICS intrinsicTable[] = {
  491.     {    "_fsincos",    2,        0,            fsincos,    NULL        },
  492.     {    "_bswap",    1,        0,            bswap,        bswapArgs    },
  493.     {    "_bsf",        1,        0,            bsf,        bswapArgs    },
  494.     {    "_bsr",        1,        0,            bsr,        bswapArgs    },
  495.     {    "_carry",    0,        0,            carry,        NULL        },
  496.     {    "_fistp",    1,        0,            fistp,        NULL        },
  497.     {    "_fabs",    1,        0,            Fabs,        NULL        },
  498.     {    "_fldpi",    0,        0,            fldpi,        NULL        },
  499.     {    "_fldl2e",    0,        0,            fldl2e,        NULL        },
  500.     {    "_fldlg2",    0,        0,            fldlg2,        NULL        },
  501.     {    "_fldln2",    0,        0,            fldln2,        NULL        },
  502.     {    "_f2xm1",    0,        0,            f2xm1,        NULL        },
  503.     {    "_rdtsc",    0,        0,            rdtsc,        NULL        },
  504.     {    "_fbld",    1,        0,            fbld,        bswapArgs    },
  505.     {    "_itobcd",    2,        0,            itobcd,        itobcdArgs    },
  506. //    {    "memset",    3,    OPTIMIZERONLY,    imemset,    memopArgs    },
  507.     /*  MMX section */
  508.     /* packss */
  509.     {    "_packsswb",3,        0,            packsswb,    paddArgs    },
  510.     {    "_packsswbi",3,        0,            packsswbi,    paddArgs    },
  511.     {    "_packssdw",3,        0,            packssdw,    paddArgs    },
  512.     {    "_packssdwi",3,        0,            packssdwi,    paddArgs    },
  513.     {    "_packuswb",3,        0,            packuswb,    paddArgs    },
  514.     {    "_packuswbi",3,        0,            packuswbi,    paddArgs    },
  515.  
  516.     /* paddX */
  517.     {    "_paddd",    3,        0,            paddd,        paddArgs    },
  518.     {    "_padddi",    3,        0,            padddi,        paddArgs    },
  519.     {    "_paddw",    3,        0,            paddw,        paddArgs    },
  520.     {    "_paddwi",    3,        0,            paddwi,        paddArgs    },
  521.     {    "_paddb",    3,        0,            paddb,        paddArgs    },
  522.     {    "_paddbi",    3,        0,            paddbi,        paddArgs    },
  523.     /* paddsX */
  524.     {    "_paddsb",    3,        0,            paddsb,        paddArgs    },
  525.     {    "_paddsbi",    3,        0,            paddsbi,    paddArgs    },
  526.     {    "_paddsw",    3,        0,            paddsw,        paddArgs    },
  527.     {    "_paddswi",    3,        0,            paddswi,    paddArgs    },
  528.     {    "_paddusb",    3,        0,            paddusb,    paddArgs    },
  529.     {    "_paddusbi",3,        0,            paddusbi,    paddArgs    },
  530.     {    "_paddsusw",3,        0,            paddusw,    paddArgs    },
  531.     {    "_paddsuswi",3,        0,            padduswi,    paddArgs    },
  532.     /* psubX */
  533.     {    "_psubd",    3,        0,            psubd,        paddArgs    },
  534.     {    "_psubdi",    3,        0,            psubdi,        paddArgs    },
  535.     {    "_psubw",    3,        0,            psubw,        paddArgs    },
  536.     {    "_psubwi",    3,        0,            psubwi,        paddArgs    },
  537.     {    "_psubb",    3,        0,            psubb,        paddArgs    },
  538.     {    "_psubbi",    3,        0,            psubbi,        paddArgs    },
  539.     /* psubsX */
  540.     {    "_psubsb",    3,        0,            psubsb,        paddArgs    },
  541.     {    "_psubsbi",    3,        0,            psubsbi,    paddArgs    },
  542.     {    "_psubsw",    3,        0,            psubsw,        paddArgs    },
  543.     {    "_psubswi",    3,        0,            psubswi,    paddArgs    },
  544.     /* pand */
  545.     {    "_pand",    3,        0,            pand,        paddArgs    },
  546.     {    "_pandi",    3,        0,            pandi,        paddArgs    },
  547.  
  548.     /* pandn */
  549.     {    "_pandn",    3,        0,            pandn,        paddArgs    },
  550.     {    "_pandni",    3,        0,            pandni,        paddArgs    },
  551.  
  552.     /* pcmeq */
  553.     {    "_pcmpeqb",    3,        0,            pcmeqb,        paddArgs    },
  554.     {    "_pcmpeqbi",3,        0,            pcmeqbi,    paddArgs    },
  555.     {    "_pcmpeqw",    3,        0,            pcmeqw,        paddArgs    },
  556.     {    "_pcmpeqwi",3,        0,            pcmeqwi,    paddArgs    },
  557.     {    "_pcmpeqd",    3,        0,            pcmeqd,        paddArgs    },
  558.     {    "_pcmpeqdi",3,        0,            pcmeqdi,    paddArgs    },
  559.  
  560.     /* pcmgt */
  561.     {    "_pcmpeqb",    3,        0,            pcmpgtb,    paddArgs    },
  562.     {    "_pcmpeqbi",3,        0,            pcmpgtbi,    paddArgs    },
  563.     {    "_pcmpeqw",    3,        0,            pcmpgtw,    paddArgs    },
  564.     {    "_pcmpeqwi",3,        0,            pcmpgtwi,    paddArgs    },
  565.     {    "_pcmpeqd",    3,        0,            pcmpgtd,    paddArgs    },
  566.     {    "_pcmpeqdi",3,        0,            pcmpgtdi,    paddArgs    },
  567.     /* pmaddwd */
  568.     {    "_pmaddwd",    3,        0,            pmaddwd,    paddArgs    },
  569.     {    "_pmaddwdi",3,        0,            pmaddwdi,    paddArgs    },
  570.     /* pmulhw */
  571.     {    "_pmulhw",    3,        0,            pmulhw,        paddArgs    },
  572.     {    "_pmulhwi",    3,        0,            pmulhwi,    paddArgs    },
  573.     /* pmullw */
  574.     {    "_pmullw",    3,        0,            pmullw,        paddArgs    },
  575.     {    "_pmullwi",    3,        0,            pmullwi,    paddArgs    },
  576.     /* por */
  577.     {    "_por",        3,        0,            por,        paddArgs    },
  578.     {    "_pori",    3,        0,            pori,        paddArgs    },
  579.     
  580.     /* psl */
  581.     {    "_pslw",    3,        0,            pslw,        paddArgs    },
  582.     {    "_pslwi",    3,        0,            pslwi,        paddArgs    },
  583.     {    "_psld",    3,        0,            psld,        paddArgs    },
  584.     {    "_psldi",    3,        0,            psldi,        paddArgs    },
  585.     {    "_pslq",    3,        0,            pslq,        paddArgs    },
  586.     {    "_pslqi",    3,        0,            pslqi,        paddArgs    },
  587.     /* psra */
  588.     {    "_psraw",    3,        0,            psraw,        paddArgs    },
  589.     {    "_psrawi",    3,        0,            psrawi,        paddArgs    },
  590.     {    "_psrad",    3,        0,            psrad,        paddArgs    },
  591.     {    "_psradi",    3,        0,            psradi,        paddArgs    },
  592.  
  593.     /* psrl */
  594.     {    "_psrlw",    3,        0,            psrlw,        paddArgs    },
  595.     {    "_psrlwi",    3,        0,            psrlwi,        paddArgs    },
  596.     {    "_psrld",    3,        0,            psrld,        paddArgs    },
  597.     {    "_psrldi",    3,        0,            psrldi,        paddArgs    },
  598.     {    "_psrlq",    3,        0,            psrlq,        paddArgs    },
  599.     {    "_psrlqi",    3,        0,            psrlqi,        paddArgs    },
  600.     /* punpckhXXx */
  601.     {    "_punpckhbw",3,        0,            punpckhbw,    paddArgs    },
  602.     {    "_punpckhbwi",3,    0,            punpckhbwi,    paddArgs    },
  603.     {    "_punpckhwd",3,        0,            punpckhwd,    paddArgs    },
  604.     {    "_punpckhwdi",3,    0,            punpckhwdi,    paddArgs    },
  605.     {    "_punpckhdq",3,        0,            punpckhdq,    paddArgs    },
  606.     {    "_punpckhdqi",3,    0,            punpckhdqi,    paddArgs    },
  607.  
  608.     /* punpcklXXx */
  609.     {    "_punpcklbw",3,        0,            punpcklbw,    paddArgs    },
  610.     {    "_punpcklbwi",3,    0,            punpcklbwi,    paddArgs    },
  611.     {    "_punpcklwd",3,        0,            punpcklwd,    paddArgs    },
  612.     {    "_punpcklwdi",3,    0,            punpcklwdi,    paddArgs    },
  613.     {    "_punpckldq",3,        0,            punpckldq,    paddArgs    },
  614.     {    "_punpckldqi",3,    0,            punpckldqi,    paddArgs    },
  615.  
  616.     {    "_pxor",    3,        0,            pxor,        paddArgs    },
  617.     {    "_pxori",    3,        0,            pxori,        paddArgs    },
  618.  
  619.     {    "_pmemmove",3,        0,            pmemmove,    paddArgs    },
  620.     {    "_replicatebyte",2,    0,            replbyte,    itobcdArgs    },
  621.     {    "_replicateword",2,    0,            replword,    itobcdArgs    },
  622.     {    "_replicatedword",2,0,            repldword,    itobcdArgs    },
  623.  
  624.     /* pcmpneq */
  625.     {    "_pcmpneqb",3,        0,            pcmpneqb,    paddArgs    },
  626.     {    "_pcmpneqbi",3,        0,            pcmpneqbi,    paddArgs    },
  627.     {    "_pcmpneqw",3,        0,            pcmpneqw,    paddArgs    },
  628.     {    "_pcmpneqwi",3,        0,            pcmpneqwi,    paddArgs    },
  629.     {    "_pcmpneqd",3,        0,            pcmpneqd,    paddArgs    },
  630.     {    "_pcmpneqdi",3,        0,            pcmpneqdi,    paddArgs    },
  631.  
  632.     {    "_reduceBooleanb",2,0,            redBoolean,    reduceArgs    },
  633.     {    "_reduceCmpeqb",3,    0,            redCmpEqb,    paddArgs    },
  634.     {    "_reduceGtb",3,        0,            redCmpGtb,    paddArgs    },
  635.     {    "_reduceLtb",3,        0,            redCmpLtb,    paddArgs    },
  636.  
  637.     {    "_emms",    0,        0,            emms,        NULL        },
  638.  
  639.     {    NULL,        0,        0,            0,            0            }
  640. };
  641.  
  642.  
  643. int IsIntrinsic(char *name)
  644. {
  645.     INTRINSICS *p = intrinsicTable;
  646.     int i = 1;
  647.  
  648.     if (name[0] != '_') {
  649.         return 0;
  650.     }
  651.     while (p->Name) {
  652.         if (name == p->Name)
  653.             if ((p->Flags & OPTIMIZERONLY) && OptimizeFlag == 0)
  654.                 return 0;
  655.             else
  656.                 return i;
  657.         p++;
  658.         i++;
  659.     }
  660.     return 0;
  661. }
  662.  
  663.  
  664. void Intrinsic(Node p)
  665. {
  666.     int idx = IsIntrinsic(p->kids[0]->syms[0]->name);
  667.     (*intrinsicTable[idx-1].fn)(p);
  668.     ArgumentsIndex = 0;
  669. }
  670.  
  671. void IntrinsicArg(Node kid,int n)
  672. {
  673.     ArgumentsTab[ArgumentsIndex] = kid;
  674.     ArgumentsNts[ArgumentsIndex] = n;
  675.     ArgumentsIndex++;
  676. }
  677.  
  678. void InstallIntrinsics(void)
  679. {
  680.     INTRINSICS *p = intrinsicTable;
  681.  
  682.     while (p->Name) {
  683.         p->Name = string(p->Name);
  684.         p++;
  685.     }
  686. }
  687.  
  688. Symbol AssignIntrinsicArg(Node p)
  689. {
  690.     int idx = p->x.intrinsicArg - 1;
  691.  
  692.     if (intrinsicTable[idx].argsFn == NULL)
  693.         return intreg[0];
  694.     else
  695.         return (*intrinsicTable[idx].argsFn)(p);
  696. }
  697.  
  698. int nrOfIntrinsicArgs(int idx)
  699. {
  700.     return intrinsicTable[idx-1].NrOfArgs;
  701. }
  702.