1 2#include <stdio.h> 3#include <stdlib.h> 4#include <assert.h> 5 6unsigned 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 18unsigned 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 32unsigned 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 43unsigned 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 54unsigned 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 69unsigned 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 87unsigned 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 105unsigned 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 123unsigned 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 146typedef unsigned int UInt; 147typedef unsigned char UChar; 148 149UInt rol1 ( UInt x ) 150{ 151 return (x << 1) | (x >> 31); 152} 153 154int 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, ®); break; 204 case 1: c = btrl_reg(reg, bitoff, ®); break; 205 case 2: c = btcl_reg(reg, bitoff, ®); break; 206 case 3: c = btl_reg(reg, bitoff, ®); 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