1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovunsigned int btsl_mem ( unsigned char* base, int bitno )
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btsl\t%2, %0\n\t"
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno));
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Pretty meaningless to dereference base here, but that's what you
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to do to get a btsl insn which refers to memory starting at
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      base. */
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovunsigned int btrl_mem ( unsigned char* base, int bitno )
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btrl\t%2, %0\n\t"
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno));
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovunsigned int btcl_mem ( unsigned char* base, int bitno )
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btcl\t%2, %0\n\t"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno));
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovunsigned int btl_mem ( unsigned char* base, int bitno )
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btl\t%2, %0\n\t"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno)
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "memory");
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned int btsl_reg ( unsigned int reg_in, int bitno,
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned int* reg_out_p )
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned int reg_out;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movl\t%3, %%eax\n\t"
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btsl\t%2, %%eax\n\t"
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "movl\t%%eax, %1\n\t"
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%0"
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=q" (res), "=r" (reg_out)
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno), "r" (reg_in)
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "eax");
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *reg_out_p = reg_out;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned int btrl_reg ( unsigned int reg_in, int bitno,
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned int* reg_out_p )
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned int reg_out;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movl\t%3, %%eax\n\t"
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btrl\t%2, %%eax\n\t"
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "movl\t%%eax, %1\n\t"
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%0"
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=q" (res), "=r" (reg_out)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno), "r" (reg_in)
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "eax");
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *reg_out_p = reg_out;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned int btcl_reg ( unsigned int reg_in, int bitno,
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unsigned int* reg_out_p )
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned int reg_out;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movl\t%3, %%eax\n\t"
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btcl\t%2, %%eax\n\t"
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "movl\t%%eax, %1\n\t"
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%0"
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=q" (res), "=r" (reg_out)
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno), "r" (reg_in)
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "eax");
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *reg_out_p = reg_out;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunsigned int btl_reg ( unsigned int reg_in, int bitno,
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       unsigned int* reg_out_p )
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned char res;
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned int reg_out;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movl\t%3, %%eax\n\t"
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btl\t%2, %%eax\n\t"
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "movl\t%%eax, %1\n\t"
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%0"
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=q" (res), "=r" (reg_out)
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno), "r" (reg_in)
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "eax");
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *reg_out_p = reg_out;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned int UInt;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned char UChar;
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt rol1 ( UInt x )
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return (x << 1) | (x >> 31);
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main ( void )
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   n, bitoff, op;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   carrydep, c, res;
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* block;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   reg;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*------------------------ MEM-L -----------------------*/
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   carrydep = 0;
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block = calloc(200,1);
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block += 100;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Valid bit offsets are -800 .. 799 inclusive. */
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (n = 0; n < 10000; n++) {
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bitoff = (random() % 1600) - 800;
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op = random() % 4;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = 2;
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op) {
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: c = btsl_mem(block, bitoff); break;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: c = btrl_mem(block, bitoff); break;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: c = btcl_mem(block, bitoff); break;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3: c = btl_mem(block, bitoff); break;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert(c == 0 || c == 1);
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep;
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute final result */
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block -= 100;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = 0;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (n = 0; n < 200; n++) {
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar ch = block[n];
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* printf("%d ", (int)block[n]); */
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = rol1(res) ^ (UInt)ch;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("MEM-L: final res 0x%x, carrydep 0x%x\n", res, carrydep);
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*------------------------ REG-L -----------------------*/
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   carrydep = 0;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reg = 0;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (n = 0; n < 1000; n++) {
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bitoff = (random() % 100) - 50;
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op = random() % 4;
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = 2;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (op) {
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: c = btsl_reg(reg, bitoff, &reg); break;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: c = btrl_reg(reg, bitoff, &reg); break;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: c = btcl_reg(reg, bitoff, &reg); break;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3: c = btl_reg(reg, bitoff, &reg); break;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert(c == 0 || c == 1);
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("REG-L: final res 0x%x, carrydep 0x%x\n", reg, carrydep);
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block += 100;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Just try one of these at once; more than one can cause a
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      confusing merging of error messages. */
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //btsl_mem(block, -800);  /* should not complain */
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //btsl_mem(block, -801);  /* should complain */
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //btsl_mem(block, 799);   /* should not complain */
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //btsl_mem(block, 800);   /* should complain */
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block -= 100;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   free(block);
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218