home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 November / VPR9711A.ISO / BENCH / archive / pfm686cb.lzh / PFM686.C next >
C/C++ Source or Header  |  1997-06-07  |  24KB  |  1,022 lines

  1. /*  How to make : gcc pfm686.c -o pfm686.g32 -O0 -Wall  */
  2. /*  pfm686 ver1.2B DysanKeihin & (koji) at fext */
  3.  
  4.  
  5. #include <stdio.h>
  6. #include <dos.h>
  7. #include <stdlib.h>
  8. #include <math.h>
  9.  
  10.  
  11. /*
  12. #define PRINT_IMED
  13.  
  14. #define DEBUG 
  15. */
  16.  
  17. #define COUNTER 1193180 /* Hz */
  18.  
  19. #define cli asm volatile("cli");
  20. #define sti asm volatile("sti");
  21.  
  22. #define MEM_1M 0xe0000000
  23. #define PHY_1M 0x100000
  24. #define PUSH_CODE          32
  25.  
  26.  
  27.  
  28. #define TickSet RDTSC(TickStart)
  29. #define TickGet RDTSC(TickStop)
  30.  
  31.  
  32.  
  33. static volatile long *pgdir;  /* Page Directry */
  34. static volatile long *pgtbl;  /* Page Table */
  35. static long seg_base;  /* Segment Base Addr (Linear) */
  36. char flag_p5=0;
  37.  
  38. static unsigned long TickStart, TickStop, Tick;
  39.  
  40. union REGS inregs,outregs;
  41.  
  42. double CycleTime;
  43. unsigned long DelayRDTSC;
  44.  
  45.  
  46.  
  47. #define IOtickSet\
  48.   asm volatile\
  49.   ("\
  50.      movb $0x30,%%al\n\
  51.      outb %%al,$0x43\n\
  52.      xorb %%al,%%al\n\
  53.      outb %%al,$0x40\n\
  54.      outb %%al,$0x40\n\
  55.    ":\
  56.     :\
  57.     :"ax"\
  58.   )
  59.  
  60.  
  61. #define IOtickGet(counter_l)\
  62.   asm volatile\
  63.   ("\
  64.      movb $0x00,%%al\n\
  65.      outb %%al,$0x43\n\
  66.      inb $0x40,%%al\n\
  67.      xchgb %%al,%%ah\n\
  68.      inb $0x40,%%al\n\
  69.      xchgb %%al,%%ah\n\
  70.      movw %%ax,%0\n\
  71.    ":"=g"(counter_l)\
  72.     :\
  73.     :"ax"\
  74.   )
  75.  
  76.  
  77. #define IOtickRecover\
  78.   asm volatile\
  79.   ("\
  80.      movb $0x36,%%al      /*timer0(system)*/\n\
  81.      outb %%al,$0x43\n\
  82.      xorw %%ax,%%ax\n\
  83.      outb %%al,$0x40\n\
  84.      outb %%al,$0x40\n\
  85.    ":\
  86.     :\
  87.     :"ax"\
  88.   )
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97. #define RDTSC(CounterLo)\
  98.   asm volatile\
  99.   ("\
  100.      .byte 0x0f\n\
  101.      .byte 0x31\n\
  102.      movl %%eax,%0\n\
  103.    ":"=g"(CounterLo)\
  104.     :\
  105.     :"ax","dx"\
  106.   )
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113. #define store_string(p,elsize)\
  114.   asm volatile\
  115.   ("\
  116.      .align 4,0x90\n\
  117.      pushl %%eax\n\
  118.      pushl %%ecx\n\
  119.      pushl %%edi\n\
  120.      cld\n\
  121.      movl  %1,%%ecx\n\
  122.      movl  %0,%%eax\n\
  123.      movl  %%eax,%%edi\n\
  124.      movl  $-1,%%eax\n\
  125.      rep\n\
  126.        stosl\n\
  127.      popl %%edi\n\
  128.      popl %%ecx\n\
  129.      popl %%eax\n\
  130.    ":\
  131.     :"g"((p)),"g"(elsize)\
  132.     :"ax","cx","di"\
  133.   )
  134.  
  135.  
  136.  
  137.  
  138.  
  139. #define load_string(p,elsize)\
  140.   asm volatile\
  141.   ("\
  142.      .align 4,0x90\n\
  143.      pushl %%eax\n\
  144.      pushl %%ecx\n\
  145.      pushl %%esi\n\
  146.      movl  %0,%%eax
  147.      movl  %%eax,%%esi
  148.      movl  %1,%%ecx\n\
  149.      cld\n\
  150.      rep\n\
  151.        lodsl  \n/*  <-- EAX is affected  */ \n\
  152.      popl %%esi\n\
  153.      popl %%ecx\n\
  154.      popl %%eax\n\
  155.    ":\
  156.     :"g"((p)),"g"((elsize))\
  157.     :"ax","cx","si"\
  158.   )
  159.  
  160.  
  161.  
  162.  
  163.  
  164. #define do_continuous_push(p_org, no_of_push, stack_start_point)\
  165.   asm volatile\
  166.   ("\
  167.      movl  %0,%%eax\n\
  168.      movl  %1,%%ecx\n\
  169.      movl  %2,%%edx\n\
  170.      call  %%eax\n\
  171.    ":\
  172.     :"g"(p_org),"g"(no_of_push),"g"(stack_start_point)\
  173.     :"ax","cx","dx"\
  174.   )
  175.  
  176.  
  177.  
  178.  
  179.  
  180. void exagoge(char e_level,char *err_mes1,char *err_mes2)
  181. {
  182.   if (*err_mes2 == (char)NULL) fprintf(stderr,"%s \n",err_mes1);
  183.   else fprintf(stderr,"%s [%s]\n",err_mes1,err_mes2);
  184.   exit(e_level);
  185. }
  186.  
  187.  
  188.  
  189.  
  190. long ExactTick()
  191. {
  192.   if (TickStop > TickStart) Tick = TickStop-TickStart;
  193.   else Tick = TickStop + (unsigned long)(~TickStart) + 1;
  194.   return(Tick);
  195. }
  196.  
  197.  
  198.  
  199. void set_code_continuous_push(long *p_start)
  200. { long i;
  201.   unsigned char *p;
  202.  
  203.   p = (char *) p_start;
  204.  
  205.   *p++ = 0x89;        /*  movl  %esp,%eax */
  206.   *p++ = 0xe0;
  207.   *p++ = 0x89;        /*  movl  %edx,%esp */
  208.   *p++ = 0xd4;
  209.  
  210.   for (i=0; i<64; i++)
  211.     *p++ = 0x60;  /*  pushal*/
  212.  
  213.   *p++ = 0xe2;    /* loop  0xbe-0xfe = start add of push (-0x40) */
  214.   *p++ = 0xbe;
  215.  
  216.   *p++ = 0x89;   /*   movl  %eax,%esp */
  217.   *p++ = 0xc4;
  218.  
  219.   *p++ = 0xc3; /* ret immediate */
  220.  
  221. }
  222.  
  223.  
  224.  
  225. void set_code_continuous_push_overhead(long *p_start)
  226. {
  227.   unsigned char *p;
  228.  
  229.   p = (char *) p_start;
  230.  
  231.   *p++ = 0x89;        /*  movl  %esp,%eax */
  232.   *p++ = 0xe0;
  233.   *p++ = 0x89;        /*  movl  %edx,%esp */
  234.   *p++ = 0xd4;
  235.  
  236.   *p++ = 0xe2;    /* loop  0xfe  */
  237.   *p++ = 0xfe;
  238.  
  239.   *p++ = 0x89;   /*   movl  %eax,%esp */
  240.   *p++ = 0xc4;
  241.  
  242.   *p++ = 0xc3; /* ret immediate */
  243.  
  244. }
  245.  
  246.  
  247.  
  248.  
  249.  
  250. #define call_test_code(p_org)\
  251.   asm volatile\
  252.   ("\
  253.      movl  %0,%%eax\n\
  254.      call  %%eax\n\
  255.    ":\
  256.     :"g"(p_org)\
  257.     :"ax"\
  258.   )
  259.  
  260.  
  261.  
  262.  
  263.  
  264. long fill_test_code(long *start,long elsize)
  265. { long readblock,i;
  266.   char *p;
  267.  
  268.   readblock = elsize / (24 / 4);
  269.   p = (char *)start;
  270.  
  271.   for(i=0; i<readblock; i++)
  272.   {
  273.     *p++ = 0x81;/* 81c300000000   adc eax,0x00000000      */
  274.     *p++ = 0xc3;
  275.     *p++ = 0x00;
  276.     *p++ = 0x00;
  277.     *p++ = 0x00;
  278.     *p++ = 0x00;
  279.     *p++ = 0x81;/* 81c000000000   adc ebx,0x00000000      */
  280.     *p++ = 0xc0;
  281.     *p++ = 0x00;
  282.     *p++ = 0x00;
  283.     *p++ = 0x00;
  284.     *p++ = 0x00;
  285.     *p++ = 0x81;/* 81c100000000   adc ecx,0x00000000      */
  286.     *p++ = 0xc1;
  287.     *p++ = 0x00;
  288.     *p++ = 0x00;
  289.     *p++ = 0x00;
  290.     *p++ = 0x00;
  291.     *p++ = 0x81;/* 81c200000000   adc edx,0x00000000      */
  292.     *p++ = 0xc2;
  293.     *p++ = 0x00;
  294.     *p++ = 0x00;
  295.     *p++ = 0x00;
  296.     *p++ = 0x00;
  297.   }
  298.   *p++ = 0xc3; /* ret immediate */
  299.  
  300.   return(readblock);
  301. }
  302.  
  303.  
  304.  
  305.  
  306. int init_pagdir(void) /* Cth (of the Watery Abyss) */
  307. {
  308.   long cr3;
  309.   short ds,ss;
  310.   long base1, base2;
  311.  
  312.   /* Get Addr of Page Dir */
  313.   asm ("
  314.     .byte 0x0f, 0x20, 0xd8;\n/* mov cr3 into eax */\n
  315.     movl %%eax, %0;
  316.     ": "=g"(cr3) : :"ax"
  317.   );
  318.   pgdir = (long *) (MEM_1M + (cr3 & ~0xfff));
  319.  
  320.   /* Get Segment Base Addr from GDT */
  321.   asm ("movw %%ds, %%ax; movw %%ax, %0": "=g"(ds): :"ax");
  322.   asm ("movw %%ss, %%ax; movw %%ax, %0": "=g"(ss): :"ax");
  323. #ifdef DEBUG
  324.   printf("ds:%x ss%x\n",ss,ds);
  325. #endif
  326.   if (ds & 0x4 || ds != ss )   return (1);
  327.   
  328.   if (ds & 0x7 ) fprintf(stdout,"ds:%x \n",ds);
  329.   
  330.   asm ("
  331.     push %%es;
  332.     movw %%ds, %%bx; andl $0xfff8, %%ebx;   \n/* Set Offset of DS in GDT */\n
  333.     movw $0x08, %%ax; movw %%ax, %%es;    \n/* Set ES points to GDT */\n
  334.     movl %%es:(%%ebx), %%eax;
  335.     movl %%eax, %0;
  336.     movl %%es:4(%%ebx), %%eax;
  337.     movl %%eax, %1;
  338.     pop %%es;
  339.     ": "=g"(base1), "=g"(base2): : "ax", "bx"
  340.   );
  341.   seg_base = base2 & 0xff000000 | (base2 & 0xff) << 16 | ((unsigned) base1 >> 16);
  342.   return (0);
  343. }
  344.  
  345.  
  346.  
  347.  
  348. long get_phyadr(void *offset) /* Cth (of the Watery Abyss) */
  349. {
  350.   long pde, pte;
  351.   unsigned long ladr;    /* Linear Address */
  352.  
  353.   ladr = seg_base + (long) offset;
  354.   pde = pgdir[ladr >> 22];
  355.   if (!(pde & 1))   return (-1);  /* Page Table Not Presented */
  356.   pgtbl = (long *) (MEM_1M + (pde & ~0xfff));
  357.  
  358.   pte = pgtbl[(ladr >> 12) & 0x3ff];
  359.   if (!(pte & 1))   return (-1);  /* Page Not Presented */
  360.   return ((pte & ~0xfff) + (ladr & 0xfff));
  361. }
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369. #define cpuid(i_eax,r_eax,r_ebx,r_ecx,r_edx)\
  370.   asm volatile\
  371.   ("\
  372. \n/*   pushl %%ebx  */\n
  373.      movl %4,%%eax
  374.      .byte 0x0f
  375.      .byte 0xa2
  376.      movl %%eax,%0
  377.      movl %%ebx,%1
  378.      movl %%ecx,%2
  379.      movl %%edx,%3
  380. \n/*   popl  %%ebx  */\n
  381.    ":"=g"(r_eax),"=g"(r_ebx),"=g"(r_ecx),"=g"(r_edx)\
  382.     :"g"(i_eax)\
  383.     :"ax","bx","cx","dx"\
  384.   )
  385.  
  386.  
  387.  
  388.  
  389.  
  390. #define MMXFLAG 0x00800000  /* Bit 23*/
  391.  
  392. long get_cpuid(char *id_string)
  393. { volatile unsigned long i_eax,r_eax,r_edx;
  394.   volatile unsigned long string_reg[4];
  395.   char vendor_string[32], p5_bug_string[64],cputype[7],cpu[4];
  396.   long i,j;
  397.   volatile double c;
  398.  
  399.   asm volatile /* Whether the CPU has ID string */
  400.   ("
  401.      pushfl
  402.      pushfl
  403.      popl  %%eax
  404.      orl  $0x200000,%%eax
  405.      pushl %%eax
  406.      popfl
  407.      pushfl
  408.      popl  %%eax
  409.      popfl
  410.      movl  %%eax,%0
  411.    ":"=g"(r_eax)
  412.     :
  413.     :"ax"
  414.   );
  415.  
  416. #ifdef DEBUG
  417. fprintf(stderr,"%lx \n",r_eax);
  418. #endif
  419.  
  420.   if (!(r_eax & 0x200000))  /* if bit21==1 then P5,P6...*/
  421.   { *id_string = (char)NULL;
  422. #ifdef DEBUG
  423.   printf(" It doesen't have CPUID. \n");
  424. #endif
  425.     return(0);
  426.   }
  427.  
  428. #ifdef DEBUG
  429.   printf(" It has CPUID. \n");
  430. #endif
  431.  
  432.   vendor_string[0] = (char)NULL;
  433.   i_eax=0;
  434.   cpuid(i_eax,string_reg[3],string_reg[0],string_reg[2],string_reg[1]);
  435.   for(i=0; i<3; i++)
  436.     for(j=0; j<4; j++)
  437.       vendor_string[i*4+j] = (char)( 0xff & (string_reg[i] >> j*8) );
  438.   vendor_string[12] = (char)NULL;
  439.  
  440.   i_eax=1;
  441.   cpuid(i_eax,r_eax,string_reg[0],string_reg[2],string_reg[1]);
  442.  
  443.   sprintf(cputype," ??? ");
  444.   if ((r_eax & 0x0ff0) == 0x0000 ) sprintf(cputype,"  non ");
  445.   if ((r_eax & 0x0ff0) == 0x0400 ) sprintf(cputype," 486DX");
  446.   if ((r_eax & 0x0ff0) == 0x0410 ) sprintf(cputype," 486DX");
  447.   if ((r_eax & 0x0ff0) == 0x0420 ) sprintf(cputype," 486SX");
  448.   if ((r_eax & 0x0ff0) == 0x0430 ) sprintf(cputype,"486DX2");
  449.   if ((r_eax & 0x0ff0) == 0x0440 ) sprintf(cputype," 486SL");
  450.   if ((r_eax & 0x0ff0) == 0x0450 ) sprintf(cputype,"486SX2");
  451.   if ((r_eax & 0x0ff0) == 0x0470 ) sprintf(cputype,"WBEDX2");
  452.   if ((r_eax & 0x0ff0) == 0x0480 ) sprintf(cputype,"  DX4 ");
  453.   if ((r_eax & 0x0ff0) == 0x0420 ) sprintf(cputype,"  UMC ");
  454.   if ((r_eax & 0x0ff0) == 0x0510 ) { sprintf(cputype,"  P5  "); flag_p5 = 1; }
  455.   if ((r_eax & 0x0ff0) == 0x0520 ) { sprintf(cputype," P54C "); flag_p5 = 1; }
  456.   if ((r_eax & 0x0ff0) == 0x0530 ) { sprintf(cputype," P24T "); flag_p5 = 1; }
  457.   if ((r_eax & 0x0ff0) == 0x0540 ) sprintf(cputype," P55C ");
  458.   if ((r_eax & 0x0ff0) == 0x0570 ) { sprintf(cputype,"P5note"); flag_p5 = 1; }
  459.   if ((r_eax & 0x0ff0) == 0x04e0 ) sprintf(cputype,"Am5x86");
  460.   if ((r_eax & 0x0ff0) == 0x0610 ) sprintf(cputype,"  P6  ");
  461.   if ((r_eax & 0x0ff0) == 0x0630 ) sprintf(cputype,"Pen-II");
  462.   if ((r_eax & 0x0ff0) == 0x0560 ) sprintf(cputype,"AMD K6");
  463.  
  464.   sprintf(p5_bug_string,"\0");
  465.   if( flag_p5 )
  466.   { c = 824633702449.0;
  467.     if( fabs (1.0 - (1.0/c)*c) > 0.00000000000001 )
  468.       sprintf(p5_bug_string,"\n| This FPU is BUGGY version.             |");
  469.   }
  470.  
  471.   i_eax=1;
  472.   cpuid(i_eax,r_eax,string_reg[0],string_reg[2],r_edx);
  473.  
  474.   if ( MMXFLAG & r_edx) sprintf(cpu,"MMX");
  475.   else sprintf(cpu,"CPU");
  476.  
  477.   sprintf(id_string,"|%s:%6s[%12s Fam%1ld Mdl%1ld Stp%2ld]|%s\0",cpu,
  478.                     cputype,vendor_string,0x0f&(r_eax>>8),0x0f&(r_eax>>4),0x0f&r_eax,p5_bug_string );
  479.  
  480.   return(1);
  481. }
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488. #define CMOS_ADDR   0x70
  489. #define CMOS_SEC    0x00
  490. #define CMOS_DATA   0x71
  491.  
  492.  
  493. void GetCycleTime(void)
  494. {
  495.   unsigned long Diff;
  496.   unsigned short NewCounter,PreviousCounter;
  497.   int j;
  498.   unsigned char sec,sec1;
  499.   long CounterValSec, Vcount;
  500.  
  501.   for(j=0; j<2; j++)
  502.   {
  503.     TickSet;
  504.     TickGet;
  505.   }
  506.   if (TickStart == TickStop ) 
  507.     exagoge(1," Sorry, this CPU doesn't have RDTSC instruction.\n Use PFM586 or PFM486.","");
  508.  
  509.   DelayRDTSC = ExactTick();
  510.   IOtickSet;
  511.  
  512.   IOtickGet(PreviousCounter);  /* wait for tick*/
  513.   while(1)
  514.   { IOtickGet(NewCounter);
  515.     if ( NewCounter > PreviousCounter) break;
  516.     PreviousCounter = NewCounter;
  517.   }
  518.  
  519.  
  520.   for(j=0; j<2; j++)
  521.   {
  522.     TickSet;
  523.  
  524.     { int i=0;                  /* wait for 10 ticks*/
  525.       while(i<10)
  526.       { IOtickGet(PreviousCounter);
  527.         while(1)
  528.         { IOtickGet(NewCounter);
  529.           if ( NewCounter > PreviousCounter) break;
  530.           PreviousCounter = NewCounter;
  531.         }
  532.         i++;
  533.       }
  534.     }
  535.  
  536.     TickGet;
  537.   }
  538.   
  539.   Diff = ExactTick()-DelayRDTSC;
  540.  
  541. /*  CycleTime = 1./COUNTER*(double)(10*0x10000)/(double)Diff;  -- v 1.1*/
  542.  
  543. #ifdef DEBUG
  544. printf("Delay:%lx\n",DelayRDTSC);
  545. printf("Diff :%lx\n",Diff);
  546. #endif
  547.  
  548. /* Check CMOS clock */
  549.   
  550.   cli;
  551.   outportb(CMOS_ADDR, CMOS_SEC);
  552.   sec = inportb(CMOS_DATA);
  553.  
  554.   Vcount = 0;
  555.   while(1)
  556.   { outportb(CMOS_ADDR, CMOS_SEC);
  557.     if ((sec1 = inportb(CMOS_DATA)) == sec) { if ( 10000 == Vcount++) break; }
  558.     else Vcount = 0;
  559.     sec = sec1;
  560.   }
  561.   while(1)
  562.   { outportb(CMOS_ADDR, CMOS_SEC);
  563.     if (sec != inportb(CMOS_DATA))  break;
  564.   }
  565.   
  566.  
  567.   TickSet;
  568.  
  569.   Vcount = 0;
  570.   while(1)
  571.   { outportb(CMOS_ADDR, CMOS_SEC);
  572.     if ( (sec1 = inportb(CMOS_DATA))==sec ) { if ( 10000 == Vcount++) break; }
  573.     else Vcount = 0;
  574.     sec = sec1;
  575.   }
  576.   while(1)
  577.   { outportb(CMOS_ADDR, CMOS_SEC);
  578.     if (sec != inportb(CMOS_DATA))  break;
  579.   }
  580.   TickGet;
  581.  
  582.   CounterValSec = ExactTick();
  583.  
  584.   sti;
  585. #ifdef DEBUG
  586.   fprintf(stdout,"%ld\n",CounterValSec);
  587.   fprintf(stdout,"%lf\n",COUNTER/(double)(10*0x10000)*(double)Diff);
  588. #endif
  589.   CycleTime = 1./CounterValSec;
  590.   if (abs ( (double)CounterValSec/1000000. - COUNTER/(double)(10*0x10000)*(double)Diff/1000000) > 0.1 )
  591.   { fprintf(stdout,"-------------------------------------------------\n");
  592.     fprintf(stdout,"Either CMOS-RTC or 14.318MHz clock seems strange.\n");
  593.     fprintf(stdout,"factor : :%5.4f\n",CounterValSec/(COUNTER/(double)(10*0x10000)*(double)Diff));
  594.   }
  595. }
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604. /*============================================================================================================*/
  605.  
  606.  
  607.  
  608.  
  609. void main(int argc,char **argv)
  610. { long i,j,k;
  611.   long fillsize,elsize,allocsize,kbytes,readblock_er,readblock_mr;
  612.   long no_of_push,no_of_push_allocsize,*stack_start_point,*stack_start_point_allocsize;
  613.   unsigned long io_delay=0,counter_val_mr,counter_val_er,counter_val_mw,counter_val_ew;
  614.   long *min_p_org,*p_org,*fill,*start,*clearance;
  615.   char vendor_string[128],CacheSizeString[128];
  616.   double time_er,time_ew,time_mr,time_mw,loop_overhead,freq,devide=1.0;
  617.   char v=0;
  618.   long int15mem=0,DiscontinuousCounter;
  619.  
  620.  
  621.   start = (long *)0;
  622.  
  623.   fprintf(stdout,"\n-- pfm686 ver1.2B  DysanKeihin & (koji) --\n");
  624.  
  625. /* dpmi test */
  626.   inregs.x.ax=0x0400;
  627.   int86(0x31,&inregs,&outregs);
  628.   if (outregs.x.bx & 1 ) exagoge(1,"PFM686 cannot run under DPMI.","");
  629.  
  630. /* int15 memory test */
  631.   inregs.x.ax=0x8800;
  632.   int86(0x15,&inregs,&outregs);
  633.   if ((long)outregs.x.ax > 1024 ) int15mem = ((long)outregs.x.ax + 1024)*1024;
  634.   if (int15mem > 0xff00*1024 ) int15mem = (0xffff * 2 )*1024; 
  635.   /*if this PC has more than 64M memory, int15mem is fixed at 128M */
  636.  
  637. #ifdef DEBUG
  638.     printf("Maxmum address of int15mem %lx \n",int15mem);
  639. #endif
  640.  
  641.  
  642.   CacheSizeString[0] = '\0';
  643.   kbytes = 256;
  644.   if (argc != 1)
  645.     for (i=1; i<argc; i++)
  646.     { if ( strchr(argv[i],'v') != NULL || strchr(argv[i],'V') != NULL) v=1;
  647.       if ( '0' <= argv[i][0] && argv[i][0] <= '9')
  648.       { kbytes = atol(argv[i]);
  649.         if ( (double)kbytes != atof(argv[i]))
  650.           exagoge(-1,"Sorry, cache size must be integer.",argv[i]);
  651.         if ( kbytes <= 1 ) exagoge(-1,"Cache size must be more than 2kbytes.",argv[i]);
  652.         sprintf(CacheSizeString,"| Cache size : [%4ld]Kbytes              |",kbytes);
  653.       }
  654.       if ( strchr(argv[i],'a') != NULL || strchr(argv[i],'A' ) != NULL)
  655.       { if( int15mem ==0 ) exagoge(-1,"Start address can be defined under INT15mem only.","");
  656.         if( i+1 > argc ) exagoge(-1,"Please define start address.","");
  657.         sscanf(argv[i+1],"%x",&k);
  658.         start = (long*)(MEM_1M + k);
  659.         i++;
  660.       }
  661.       if ( strchr(argv[i],'t') != NULL || strchr(argv[i],'T' ) != NULL)
  662.       {
  663.         if( i+1 > argc ) exagoge(-1,"Please define start address.","");
  664.         sscanf(argv[i+1],"%lf",&devide);
  665.  
  666.         i++;
  667.       }
  668.     }
  669.  
  670.  
  671.  
  672. #ifdef DEBUG
  673.     if ((long)start != 0)
  674.     {
  675.       if (init_pagdir()) exagoge(-1,"Data Segment Selector Points LDT","");
  676.       *start = 0xffffffff;
  677.       printf("v=%d kbytes=%ld log_start:%p  phy_start:%lx\n",v,kbytes,start,get_phyadr(start));
  678.     }
  679. #endif
  680.  
  681.   if ( kbytes & 1 == 1 )
  682.   { fprintf(stderr,"Please define cache size with even value.\n");
  683.     kbytes++;
  684.   }
  685.  
  686.  
  687.  
  688.   if ( kbytes > 32 ) kbytes -=2;
  689.   elsize = kbytes*256;/* array size counted in long */
  690.  
  691.   if ( elsize < 65500 ) allocsize = 65500;
  692.   else allocsize = elsize;
  693.  
  694.  
  695.   fillsize = ( elsize*2 > 1024*256 )? elsize*2:1024*256;
  696.  
  697.   p_org = (long *)malloc((allocsize + PUSH_CODE)*4 + 16);
  698.   min_p_org = p_org;
  699.   if (start != (long *)0)
  700.   {
  701. #ifdef DEBUG
  702.   printf("elsize:%lx  kbytes:%lx  allocsize:%lx  fillsize:%lx \n",elsize,kbytes,allocsize,fillsize);
  703.   printf("start-MEM_1M:%lx > p_org:%lx && start+elsize*4- MEM_1M:%lx < int15mem:%lx\n",(long)start - MEM_1M,(long)p_org+PHY_1M,(long)start + elsize*4 - MEM_1M,int15mem);
  704. #endif
  705.     if ( (long)start - MEM_1M >= (long)min_p_org+PHY_1M
  706.         && (long)start + elsize*4 - MEM_1M < int15mem)
  707.     { free(p_org);
  708.       p_org = start;
  709.     }
  710.     else
  711.     { fprintf(stdout,"Invalid address.[%lx - %lx]\nIt must be within [%lx - %lx].\n",(long)start-MEM_1M,(long)start-MEM_1M+elsize*4,(long)min_p_org+PHY_1M,int15mem);
  712.       exagoge(-1,"","");
  713.     }
  714.   }
  715.   else
  716.   {
  717.     p_org = p_org + 8 - ((long)p_org & 0x1fL)/4 ; /*align 8bytes*/
  718.   }
  719.  
  720.  
  721.   for (i=0; i<elsize + PUSH_CODE + 4; i++)
  722.     *(p_org + i) = 0xffffffff;
  723.   no_of_push = elsize/64/8;
  724.   no_of_push_allocsize = allocsize/64/8;
  725.   stack_start_point = p_org + elsize + PUSH_CODE;
  726.   stack_start_point_allocsize = p_org + allocsize + PUSH_CODE;
  727.  
  728.  
  729.  
  730. /* fill と dummy の間に fill の大きさの隙間を空ける */
  731.  
  732.   if (start == (long *)0)
  733.   {
  734.     clearance = (long *)malloc(allocsize *4 );
  735.      for (i=0; i<allocsize ; i++)
  736.        *(clearance + i) = 0xffffffff;
  737.   }
  738.  
  739.  
  740.  
  741.  
  742.  
  743.   if (start != (long *)0)
  744.   {
  745. #ifdef DEBUG
  746.   printf("int15mem - (long)(p_org + elsize)-MEM_1M:%lx > p_org:%lx\n",int15mem - ((long)(p_org + elsize) - MEM_1M),(long)p_org-MEM_1M - (PHY_1M+(long)min_p_org));
  747.   printf("p_org:%lp  elsize:%lx  p_org+elsize:%lp\n",p_org,elsize,p_org + elsize);
  748. #endif
  749.     if ( int15mem - ((long)(p_org + elsize) - MEM_1M)
  750.          >  (long)p_org-MEM_1M - (PHY_1M+(long)min_p_org))
  751.     { fill = p_org + allocsize*2 + 256;  /* elsize*2 とするのはclearanceの分 */
  752.       if ( (long)fill + fillsize*4 + 16 >= int15mem)
  753.         exagoge(-1,"Too small int15 memory","p_org<fill");
  754. #ifdef DEBUG
  755.   printf("Logic1:fill:%lp\n",fill);
  756. #endif
  757.     
  758.     }
  759.     else
  760.     { fill = p_org - fillsize - 16;
  761.       if ( (long)fill - MEM_1M < PHY_1M )
  762.         exagoge(-1,"Too small int15 memory","fill<p_org");
  763. #ifdef DEBUG
  764.   printf("Logic2:fill:%lp\n",fill);
  765. #endif
  766.     }
  767.   }
  768.   else
  769.   { fill  = (long *)malloc(fillsize * 4 + 256);  /* +256 is insurance */
  770.       if ( fill == NULL )
  771.         exagoge(-1,"Insufficient memory","");
  772.     fill = fill + 8 - ((long)fill & 0x1f)/4 ; /*align 32bytes*/
  773.   }
  774.  
  775.  
  776.   for (i=0; i<fillsize + 4; i++)
  777.     *(fill + i) = 0xffffffff;
  778.  
  779.  
  780.  
  781. #ifdef DEBUG
  782.   printf("p_org = %lx  elsize =%lx \n",(long)p_org,elsize);
  783. #endif
  784.  
  785.  
  786.  
  787.  
  788. /*  Get physical address of memory  */
  789.  
  790.   if (init_pagdir()) exagoge(-1,"Data Segment Selector Points LDT","");
  791.  
  792. #ifdef PRINT_IMED
  793.   if( v==1 )
  794.   { fprintf(stdout,"Cache fill %08lX - %08lX\n",get_phyadr(p_org),get_phyadr(p_org+elsize));
  795.     fprintf(stdout,"Dummy fill %08lX - %08lX\n",get_phyadr(fill),get_phyadr(fill+fillsize));
  796.   }
  797. #endif
  798.  
  799.   DiscontinuousCounter = 0;
  800.   if (elsize > 1024)
  801.   { j = get_phyadr(p_org);
  802.     for(i=1024; i<elsize; i+=1024)
  803.     { k = get_phyadr(p_org + i);
  804.       if ( j + 4096 != k)
  805.       { 
  806. #ifdef DEBUG
  807. fprintf(stderr,"j:%ld ,k:%ld\n",j,k);
  808. #endif
  809.         DiscontinuousCounter++;
  810.       }
  811.       j = k;
  812.     }
  813.   }
  814.   if( DiscontinuousCounter > 1)
  815.     fprintf(stdout,"Warning(pfm686) : Physical memory was allocated discontinuously(%ld).\n",DiscontinuousCounter);
  816.  
  817.  
  818.  
  819. /*  cpuid  */
  820. #ifdef PRINT_IMED
  821.   if ( get_cpuid(&vendor_string[0]) ) fprintf(stdout,"%s\n",vendor_string);
  822. #endif
  823.  
  824. #ifdef DEBUG
  825.   printf("/* cli */\n");
  826. #endif
  827.  
  828.   cli;
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835. /* evaluate clock frequency */
  836.  
  837.   GetCycleTime();
  838.  
  839.   freq = .000001/CycleTime;
  840.  
  841. #ifdef PRINT_IMED
  842.   fprintf(stdout,"CPU Frequency %6.2f[MHz]\n",freq);
  843. #endif
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850. /* e-cache read */
  851.   readblock_er = fill_test_code(p_org,elsize);
  852.   for (i=0; i<4; i++)
  853.   { TickSet;
  854.       call_test_code(p_org);
  855.     TickGet;
  856.   }
  857.   counter_val_er = ExactTick();
  858.  
  859. #ifdef DEBUG
  860. fprintf(stdout,"CounterValER:%ld  \n",counter_val_er);
  861. #endif
  862.  
  863. /* call overhead of E-cache read */
  864.   
  865.   *p_org = 0xc3; /* ret immediate */
  866.   for(i=0; i<4; i++)
  867.   {
  868.     TickSet;
  869.       call_test_code(p_org);
  870.     TickGet;
  871.   }
  872.   counter_val_er -= ExactTick();
  873.  
  874.   time_er = (double)(counter_val_er * CycleTime * 1e+9 )/(double)(readblock_er * 24 / 4 );
  875. #ifdef PRINT_IMED
  876.   fprintf(stdout,"CounterValER:%ld  CycleTime:%e\n",counter_val_er,CycleTime);
  877.   fprintf(stdout,"E-cache read  %6.2f[ns/dword] :%5.2f[clocks]\n",time_er,time_er/(1000./freq));
  878. #endif
  879.  
  880.  
  881.  
  882.  
  883. /* E-cache write */
  884.     set_code_continuous_push(p_org);
  885.     for(j=0; j<4; j++)
  886.     {
  887.       load_string(p_org,elsize+PUSH_CODE );
  888.       TickSet;
  889.         do_continuous_push(p_org, no_of_push, stack_start_point);
  890.       TickGet;
  891.     }
  892.     counter_val_ew = ExactTick();
  893.  
  894. /* for & call overhead of E-cache write */
  895.  
  896.   set_code_continuous_push_overhead(p_org);
  897.   for(j=0; j<4; j++)
  898.   {
  899.     load_string(p_org,elsize+PUSH_CODE );
  900.     TickSet;
  901.       do_continuous_push(p_org, no_of_push, stack_start_point);
  902.     TickGet;
  903.   }
  904.   counter_val_ew -= ExactTick();
  905.  
  906.   time_ew = ((double)counter_val_ew * CycleTime * 1e+9  - no_of_push*loop_overhead)/(double)elsize;
  907. #ifdef PRINT_IMED
  908.   fprintf(stdout,"CounterValEW:%ld  CycleTime:%e\n",counter_val_ew,CycleTime);
  909.   fprintf(stdout,"E-cache write %6.2f[ns/dword] :%5.2f[clocks]\n",time_ew,time_ew/(1000./freq));
  910. #endif
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917. /* main read */
  918.  
  919. #ifdef DEBUG
  920.   fprintf(stdout,"fill:%lx  fillsize:%lx  p_org:%lx  allocsize:%lx \n", fill,fillsize,p_org,allocsize);
  921. #endif
  922.   readblock_mr = fill_test_code(p_org,allocsize);
  923.   fill_test_code(fill,fillsize);
  924. #ifdef DEBUG
  925.   fprintf(stdout,"success!  fill_test_code(fill,fillsize);  \n");
  926. #endif
  927.   for (i=0; i<4; i++)
  928.   {
  929.     call_test_code(fill);
  930.  
  931.     TickSet;
  932.     call_test_code(p_org);
  933.     TickGet;
  934.   }
  935.   counter_val_mr = ExactTick() - io_delay;
  936.   time_mr = (double)(counter_val_mr * CycleTime * 1e+9 )/(double)(readblock_mr * 24 / 4 );
  937.  
  938. #ifdef PRINT_IMED
  939.   fprintf(stdout,"main    read  %6.2f[ns/dword] :%5.2f[clocks]\n",time_mr,time_mr/(1000./freq));
  940. #endif
  941.  
  942.  
  943.  
  944.  
  945. /* main write */
  946.  
  947.   fill_test_code(fill,fillsize);
  948.   set_code_continuous_push(p_org);
  949.   for (i=0; i<4; i++)
  950.   {
  951.     call_test_code(fill);
  952.     TickSet;
  953.     do_continuous_push(p_org, no_of_push_allocsize, stack_start_point_allocsize);
  954.     TickGet;
  955.   }
  956.   counter_val_mw = ExactTick() - io_delay;
  957.   time_mw = ((double)counter_val_mw * CycleTime * 1e+9  - no_of_push_allocsize*loop_overhead)/(double)allocsize  ;
  958. #ifdef PRINT_IMED
  959.   fprintf(stdout,"main   write  %6.2f[ns/dword] :%5.2f[clocks]\n",time_mw,time_mw/(1000./freq));
  960. #endif
  961.  
  962.  
  963.  
  964.  
  965. /* Recover timer IC  */
  966.   IOtickRecover;
  967.   sti;
  968.  
  969.   free(p_org);
  970.   free(fill);
  971.  
  972.  
  973.  
  974. /*  print   */
  975.  
  976.  
  977. #ifndef PRINT_IMED
  978.   if ( get_cpuid(&vendor_string[0]) )
  979.   { fprintf(stdout,"------------------------------------------\n");
  980.     fprintf(stdout,"%s\n",vendor_string);
  981.   }
  982.  
  983.  
  984.   if( v==1 )
  985.   { fprintf(stdout,"| Cache fill %08lX - %08lX         |\n",get_phyadr(p_org),get_phyadr(p_org+elsize));
  986.     fprintf(stdout,"| Dummy fill %08lX - %08lX         |\n",get_phyadr(fill),get_phyadr(fill+fillsize));
  987.   }
  988.   if( CacheSizeString[0] != '\0' )
  989.     fprintf(stdout,"%s\n",CacheSizeString);
  990.   fprintf(stdout,"|----------------------------------------|\n");
  991.   { char st[5][10];
  992.     sprintf(st[0],"%6.2f",freq);
  993.     sprintf(st[1],"%7.3f",time_er);
  994.     sprintf(st[2],"%7.3f",time_ew);
  995.     sprintf(st[3],"%7.3f",time_mr);
  996.     sprintf(st[4],"%7.3f",time_mw);
  997.     
  998.     if ( fabs( devide - 1.0) < 0.001 ) 
  999.       fprintf(stdout,"|  %6s[MHz]  | [ns/dword] |[CPUclocks]|\n",st[0]);
  1000.     else
  1001.       fprintf(stdout,"|%6s/%3.1f[MHz]| [ns/dword] |[EXTclocks]|\n",st[0],devide);
  1002.     fprintf(stdout,"|---------------+------------+-----------|\n");
  1003.     fprintf(stdout,"| E-cache read  | %8s   |  %6.3f   |\n",st[1],time_er/(1000./freq)/devide);
  1004.     fprintf(stdout,"| E-cache write | %8s   |  %6.3f   |\n",st[2],time_ew/(1000./freq)/devide);
  1005.     fprintf(stdout,"| main    read  | %8s   |  %6.3f   |\n",st[3],time_mr/(1000./freq)/devide);
  1006.     fprintf(stdout,"| main    write | %8s   |  %6.3f   |\n",st[4],time_mw/(1000./freq)/devide);
  1007.     fprintf(stdout,"------------------------------------------\n");
  1008. /*
  1009.     printf("[%s]",st[0]);
  1010.     printf("[%s]",st[1]);
  1011.     printf("[%s]",st[2]);
  1012.     printf("[%s]",st[3]);
  1013.     printf("[%s]",st[4]);
  1014. */
  1015.   }
  1016.   
  1017. #endif
  1018. }
  1019.  
  1020.  
  1021.  
  1022.