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