1 // PERMUTE_ARGS: -release -g
2 
version(Windows)3 version(Windows) {}
version(X86_64)4 else version(X86_64)
5 {
6         /* uncomment to enable tests! */
7         //version = Run_X86_64_Tests;
8 }
9 
10 extern (C) int printf(const char*, ...);
11 
tuple(A...)12 template tuple(A...) { alias A tuple; }
13 
14 alias byte   B;
15 alias short  S;
16 alias int    I;
17 alias long   L;
18 alias float  F;
19 alias double D;
20 alias real   R;
21 
22 // Single Type
23 
24 struct b        { B a;                  }
25 struct bb       { B a,b;                }
26 struct bbb      { B a,b,c;              }
27 struct bbbb     { B a,b,c,d;            }
28 struct bbbbb    { B a,b,c,d, e;         }
29 struct b6       { B a,b,c,d, e,f;       }
30 struct b7       { B a,b,c,d, e,f,g;     }
31 struct b8       { B a,b,c,d, e,f,g,h;   }
32 struct b9       { B a,b,c,d, e,f,g,h, i;                }
33 struct b10      { B a,b,c,d, e,f,g,h, i,j;              }
34 struct b11      { B a,b,c,d, e,f,g,h, i,j,k;            }
35 struct b12      { B a,b,c,d, e,f,g,h, i,j,k,l;          }
36 struct b13      { B a,b,c,d, e,f,g,h, i,j,k,l, m;       }
37 struct b14      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n;     }
38 struct b15      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o;   }
39 struct b16      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p; }
40 struct b17      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q;      }
41 struct b18      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r;    }
42 struct b19      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r,s;  }
43 struct b20      { B a,b,c,d, e,f,g,h, i,j,k,l, m,n,o,p, q,r,s,t;}
44 
45 struct s        { S a;                  }
46 struct ss       { S a,b;                }
47 struct sss      { S a,b,c;              }
48 struct ssss     { S a,b,c,d;            }
49 struct sssss    { S a,b,c,d, e;         }
50 struct s6       { S a,b,c,d, e,f;       }
51 struct s7       { S a,b,c,d, e,f,g;     }
52 struct s8       { S a,b,c,d, e,f,g,h;   }
53 struct s9       { S a,b,c,d, e,f,g,h, i;  }
54 struct s10      { S a,b,c,d, e,f,g,h, i,j;}
55 
56 struct i        { I a;          }       struct l        { L a;          }
57 struct ii       { I a,b;        }       struct ll       { L a,b;        }
58 struct iii      { I a,b,c;      }       struct lll      { L a,b,c;      }
59 struct iiii     { I a,b,c,d;    }       struct llll     { L a,b,c,d;    }
60 struct iiiii    { I a,b,c,d,e;  }       struct lllll    { L a,b,c,d,e;  }
61 
62 struct f        { F a;          }       struct d        { D a;          }
63 struct ff       { F a,b;        }       struct dd       { D a,b;        }
64 struct fff      { F a,b,c;      }       struct ddd      { D a,b,c;      }
65 struct ffff     { F a,b,c,d;    }       struct dddd     { D a,b,c,d;    }
66 struct fffff    { F a,b,c,d,e;  }       struct ddddd    { D a,b,c,d,e;  }
67 
68 // Mixed Size
69 
70 struct js       { I a;   S b;   }
71 struct iss      { I a;   S b,c; }
72 struct  si      { S a;   I b;   }
73 struct ssi      { S a,b; I c;   }
74 struct sis      { S a;   I b;  S c; }
75 
76 struct ls       { L a;   S b;   }
77 struct lss      { L a;   S b,c; }
78 struct  sl      { S a;   L b;   }
79 struct ssl      { S a,b; L c;   }
80 struct sls      { S a;   L b;  S c; }
81 
82 struct li       { L a;   I b;   }
83 struct lii      { L a;   I b,c; }
84 struct  il      { I a;   L b;   }
85 struct iil      { I a,b; L c;   }
86 struct ili      { I a;   L b;  I c; }
87 
88 struct df       { D a;   F b;   }
89 struct dff      { D a;   F b,c; }
90 struct  fd      { F a;   D b;   }
91 struct ffd      { F a,b; D c;   }
92 struct fdf      { F a;   D b;  F c; }
93 
94 // Mixed Types
95 
96 struct fi       { F a;   I b;   }
97 struct fii      { F a;   I b,c; }
98 struct  jf      { I a;   F b;   }
99 struct iif      { I a,b; F c;   }
100 struct ifi      { I a;   F b;  I c; }
101 
102 struct ffi      { F a,b; I c;           }
103 struct ffii     { F a,b; I c,d;         }
104 struct  iff     { I a;   F b,c;         }
105 struct iiff     { I a,b; F c,d;         }
106 struct ifif     { I a;   F b;  I c; F d;}
107 
108 struct di       { D a;   I b;   }
109 struct dii      { D a;   I b,c; }
110 struct  id      { I a;   D b;   }
111 struct iid      { I a,b; D c;   }
112 struct idi      { I a;   D b;  I c; }
113 
114 // Real ( long double )
115 
116 struct r        { R a;          }
117 struct rr       { R a,b;        }
118 struct rb       { R a;   B b;   }
119 struct rf       { R a;   F b;   }
120 struct fr       { F a;   R b;   }
121 
122                 // Int Registers only
123 alias tuple!(   b,bb,bbb,bbbb,bbbbb,
124                 b6, b7, b8, b9, b10,
125                 b11,b12,b13,b14,b15,
126                 b16,b17,b18,b19,b20,
127                 s,ss,sss,ssss,sssss,
128                 s6, s7, s8, s9, s10,
129                 i,ii,iii,iiii,iiiii,
130                 l,ll,lll,llll,lllll,
131                 //
132                 js,iss,si,ssi, sis,
133                 ls,lss,sl,ssl, sls,
134                 li,lii,il,iil, ili,
135                 fi,fii,jf,iif, ifi,
136                 ffi,ffii,iff,iiff,ifif, // INT_END
137 
138                 // SSE registers only
139                 f,ff,fff,ffff,fffff,
140                 d,dd,ddd,dddd,ddddd,
141                 //
142                 df,dff,fd,ffd, fdf,     // SSE_END
143 
144                 // Int and SSE
145                 di,  dii,id, iid, idi,  // MIX_END
146                 // ---
147             ) ALL_T;
148 
149 enum INT_END = 65;
150 enum SSE_END = 80;
151 enum MIX_END = ALL_T.length;
152 
153                 // x87
154 alias tuple!(   r,rr,rb,rf,fr,
155                 // ---
156             ) R_T;
157 //"r","rr","rb","rf","fr",
158 
159 
160 string[] ALL_S=[
161                 "b","bb","bbb","bbbb","bbbbb",
162                 "b6", "b7", "b8", "b9", "b10",
163                 "b11","b12","b13","b14","b15",
164                 "b16","b17","b18","b19","b20",
165                 "s","ss","sss","ssss","sssss",
166                 "s6","s7","s8","s9" , "s10",
167                 "i","ii","iii","iiii","iiiii",
168                 "l","ll","lll","llll","lllll",
169                 // ---
170                 "js","iss","si","ssi", "sis",
171                 "ls","lss","sl","ssl", "sls",
172                 "li","lii","il","iil", "ili",
173                 "fi","fii","jf","iif", "ifi",
174                 "ffi","ffii","iff","iiff","ifif",
175                 // ---
176                 "f","ff","fff","ffff","fffff",
177                 "d","dd","ddd","dddd","ddddd",
178                 "df","dff","fd","ffd", "dfd",
179                 // ---
180                 "di","dii","id","iid","idi",
181                ];
182 
183 /* ***********************************************************************
184                                    All
185  ************************************************************************/
186 // test1 Struct passing and return
187 
188 int[MIX_END] results_1;
189 
test1_out(T)190 T test1_out(T)( )
191 {
192         T t;
193         foreach( i, ref e; t.tupleof )  e = i+1;
194         return t;
195 }
test1_inout(T)196 T test1_inout(T)( T t)
197 {
198         foreach( i, ref e; t.tupleof )  e += 10;
199         return t;
200 }
201 
test1_call_out(T)202 void test1_call_out(T)( int n )
203 {
204         T t1;
205         foreach( i, ref e; t1.tupleof ) e = i+1;
206         T t2 = test1_out!(T)();
207 
208         if( t1 == t2 ) results_1[n] |= 1;
209 }
test1_call_inout(T)210 void test1_call_inout(T)( int n )
211 {
212         T t1;
213         foreach( i, ref e; t1.tupleof ) e = i+1;
214         T t2 = test1_inout!(T)( t1 );
215         foreach( i, ref e; t1.tupleof ) e += 10;
216 
217         if( t1 == t2 ) results_1[n] |= 2;
218 }
219 
D_test1()220 void D_test1( )
221 {
222         // Run Tests
223         foreach( n, T; ALL_T )
224         {
225                 test1_call_out!(T)(n);
226                 test1_call_inout!(T)(n);
227         }
228 
229         bool pass = true;
230         foreach( i, r; results_1 )
231         {
232                 if( ~r & 1 )
233                 {
234                 pass = false;
235                 printf( "Test1   out %s \tFail\n", ALL_S[i].ptr );
236                 }
237                 if( ~r & 2 )
238                 {
239                 pass = false;
240                 printf( "Test1 inout %s \tFail\n", ALL_S[i].ptr );
241                 }
242         }
243         assert( pass );
244 
245         results_1[0..5] = 0;
246         foreach( n, T; R_T )
247         {
248                 test1_call_out!(T)(n);
249                 test1_call_inout!(T)(n);
250         }
251 }
252 
253 /************************************************************************/
254 // based on runnable/test23.d : test44()
255 // Return Struct into an Array
256 
257 struct S1
258 {       int i,j;
259 
fooS1260         static S1 foo(int x)
261         {       S1 s;
262                 s.i = x;
263                 return s;
264 }       }
265 struct S2
266 {       int i,j,k;
267 
foo(int x)268         static S2 foo(int x)
269         {       S2 s;
270                 s.i = x;
271                 return s;
272 }       }
273 struct S3
274 {       float i,j;
275 
fooS3276         static S3 foo(int x)
277         {       S3 s;
278                 s.i = x;
279                 return s;
280 }       }
281 struct S4
282 {       float i,j,k;
283 
foo(int x)284         static S4 foo(int x)
285         {       S4 s;
286                 s.i = x;
287                 return s;
288 }       }
289 struct S5
290 {       float i,j;
291         int   k;
292 
fooS5293         static S5 foo(float x)
294         {       S5 s;
295                 s.i = x;
296                 return s;
297 }       }
298 
D_test2()299 void D_test2()
300 {
301         S1[] s1;
302         S2[] s2;
303         S3[] s3;
304         S4[] s4;
305         S5[] s5;
306 
307         s1 = s1 ~ S1.foo(6);    s1 = s1 ~ S1.foo(1);
308         s2 = s2 ~ S2.foo(6);    s2 = s2 ~ S2.foo(1);
309         s3 = s3 ~ S3.foo(6);    s3 = s3 ~ S3.foo(1);
310         s4 = s4 ~ S4.foo(6);    s4 = s4 ~ S4.foo(1);
311         s5 = s5 ~ S5.foo(6);    s5 = s5 ~ S5.foo(1);
312 
313         assert( s1.length == 2 );
314         assert( s1[0].i == 6 );
315         assert( s1[1].i == 1 );
316 
317         assert( s2.length == 2 );
318         assert( s2[0].i == 6 );
319         assert( s2[1].i == 1 );
320 
321 /+      // These Fail on Mainline DMD64 ( Should pass! )
322         assert( s3.length == 2 );
323         assert( s3[0].i == 6 );
324         assert( s3[1].i == 1 );
325 
326         assert( s4.length == 2 );
327         assert( s4[0].i == 6 );
328         assert( s4[1].i == 1 );
329 +/
330         assert( s5.length == 2 );
331         assert( s5[0].i == 6 );
332         assert( s5[1].i == 1 );
333 
334 }
335 
336 /* ***********************************************************************
337                                 X86_64
338  ************************************************************************/
339 
version(Run_X86_64_Tests)340 version(Run_X86_64_Tests)
341 {
342 
343 
344 struct TEST
345 {
346         immutable int       num;
347         immutable string    desc;
348         bool[MIX_END] result;
349 }
350 
351 /**
352  * 0 = Should Fail
353  * 1 = Should Pass
354  */
355 immutable int[MIX_END] expected =
356         [
357         1,1,1,1,1, // b
358         1,1,1,1,1, // b6
359         1,1,1,1,1, // b11
360         1,0,0,0,0, // b16
361 
362         1,1,1,1,1, // s
363         1,1,1,0,0, // s6
364         1,1,1,1,0, // i
365         1,1,0,0,0, // l
366         1,1,1,1,1, // si mix
367         1,1,1,1,0, // sl
368         1,1,1,1,0, // il
369         1,1,1,1,1, // int and float
370         1,1,1,1,1, // int and float
371 
372         // SSE regs only
373         1,1,1,1,0, // f
374         1,1,0,0,0, // d
375         1,1,1,1,0, // float and double
376 
377         // SSE + INT regs
378         1,1,1,1,0, // int and double
379         ];
380 
381 
382 /**
383  * Describes value expected in registers
384  *
385  * null means do not test
386  * ( because value is passed on the stack ).
387  */
388 
389 immutable long[][] RegValue =
390         [
391 /*   0  b       */ [ 0x0000000000000001,                    ],
392 /*   1  bb      */ [ 0x0000000000000201,                    ],
393 /*   2  bbb     */ [ 0x0000000000030201,                    ],
394 /*   3  bbbb    */ [ 0x0000000004030201,                    ],
395 /*   4  bbbbb   */ [ 0x0000000504030201,                    ],
396 /*   5  b6      */ [ 0x0000060504030201,                    ],
397 /*   6  b7      */ [ 0x0007060504030201,                    ],
398 /*   7  b8      */ [ 0x0807060504030201,                    ],
399 /*   8  b9      */ [ 0x0807060504030201, 0x0000000000000009 ],
400 /*   9  b10     */ [ 0x0807060504030201, 0x0000000000000a09 ],
401 /*  10  b11     */ [ 0x0807060504030201, 0x00000000000b0a09 ],
402 /*  11  b12     */ [ 0x0807060504030201, 0x000000000c0b0a09 ],
403 /*  12  b13     */ [ 0x0807060504030201, 0x0000000d0c0b0a09 ],
404 /*  13  b14     */ [ 0x0807060504030201, 0x00000e0d0c0b0a09 ],
405 /*  14  b15     */ [ 0x0807060504030201, 0x000f0e0d0c0b0a09 ],
406 /*  15  b16     */ [ 0x0807060504030201, 0x100f0e0d0c0b0a09 ],
407 /*  16  b17     */ null,
408 /*  17  b18     */ null,
409 /*  18  b19     */ null,
410 /*  19  b20     */ null,
411 /*  20  s       */ [ 0x0000000000000001,                    ],
412 /*  21  ss      */ [ 0x0000000000020001,                    ],
413 /*  22  sss     */ [ 0x0000000300020001,                    ],
414 /*  23  ssss    */ [ 0x0004000300020001,                    ],
415 /*  24  sssss   */ [ 0x0004000300020001, 0x0000000000000005 ],
416 /*  25  s6      */ [ 0x0004000300020001, 0x0000000000060005 ],
417 /*  26  s7      */ [ 0x0004000300020001, 0x0000000700060005 ],
418 /*  27  s8      */ [ 0x0004000300020001, 0x0008000700060005 ],
419 /*  28  s9      */ null,
420 /*  29  s10     */ null,
421 /*  30  i       */ [ 0x0000000000000001,                    ],
422 /*  31  ii      */ [ 0x0000000200000001,                    ],
423 /*  32  iii     */ [ 0x0000000200000001, 0x0000000000000003 ],
424 /*  33  iiii    */ [ 0x0000000200000001, 0x0000000400000003 ],
425 /*  34  iiiii   */ null,
426 /*  35  l       */ [ 0x0000000000000001,                    ],
427 /*  36  ll      */ [ 0x0000000000000001, 0x0000000000000002 ],
428 /*  37  lll     */ null,
429 /*  38  llll    */ null,
430 /*  39  lllll   */ null,
431 
432 /*  40  js      */ [ 0x0000000200000001,                    ],
433 /*  41  iss     */ [ 0x0003000200000001,                    ],
434 /*  42  si      */ [ 0x0000000200000001,                    ],
435 /*  43  ssi     */ [ 0x0000000300020001,                    ],
436 /*  44  sis     */ [ 0x0000000200000001, 0x0000000000000003 ],
437 /*  45  ls      */ [ 0x0000000000000001, 0x0000000000000002 ],
438 /*  46  lss     */ [ 0x0000000000000001, 0x0000000000030002 ],
439 /*  47  sl      */ [ 0x0000000000000001, 0x0000000000000002 ],
440 /*  48  ssl     */ [ 0x0000000000020001, 0x0000000000000003 ],
441 /*  49  sls     */ null,
442 /*  50  li      */ [ 0x0000000000000001, 0x0000000000000002 ],
443 /*  51  lii     */ [ 0x0000000000000001, 0x0000000300000002 ],
444 /*  52  il      */ [ 0x0000000000000001, 0x0000000000000002 ],
445 /*  53  iil     */ [ 0x0000000200000001, 0x0000000000000003 ],
446 /*  54  ili     */ null,
447 
448 /*  55  fi      */ [ 0x000000023f800000,                    ],
449 /*  56  fii     */ [ 0x000000023f800000, 0x0000000000000003 ],
450 /*  57  jf      */ [ 0x4000000000000001,                    ],
451 /*  58  iif     */ [ 0x0000000200000001, 0x0000000040400000 ],
452 /*  59  ifi     */ [ 0x4000000000000001, 0x0000000000000003 ],
453 
454 /*  60  ffi     */ [ 0x0000000000000003, 0x400000003f800000 ],
455 /*  61  ffii    */ [ 0x0000000400000003, 0x400000003f800000 ],
456 /*  62  iff     */ [ 0x4000000000000001, 0x0000000040400000 ],
457 /*  63  iiff    */ [ 0x0000000200000001, 0x4080000040400000 ],
458 /*  64  ifif    */ [ 0x4000000000000001, 0x4080000000000003 ],
459 
460 /*  65  f       */ [ 0x000000003f800000,                    ],
461 /*  66  ff      */ [ 0x400000003f800000,                    ],
462 /*  67  fff     */ [ 0x400000003f800000, 0x0000000040400000 ],
463 /*  68  ffff    */ [ 0x400000003f800000, 0x4080000040400000 ],
464 /*  69  fffff   */ null,
465 /*  70  d       */ [ 0x3ff0000000000000,                    ],
466 /*  71  dd      */ [ 0x3ff0000000000000, 0x4000000000000000 ],
467 /*  72  ddd     */ null,
468 /*  73  dddd    */ null,
469 /*  74  ddddd   */ null,
470 
471 /*  75  df      */ [ 0x3ff0000000000000, 0x0000000040000000 ],
472 /*  76  dff     */ [ 0x3ff0000000000000, 0x4040000040000000 ],
473 /*  77  fd      */ [ 0x000000003f800000, 0x4000000000000000 ],
474 /*  78  ffd     */ [ 0x400000003f800000, 0x4008000000000000 ],
475 /*  79  fdf     */ null,
476 
477 /*  80  di      */ [ 0x3ff0000000000000, 0x0000000000000002 ],
478 /*  81  dii     */ [ 0x3ff0000000000000, 0x0000000300000002 ],
479 /*  82  id      */ [ 0x4000000000000000, 0x0000000000000001 ],
480 /*  83  iid     */ [ 0x4008000000000000, 0x0000000200000001 ],
481 /*  84  idi     */ null,
482         ];
483 
484 /* Have to do it this way for OSX: Issue 7354 */
485 __gshared long[2] dump;
486 
487 /**
488  * Generate Register capture
489  */
490 string gen_reg_capture( int n, string registers )( )
491 {
492         if( RegValue[n] == null ) return "return;";
493 
494         string[] REG = mixin(registers); // ["RDI","RSI"];
495 
496         // Which type of compare
497         static if(n < INT_END)
498                 enum MODE = 1; // Int
499         else static if(n < SSE_END)
500                 enum MODE = 2; // Float
501         else    enum MODE = 3; // Mix
502 
503         /* Begin */
504 
505         string code = "asm {\n";
506 
507         final switch( MODE )
508         {
509                 case 1: code ~= "mov [dump], "~REG[0]~";\n";
510                         REG = REG[1..$];
511                 break;
512                 case 2:
513                 case 3: code ~= "movq [dump], XMM0;\n";
514         }
515 
516         if( RegValue[n].length == 2 )
517         final switch( MODE )
518         {
519                 case 1:
520                 case 3: code ~= "mov [dump+8], "~REG[0]~";\n";
521                 break;
522                 case 2: code ~= "movq [dump+8], XMM1;\n";
523         } else {
524                 code ~= "xor R8, R8;\n";
525                 code ~= "mov [dump+8], R8;\n";
526         }
527 
528         return code ~ "}\n";
529 }
530 
531 /**
532  * Check the results
533  */
534 bool check( TEST data )
535 {
536         bool pass = true;
537         foreach( i, e; expected )
538         {
539                 if( data.result[i] != (e & 1) )
540                 {
541                         printf( "Test%d %s \tFail\n", data.num, ALL_S[i].ptr);
542                         pass = false;
543                 }
544         }
545         return pass;
546 }
547 
548 /************************************************************************/
549 
550 // test1 Return Struct in Registers
551 // ( if RDI == 12 we have no hidden pointer )
552 
553 TEST data1 = { 1, "RDI hidden pointer" };
554 
555 T test1_asm( T, int n )( int i )
556 {
557         asm {
558 
559         cmp EDI, 12;
560         je L1;
561 
562         leave; ret;
563         }
564 L1:
565         data1.result[n] = true;
566 }
567 
568 void test1()
569 {
570         printf("\nRunning iasm Test 1 ( %s )\n", data1.desc.ptr);
571 
572         foreach( int n, T; ALL_T )
573                 test1_asm!(T,n)(12);
574 
575         check( data1 );
576 }
577 
578 /************************************************************************/
579 // test2 Pass Struct in Registers
580 // ( if RDI == 0 we have no stack pointer )
581 
582 TEST data2 = { 2, "RDI struct pointer" };
583 
584 T test2_asm( T, int n )( T t )
585 {
586         asm {
587 
588         mov [dump], RDI;
589         mov [dump+8], RSP;
590         cmp EDI, 0; // TODO test RDI is a ptr to stack ? ?
591         je L1;
592 
593         leave; ret;
594         }
595 L1:
596         data2.result[n] = true;
597 }
598 T test2f_asm( T, int n )( T t, int x )
599 {
600         asm {
601 
602         cmp EDI, 12;
603         je L1;
604 
605         leave; ret;
606         }
607 L1:
608         data2.result[n] = true;
609 }
610 
611 void test2()
612 {
613         printf("\nRunning iasm Test 2 ( %s )\n", data2.desc.ptr);
614 
615         // Integer
616         foreach( int n, T; ALL_T ) {
617                 T t = { 0 };
618                 test2_asm!(T,n)( t );
619         }
620 
621         // float alternative test
622         foreach( int n, T; ALL_T[INT_END..SSE_END] )
623         {
624                 enum n2 = n + INT_END;
625                 data2.result[n2] = false;
626                 test2f_asm!(T,n2)( T.init, 12 );
627         }
628 
629         check( data2 );
630 }
631 
632 /************************************************************************/
633 // test3
634 
635 TEST data3 = { 3, "Check Return Register value" };
636 
637 void test3_run( T, int n )( )
638 {
639         test3_ret!T();
640         mixin( gen_reg_capture!(n,`["RAX","RDX"]`)() );
641 
642         //dbg!(T,n)( );
643 
644         enum len = RegValue[n].length;
645         if( dump[0..len] == RegValue[n] )
646                 data3.result[n] = true;
647 }
648 
649 T test3_ret( T )( )
650 {
651         T t;
652         foreach( i, ref e; t.tupleof )  e = i+1;
653         return t;
654 }
655 
656 void test3()
657 {
658         printf("\nRunning iasm Test 3 ( %s )\n", data3.desc.ptr);
659 
660         foreach( int n, T; ALL_T )
661                 test3_run!(T,n)( );
662 
663         check( data3 );
664 }
665 
666 /************************************************************************/
667 // test4
668 
669 TEST data4 = { 4, "Check Input Register value" };
670 
671 void test4_run( T, int n )( T t )
672 {
673         mixin( gen_reg_capture!(n,`["RDI","RSI"]`)() );
674 
675         //dbg!(T,n)( );
676 
677         enum len = RegValue[n].length;
678         if( dump[0..len] == RegValue[n] )
679                 data4.result[n] = true;
680 }
681 
682 void dbg( T, int n )( )
683 {
684         import std.stdio;
685         writefln( "D %s\t[ %16x, %16x ]", T.stringof, dump[0], dump[1], );
686         writef(   "C %s\t[ %16x", T.stringof, RegValue[n][0] );
687         if( RegValue[n].length == 2 )
688         writef( ", %16x", RegValue[n][1] );
689         writefln( " ]" );
690 }
691 void test4()
692 {
693         printf("\nRunning iasm Test 4 ( %s )\n", data4.desc.ptr);
694 
695         foreach( int n, T; ALL_T )
696         {
697                 T t;
698                 foreach( i, ref e; t.tupleof )  e = i+1;
699                 test4_run!(T,n)( t );
700         }
701         check( data4 );
702 }
703 
704 
705 } // end version(Run_X86_64_Tests)
706 
707 /************************************************************************/
708 
709 
main()710 void main()
711 {
712         D_test1();
713         D_test2();
714 
715         version(Run_X86_64_Tests)
716         {
717                 test1();
718                 test2();
719                 test3();
720                 test4();
721         }
722 }
723 
724 /+
725 /**
726  * C code to generate the table RegValue
727  */
728 string c_generate_returns()
729 {
730         string value =  " 1, 2, 3, 4, 5, 6, 7, 8, 9,10,"
731                         "11,12,13,14,15,16,17,18,19,20,";
732 
733         string code = "#include \"cgen.h\"\n";
734 
735         // Generate return functions
736         foreach( int n, T; ALL_T )
737         {
738                 auto Ts  = T.stringof;
739                 auto len = T.tupleof.length;
740 
741                 code ~= "struct "~Ts~" func_ret_"~Ts~"(void) { \n";
742                 code ~= "struct "~Ts~" x = { ";
743                 code ~= value[0..len*3] ~ " };\n";
744                 code ~= "return x;\n}\n";
745         }
746         return code;
747 }
748 string c_generate_pass()
749 {
750         string value =  " 1, 2, 3, 4, 5, 6, 7, 8, 9,10,"
751                         "11,12,13,14,15,16,17,18,19,20,";
752 
753         string code;
754 
755         // Generate return functions
756         foreach( int n, T; ALL_T )
757         {
758                 auto Ts  = T.stringof;
759                 auto len = T.tupleof.length;
760 
761                 code ~= "void func_pass_"~Ts~"( struct "~Ts~" x ) {\n";
762                 ////////////////
763                 // Which type of compare
764                 static if(n < INT_END)
765                         enum MODE = 1; // Int
766                 else static if(n < SSE_END)
767                         enum MODE = 2; // Float
768                 else    enum MODE = 3; // Mix
769 
770                 auto nn  = n.stringof;
771 
772                 /* Begin */
773 
774                 code ~= "asm(\n";
775                 final switch( MODE )
776                 {
777                 case 1:
778                 code ~= `"movq  %rdi, reg\n" "movq  %rsi, reg+8\n"`;
779                 break;
780                 case 2:
781                 code ~= `"movq %xmm0, reg\n" "movq %xmm1, reg+8\n"`;
782                 break;
783                 case 3:
784                 code ~= `"movq %xmm0, reg\n" "movq  %rdi, reg+8\n"`;
785                 }
786                 code ~= "\n);\n";
787                 code ~= "}\n";
788 
789                 ////////////////
790                 code ~= "void func_call_"~Ts~"( void ) {\n";
791                 code ~= "struct "~Ts~" x = { ";
792                 code ~= value[0..len*3] ~ " };\n";
793                 code ~= "func_pass_"~Ts~"( x );\n}\n";
794         }
795         return code;
796 }
797 string c_generate_main()
798 {
799         string code = "void main() {\n";
800 
801         foreach( int n, T; ALL_T )
802         {
803                 // Which type of compare
804                 static if(n < INT_END)
805                         enum MODE = 1; // Int
806                 else static if(n < SSE_END)
807                         enum MODE = 2; // Float
808                 else    enum MODE = 3; // Mix
809 
810                 auto nn  = n.stringof;
811                 auto Ts  = T.stringof;
812 
813                 /* Begin */
814 
815                 code ~= `printf("/* %3d  `~Ts~`\t*/ ", `~nn~`);`"\n";
816                 if( !(expected[n] & 1) )
817                 {
818                         code ~= `printf("null,\n");`"\n";
819                         continue;
820                 }
821                 code ~= "asm(\n";
822                 code ~= `"call func_ret_`~Ts~`\n"`"\n";
823                 final switch( MODE )
824                 {
825                 case 1:
826                 code ~= `"movq  %rax, reg\n" "movq  %rdx, reg+8\n"`;
827                 break;
828                 case 2:
829                 code ~= `"movq %xmm0, reg\n" "movq %xmm1, reg+8\n"`;
830                 break;
831                 case 3:
832                 code ~= `"movq %xmm0, reg\n" "movq  %rax, reg+8\n"`;
833                 }
834                 code ~= "\n);\n";
835 
836                 code ~= `printf("[ 0x%016lx", reg.r1 );`"\n";
837 
838                 if( T.sizeof > 8  || MODE == 3 )
839                         code ~= `printf(", 0x%016lx ],\n", reg.r2 );`"\n";
840                 else    code ~= `printf(",   %015c  ],\n", ' '    );`"\n";
841         }
842 
843         foreach( int n, T; ALL_T )
844         {
845                 // Which type of compare
846                 static if(n < INT_END)
847                         enum MODE = 1; // Int
848                 else static if(n < SSE_END)
849                         enum MODE = 2; // Float
850                 else    enum MODE = 3; // Mix
851 
852                 auto nn  = n.stringof;
853                 auto Ts  = T.stringof;
854 
855                 /* Begin */
856 
857                 code ~= `printf("/* %3d  `~Ts~`\t*/ ", `~nn~`);`"\n";
858                 if( !(expected[n] & 1) )
859                 {
860                         code ~= `printf("null,\n");`"\n";
861                         continue;
862                 }
863                 code ~= "func_call_"~Ts~"();\n";
864 
865                 code ~= `printf("[ 0x%016lx", reg.r1 );`"\n";
866 
867                 if( T.sizeof > 8  || MODE == 3 )
868                         code ~= `printf(", 0x%016lx ],\n", reg.r2 );`"\n";
869                 else    code ~= `printf(",   %015c  ],\n", ' '    );`"\n";
870         }
871 
872 
873         return code ~ "}";
874 }
875 pragma(msg, c_generate_returns() );
876 pragma(msg, c_generate_pass() );
877 pragma(msg, c_generate_main() );
878 // +/
879 
880 /+
881 /**
882  * Generate Functions that pass/return each Struct type
883  *
884  * ( Easier to look at objdump this way )
885  */
886 string d_generate_functions( )
887 {
888         string code = "extern(C) {";
889 
890         // pass
891         foreach( s; ALL_T )
892         {
893                 string ss = s.stringof;
894 
895                 code ~= "void func_in_"~ss~"( "~ss~" t ) { t.a = 12; }\n";
896         }
897         // return
898         foreach( s; ALL_T[0..10] )
899         {
900                 string ss = s.stringof;
901 
902                 code ~= `
903                 auto func_out_`~ss~`()
904                 {
905                         `~ss~` t;
906                         foreach( i, ref e; t.tupleof )  e = i+1;
907                         return t;
908                 }`;
909         }
910         // pass & return
911         foreach( s; ALL_T[0..10] )
912         {
913                 string ss = s.stringof;
914 
915                 code ~= `
916                 auto func_inout_`~ss~`( `~ss~` t )
917                 {
918                         foreach( i, ref e; t.tupleof )  e += 10;
919                         return t;
920                 }`;
921         }
922         return code ~ "\n} // extern(C)\n";
923 }
924 //pragma( msg, d_generate_functions() );
925 mixin( d_generate_functions() );
926 // +/
927