Brian Silverman | 84b2223 | 2019-01-25 20:29:29 -0800 | [diff] [blame^] | 1 | # pycrc -- parameterisable CRC calculation utility and C source code generator |
| 2 | # |
| 3 | # Copyright (c) 2017 Thomas Pircher <tehpeh-web@tty1.net> |
| 4 | # |
| 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | # of this software and associated documentation files (the "Software"), to |
| 7 | # deal in the Software without restriction, including without limitation the |
| 8 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 9 | # sell copies of the Software, and to permit persons to whom the Software is |
| 10 | # furnished to do so, subject to the following conditions: |
| 11 | # |
| 12 | # The above copyright notice and this permission notice shall be included in |
| 13 | # all copies or substantial portions of the Software. |
| 14 | # |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 21 | # IN THE SOFTWARE. |
| 22 | |
| 23 | |
| 24 | """ |
| 25 | use as follows: |
| 26 | |
| 27 | import pycrc.codegen as cg |
| 28 | import pycrc.opt as opt |
| 29 | opt = opt.Options() |
| 30 | print(cg.CodeGen(opt, '', [ |
| 31 | 'if (a == b) {', |
| 32 | cg.CodeGen(opt, 4*' ', ['print("a equals b\\n");']), |
| 33 | '}', |
| 34 | ])) |
| 35 | """ |
| 36 | |
| 37 | import pycrc.symtable |
| 38 | import pycrc.expr as expr |
| 39 | |
| 40 | |
| 41 | class CodeGen(object): |
| 42 | """ |
| 43 | The symbol table class. |
| 44 | """ |
| 45 | def __init__(self, opt, indent, content = []): |
| 46 | """ |
| 47 | The class constructor. |
| 48 | """ |
| 49 | self.opt = opt |
| 50 | self.sym = pycrc.symtable.SymbolTable(opt) |
| 51 | self.indent = indent |
| 52 | self.content = content |
| 53 | |
| 54 | def gen(self, indent = ''): |
| 55 | """ |
| 56 | Return an array of strings. |
| 57 | """ |
| 58 | out = [] |
| 59 | if self.indent is None: |
| 60 | indent = '' |
| 61 | else: |
| 62 | indent += self.indent |
| 63 | for item in self.content: |
| 64 | if isinstance(item, str): |
| 65 | out.append(indent + item) |
| 66 | else: |
| 67 | out += item.gen(indent) |
| 68 | return out |
| 69 | |
| 70 | def __str__(self): |
| 71 | """ |
| 72 | Stringify the object. |
| 73 | """ |
| 74 | return '\n'.join([l.rstrip() for l in self.gen()]) |
| 75 | |
| 76 | |
| 77 | class Conditional(CodeGen): |
| 78 | """ |
| 79 | A conditional block of code. |
| 80 | """ |
| 81 | def __init__(self, opt, indent, condition, content): |
| 82 | """ |
| 83 | The class constructor. |
| 84 | """ |
| 85 | super(Conditional, self).__init__(opt, indent) |
| 86 | if condition: |
| 87 | self.content = content |
| 88 | |
| 89 | |
| 90 | class Conditional2(CodeGen): |
| 91 | """ |
| 92 | A conditional block of code with an else block. |
| 93 | """ |
| 94 | def __init__(self, opt, indent, condition, content_true, content_false): |
| 95 | """ |
| 96 | The class constructor. |
| 97 | """ |
| 98 | super(Conditional2, self).__init__(opt, indent) |
| 99 | if condition: |
| 100 | self.content = content_true |
| 101 | else: |
| 102 | self.content = content_false |
| 103 | |
| 104 | |
| 105 | class Comment(CodeGen): |
| 106 | """ |
| 107 | A comment wrapper. |
| 108 | """ |
| 109 | def __init__(self, opt, indent, content): |
| 110 | """ |
| 111 | The class constructor. |
| 112 | """ |
| 113 | super(Comment, self).__init__(opt, indent) |
| 114 | self.content = [ |
| 115 | '/**', |
| 116 | CodeGen(opt, indent + ' * ', content), |
| 117 | ' */' |
| 118 | ] |
| 119 | |
| 120 | |
| 121 | class ParamBlock(CodeGen): |
| 122 | """ |
| 123 | Print the parameters of the model. |
| 124 | """ |
| 125 | def __init__(self, opt, indent, algorithm = False): |
| 126 | """ |
| 127 | The class constructor. |
| 128 | """ |
| 129 | super(ParamBlock, self).__init__(opt, indent) |
| 130 | self.content = [ |
| 131 | '- {0:13s} = {1}'.format('Width', self.sym['crc_width']), |
| 132 | '- {0:13s} = {1}'.format('Poly', self.sym['crc_poly']), |
| 133 | '- {0:13s} = {1}'.format('XorIn', self.sym['crc_xor_in']), |
| 134 | '- {0:13s} = {1}'.format('ReflectIn', self.sym['crc_reflect_in']), |
| 135 | '- {0:13s} = {1}'.format('XorOut', self.sym['crc_xor_out']), |
| 136 | '- {0:13s} = {1}'.format('ReflectOut', self.sym['crc_reflect_out']), |
| 137 | Conditional(opt, '', algorithm, |
| 138 | ['- {0:13s} = {1}'.format('Algorithm', self.sym['crc_algorithm'])]), |
| 139 | Conditional(opt, '', opt.slice_by > 1, |
| 140 | ['- {0:13s} = {1}'.format('SliceBy', opt.slice_by)]), |
| 141 | ] |
| 142 | |
| 143 | |
| 144 | |
| 145 | class File(CodeGen): |
| 146 | """ |
| 147 | Generate the file output. |
| 148 | """ |
| 149 | def __init__(self, opt, indent): |
| 150 | """ |
| 151 | The class constructor. |
| 152 | """ |
| 153 | super(File, self).__init__(opt, indent) |
| 154 | self.content = [ |
| 155 | Comment(opt, '', [ |
| 156 | '\\file', |
| 157 | 'Functions and types for CRC checks.', |
| 158 | '', |
| 159 | 'Generated on {datetime}'.format(**self.sym), |
| 160 | 'by {program_version}, {program_url}'.format(**self.sym), |
| 161 | 'using the configuration:', |
| 162 | ParamBlock(opt, ' ', algorithm = True), |
| 163 | Conditional(opt, '', opt.action == opt.action_generate_h, [ |
| 164 | '', |
| 165 | 'This file defines the functions {crc_init_function}(), ' \ |
| 166 | '{crc_update_function}() and {crc_finalize_function}().'.format(**self.sym), |
| 167 | '', |
| 168 | 'The {crc_init_function}() function returns the inital \c crc value and must be called'.format(**self.sym), |
| 169 | 'before the first call to {crc_update_function}().'.format(**self.sym), |
| 170 | 'Similarly, the {crc_finalize_function}() function must be called after the last call'.format(**self.sym), |
| 171 | 'to {crc_update_function}(), before the \c crc is being used.'.format(**self.sym), |
| 172 | 'is being used.', |
| 173 | '', |
| 174 | 'The {crc_update_function}() function can be called any number of times (including zero'.format(**self.sym), |
| 175 | 'times) in between the {crc_init_function}() and {crc_finalize_function}() calls.'.format(**self.sym), |
| 176 | '', |
| 177 | 'This pseudo-code shows an example usage of the API:', |
| 178 | '\code{.c}', |
| 179 | Conditional(self.opt, '', self.opt.undefined_crc_parameters, [ |
| 180 | '{cfg_t} cfg = '.format(**self.sym) + '{', |
| 181 | Conditional(self.opt, 4*' ', self.opt.width is None, [ |
| 182 | '0, // width', |
| 183 | ]), |
| 184 | Conditional(self.opt, 4*' ', self.opt.poly is None, [ |
| 185 | '0, // poly', |
| 186 | ]), |
| 187 | Conditional(self.opt, 4*' ', self.opt.reflect_in is None, [ |
| 188 | '0, // reflect_in', |
| 189 | ]), |
| 190 | Conditional(self.opt, 4*' ', self.opt.xor_in is None, [ |
| 191 | '0, // xor_in', |
| 192 | ]), |
| 193 | Conditional(self.opt, 4*' ', self.opt.reflect_out is None, [ |
| 194 | '0, // reflect_out', |
| 195 | ]), |
| 196 | Conditional(self.opt, 4*' ', self.opt.xor_out is None, [ |
| 197 | '0, // xor_out', |
| 198 | ]), |
| 199 | Conditional(self.opt, 4*' ', self.opt.width is None, [ |
| 200 | '', |
| 201 | '0, // crc_mask', |
| 202 | '0, // msb_mask', |
| 203 | '0, // crc_shift', |
| 204 | ]), |
| 205 | '};', |
| 206 | ]), |
| 207 | '{crc_t} crc;'.format(**self.sym), |
| 208 | 'unsigned char data[MAX_DATA_LEN];', |
| 209 | 'size_t data_len;', |
| 210 | '', |
| 211 | Conditional(self.opt, '', _use_crc_table_gen(self.opt), [ |
| 212 | '{crc_table_gen_function}(&cfg);'.format(**self.sym), |
| 213 | ]), |
| 214 | 'crc = {0}({1});'.format(self.sym['crc_init_function'], '' if _use_constant_crc_init(self.sym) else '&cfg'), |
| 215 | 'while ((data_len = read_data(data, MAX_DATA_LEN)) > 0) {', |
| 216 | CodeGen(self.opt, 4*' ', [ |
| 217 | 'crc = {0}({1}crc, data, data_len);'.format(self.sym['crc_update_function'], '' if _use_cfg_in_crc_update(self.opt) else '&cfg, '), |
| 218 | ]), |
| 219 | '}', |
| 220 | 'crc = {0}({1}crc);'.format(self.sym['crc_finalize_function'], '' if _use_cfg_in_finalize(self.opt) else '&cfg, '), |
| 221 | '\endcode', |
| 222 | ]), |
| 223 | ]), |
| 224 | ] |
| 225 | if opt.action == opt.action_generate_h: |
| 226 | self.content += self._header_file() |
| 227 | elif opt.action == opt.action_generate_c: |
| 228 | self.content += self._c_file() |
| 229 | elif opt.action == opt.action_generate_c_main: |
| 230 | self.content += self._c_file() + self._main_file() |
| 231 | |
| 232 | def _header_file(self): |
| 233 | """ |
| 234 | Add header content. |
| 235 | """ |
| 236 | out = [ |
| 237 | '#ifndef {header_protection}'.format(**self.sym), |
| 238 | '#define {header_protection}'.format(**self.sym), |
| 239 | '', |
| 240 | CodeGen(self.opt, '', _includes(self.opt)), |
| 241 | '#include <stdlib.h>', |
| 242 | Conditional(self.opt, '', self.opt.c_std != 'C89', |
| 243 | ['#include <stdint.h>']), |
| 244 | Conditional(self.opt, '', _use_cfg(self.opt) and self.opt.c_std != 'C89', |
| 245 | ['#include <stdbool.h>']), |
| 246 | '', |
| 247 | '#ifdef __cplusplus', |
| 248 | 'extern "C" {', |
| 249 | '#endif', |
| 250 | '', '', |
| 251 | Comment(self.opt, '', [ |
| 252 | 'The definition of the used algorithm.', |
| 253 | '', |
| 254 | 'This is not used anywhere in the generated code, but it may be used by the', |
| 255 | 'application code to call algorithm-specific code, if desired.', |
| 256 | ]), |
| 257 | '#define {0} 1'.format(_crc_algo_define(self.opt, self.sym)), |
| 258 | '', '', |
| 259 | Comment(self.opt, self.indent, [ |
| 260 | 'The type of the CRC values.', |
| 261 | '', |
| 262 | 'This type must be big enough to contain at least {cfg_width} bits.'.format(**self.sym), |
| 263 | ]), |
| 264 | 'typedef {underlying_crc_t} {crc_t};'.format(**self.sym), |
| 265 | Conditional(self.opt, '', _use_cfg(self.opt), [ |
| 266 | '', '', |
| 267 | Comment(self.opt, self.indent, ['The configuration type of the CRC algorithm.']), |
| 268 | 'typedef struct {', |
| 269 | Conditional(self.opt, 4*' ', self.opt.width is None, |
| 270 | ['{0:24s} {1}'.format('unsigned int width;', |
| 271 | '/*!< The width of the polynomial */')]), |
| 272 | Conditional(self.opt, 4*' ', self.opt.poly is None, |
| 273 | ['{0:24s} {1}'.format(self.sym['crc_t'] + ' poly;', |
| 274 | '/*!< The CRC polynomial */')]), |
| 275 | Conditional(self.opt, 4*' ', self.opt.reflect_in is None, |
| 276 | ['{0:24s} {1}'.format(self.sym['c_bool'] + ' reflect_in;', |
| 277 | '/*!< Whether the input shall be reflected or not */')]), |
| 278 | Conditional(self.opt, 4*' ', self.opt.xor_in is None, |
| 279 | ['{0:24s} {1}'.format(self.sym['crc_t'] + ' xor_in;', |
| 280 | '/*!< The initial value of the register */')]), |
| 281 | Conditional(self.opt, 4*' ', self.opt.reflect_out is None, |
| 282 | ['{0:24s} {1}'.format(self.sym['c_bool'] + ' reflect_out;', |
| 283 | '/*!< Whether the output shall be reflected or not */')]), |
| 284 | Conditional(self.opt, 4*' ', self.opt.xor_out is None, |
| 285 | ['{0:24s} {1}'.format(self.sym['crc_t'] + ' xor_out;', |
| 286 | '/*!< The value which shall be XOR-ed to the final CRC value */')]), |
| 287 | Conditional(self.opt, 4*' ', self.opt.width is None, [ |
| 288 | '', |
| 289 | '/* internal parameters */', |
| 290 | '{0:24s} {1}'.format(self.sym['crc_t'] + ' msb_mask;', '/*!< a bitmask with the Most Significant Bit set to 1'), |
| 291 | 33*' ' + 'initialise as (crc_t)1u << (width - 1) */', |
| 292 | '{0:24s} {1}'.format(self.sym['crc_t'] + ' crc_mask;', '/*!< a bitmask with all width bits set to 1'), |
| 293 | 33*' ' + 'initialise as (cfg->msb_mask - 1) | cfg->msb_mask */', |
| 294 | '{0:24s} {1}'.format('unsigned int crc_shift;', '/*!< a shift count that is used when width < 8'), |
| 295 | 33*' ' + 'initialise as cfg->width < 8 ? 8 - cfg->width : 0 */', |
| 296 | ]), |
| 297 | '}} {cfg_t};'.format(**self.sym), |
| 298 | ]), |
| 299 | Conditional(self.opt, '', _use_reflect_func(self.opt) and not _use_static_reflect_func(self.opt), [ |
| 300 | '', '', |
| 301 | Comment(self.opt, '', [ |
| 302 | 'Reflect all bits of a \\a data word of \\a data_len bytes.', |
| 303 | '', |
| 304 | '\\param[in] data The data word to be reflected.', |
| 305 | '\\param[in] data_len The width of \\a data expressed in number of bits.', |
| 306 | '\\return The reflected data.' |
| 307 | ]), |
| 308 | '{crc_t} {crc_reflect_function}({crc_t} data, size_t data_len);'.format(**self.sym), |
| 309 | ]), |
| 310 | Conditional(self.opt, '', _use_crc_table_gen(self.opt), [ |
| 311 | '', '', |
| 312 | Comment(self.opt, '', [ |
| 313 | 'Populate the private static crc table.', |
| 314 | '', |
| 315 | '\\param[in] cfg A pointer to an initialised {cfg_t} structure.'.format(**self.sym), |
| 316 | ]), |
| 317 | 'void {crc_table_gen_function}(const {cfg_t} *cfg);'.format(**self.sym), |
| 318 | ]), |
| 319 | '', '', |
| 320 | Comment(self.opt, '', [ |
| 321 | 'Calculate the initial crc value.', |
| 322 | '', |
| 323 | Conditional(self.opt, '', _use_cfg(self.opt), [ |
| 324 | '\\param[in] cfg A pointer to an initialised {cfg_t} structure.'.format(**self.sym), |
| 325 | ]), |
| 326 | '\\return The initial crc value.', |
| 327 | ]), |
| 328 | Conditional2(self.opt, '', _use_constant_crc_init(self.sym), [ |
| 329 | Conditional2(self.opt, '', self.opt.c_std == 'C89', [ |
| 330 | '#define {crc_init_function}() ({crc_init_value})'.format(**self.sym), |
| 331 | ], [ |
| 332 | 'static inline {0}'.format(_crc_init_function_def(self.opt, self.sym)), |
| 333 | '{', |
| 334 | ' return {crc_init_value};'.format(**self.sym), |
| 335 | '}', |
| 336 | ]), |
| 337 | ], [ |
| 338 | '{0};'.format(_crc_init_function_def(self.opt, self.sym)), |
| 339 | ]), |
| 340 | '', '', |
| 341 | Comment(self.opt, '', [ |
| 342 | 'Update the crc value with new data.', |
| 343 | '', |
| 344 | '\\param[in] crc The current crc value.', |
| 345 | Conditional(self.opt, '', not _use_cfg_in_crc_update(self.opt), [ |
| 346 | '\\param[in] cfg A pointer to an initialised {cfg_t} structure.'.format(**self.sym), |
| 347 | ]), |
| 348 | '\\param[in] data Pointer to a buffer of \\a data_len bytes.', |
| 349 | '\\param[in] data_len Number of bytes in the \\a data buffer.', |
| 350 | '\\return The updated crc value.', |
| 351 | ]), |
| 352 | '{0};'.format(_crc_update_function_def(self.opt, self.sym)), |
| 353 | '', '', |
| 354 | Comment(self.opt, '', [ |
| 355 | 'Calculate the final crc value.', |
| 356 | '', |
| 357 | Conditional(self.opt, '', not _use_cfg_in_finalize(self.opt), [ |
| 358 | '\\param[in] cfg A pointer to an initialised {cfg_t} structure.'.format(**self.sym), |
| 359 | ]), |
| 360 | '\\param[in] crc The current crc value.', |
| 361 | '\\return The final crc value.', |
| 362 | ]), |
| 363 | Conditional2(self.opt, '', _use_inline_crc_finalize(self.opt), [ |
| 364 | Conditional2(self.opt, '', self.opt.c_std == 'C89', [ |
| 365 | '#define {0}(crc) ({1})'.format(self.sym['crc_finalize_function'], _crc_final_value(self.opt, self.sym)), |
| 366 | ], [ |
| 367 | 'static inline {0}'.format(_crc_finalize_function_def(self.opt, self.sym)), |
| 368 | '{', |
| 369 | ' return {0};'.format(_crc_final_value(self.opt, self.sym)), |
| 370 | '}', |
| 371 | ]), |
| 372 | ], [ |
| 373 | '{0};'.format(_crc_finalize_function_def(self.opt, self.sym)), |
| 374 | ]), |
| 375 | '', '', |
| 376 | '#ifdef __cplusplus', |
| 377 | '} /* closing brace for extern "C" */', |
| 378 | '#endif', |
| 379 | '', |
| 380 | '#endif /* {header_protection} */'.format(**self.sym), |
| 381 | '', |
| 382 | ] |
| 383 | return out |
| 384 | |
| 385 | def _c_file(self): |
| 386 | """ |
| 387 | Add C file content. |
| 388 | """ |
| 389 | out = [ |
| 390 | CodeGen(self.opt, '', _includes(self.opt)), |
| 391 | '#include "{header_filename}" /* include the header file generated with pycrc */'.format(**self.sym), |
| 392 | '#include <stdlib.h>', |
| 393 | Conditional(self.opt, '', self.opt.c_std != 'C89', [ |
| 394 | '#include <stdint.h>', |
| 395 | Conditional(self.opt, '', self.opt.undefined_crc_parameters or \ |
| 396 | self.opt.algorithm == self.opt.algo_bit_by_bit or \ |
| 397 | self.opt.algorithm == self.opt.algo_bit_by_bit_fast, [ |
| 398 | '#include <stdbool.h>', |
| 399 | ]), |
| 400 | ]), |
| 401 | Conditional(self.opt, '', self.opt.slice_by > 1, [ |
| 402 | '#include <endian.h>', |
| 403 | ]), |
| 404 | Conditional(self.opt, '', _use_reflect_func(self.opt) and _use_static_reflect_func(self.opt), [ |
| 405 | '', |
| 406 | 'static {crc_t} {crc_reflect_function}({crc_t} data, size_t data_len);'.format(**self.sym), |
| 407 | ]), |
| 408 | '', |
| 409 | CodeGen(self.opt, '', _crc_table(self.opt, self.sym)), |
| 410 | CodeGen(self.opt, '', _crc_reflect_function_gen(self.opt, self.sym)), |
| 411 | CodeGen(self.opt, '', _crc_init_function_gen(self.opt, self.sym)), |
| 412 | CodeGen(self.opt, '', _crc_table_gen(self.opt, self.sym)), |
| 413 | CodeGen(self.opt, '', _crc_update_function_gen(self.opt, self.sym)), |
| 414 | CodeGen(self.opt, '', _crc_finalize_function_gen(self.opt, self.sym)), |
| 415 | '', |
| 416 | ] |
| 417 | return out |
| 418 | |
| 419 | def _main_file(self): |
| 420 | """ |
| 421 | Add main file content. |
| 422 | """ |
| 423 | out = [ |
| 424 | '', |
| 425 | '', |
| 426 | CodeGen(self.opt, '', _includes(self.opt)), |
| 427 | '#include <stdio.h>', |
| 428 | '#include <getopt.h>', |
| 429 | Conditional(self.opt, '', self.opt.undefined_crc_parameters, [ |
| 430 | '#include <stdlib.h>', |
| 431 | '#include <stdio.h>', |
| 432 | '#include <ctype.h>', |
| 433 | ]), |
| 434 | Conditional(self.opt, '', self.opt.c_std != 'C89', [ |
| 435 | '#include <stdbool.h>', |
| 436 | ]), |
| 437 | '#include <string.h>', |
| 438 | '', |
| 439 | 'static char str[256] = "123456789";', |
| 440 | 'static {c_bool} verbose = {c_false};'.format(**self.sym), |
| 441 | self._getopt_template(), |
| 442 | '', |
| 443 | '', |
| 444 | Conditional2(self.opt, '', self.opt.undefined_crc_parameters, [ |
| 445 | 'static void print_params(const {cfg_t} *cfg)'.format(**self.sym), |
| 446 | ], [ |
| 447 | 'static void print_params(void)', |
| 448 | ]), |
| 449 | '{', |
| 450 | CodeGen(self.opt, 4*' ', [ |
| 451 | 'char format[20];', |
| 452 | '', |
| 453 | Conditional2(self.opt, '', self.opt.c_std == 'C89', [ |
| 454 | 'sprintf(format, "%%-16s = 0x%%0%dlx\\n", (unsigned int)({cfg_width} + 3) / 4);'.format(**self.sym), |
| 455 | 'printf("%-16s = %d\\n", "width", (unsigned int){cfg_width});'.format(**self.sym), |
| 456 | 'printf(format, "poly", (unsigned long int){cfg_poly});'.format(**self.sym), |
| 457 | 'printf("%-16s = %s\\n", "reflect_in", {0});'.format(self.sym['cfg_reflect_in'] + ' ? "true": "false"' if self.opt.reflect_in is None else ('"true"' if self.opt.reflect_in else '"false"')), |
| 458 | 'printf(format, "xor_in", (unsigned long int){cfg_xor_in});'.format(**self.sym), |
| 459 | 'printf("%-16s = %s\\n", "reflect_out", {0});'.format(self.sym['cfg_reflect_out'] + ' ? "true": "false"' if self.opt.reflect_out is None else ('"true"' if self.opt.reflect_out else '"false"')), |
| 460 | 'printf(format, "xor_out", (unsigned long int){cfg_xor_out});'.format(**self.sym), |
| 461 | 'printf(format, "crc_mask", (unsigned long int){cfg_mask});'.format(**self.sym), |
| 462 | 'printf(format, "msb_mask", (unsigned long int){cfg_msb_mask});'.format(**self.sym), |
| 463 | ], [ |
| 464 | 'snprintf(format, sizeof(format), "%%-16s = 0x%%0%dllx\\n", (unsigned int)({cfg_width} + 3) / 4);'.format(**self.sym), |
| 465 | 'printf("%-16s = %d\\n", "width", (unsigned int){cfg_width});'.format(**self.sym), |
| 466 | 'printf(format, "poly", (unsigned long long int){cfg_poly});'.format(**self.sym), |
| 467 | 'printf("%-16s = %s\\n", "reflect_in", {0});'.format(self.sym['cfg_reflect_in'] + ' ? "true": "false"' if self.opt.reflect_in is None else ('"true"' if self.opt.reflect_in else '"false"')), |
| 468 | 'printf(format, "xor_in", (unsigned long long int){cfg_xor_in});'.format(**self.sym), |
| 469 | 'printf("%-16s = %s\\n", "reflect_out", {0});'.format(self.sym['cfg_reflect_out'] + ' ? "true": "false"' if self.opt.reflect_out is None else ('"true"' if self.opt.reflect_out else '"false"')), |
| 470 | 'printf(format, "xor_out", (unsigned long long int){cfg_xor_out});'.format(**self.sym), |
| 471 | 'printf(format, "crc_mask", (unsigned long long int){cfg_mask});'.format(**self.sym), |
| 472 | 'printf(format, "msb_mask", (unsigned long long int){cfg_msb_mask});'.format(**self.sym), |
| 473 | ]), |
| 474 | ]), |
| 475 | '}', |
| 476 | '', |
| 477 | '', |
| 478 | Comment(self.opt, '', [ |
| 479 | 'C main function.', |
| 480 | '\\param[in] argc the number of arguments in \\a argv.', |
| 481 | '\\param[in] argv a NULL-terminated array of pointers to the argument strings.', |
| 482 | '\\retval 0 on success.', |
| 483 | '\\retval >0 on error.', |
| 484 | ]), |
| 485 | 'int main(int argc, char *argv[])', |
| 486 | '{', |
| 487 | CodeGen(self.opt, 4*' ', [ |
| 488 | Conditional(self.opt, '', self.opt.undefined_crc_parameters, [ |
| 489 | '{cfg_t} cfg = '.format(**self.sym) + '{', |
| 490 | Conditional(self.opt, 4*' ', self.opt.width is None, [ |
| 491 | '0, /* width */', |
| 492 | ]), |
| 493 | Conditional(self.opt, 4*' ', self.opt.poly is None, [ |
| 494 | '0, /* poly */', |
| 495 | ]), |
| 496 | Conditional(self.opt, 4*' ', self.opt.reflect_in is None, [ |
| 497 | '0, /* reflect_in */', |
| 498 | ]), |
| 499 | Conditional(self.opt, 4*' ', self.opt.xor_in is None, [ |
| 500 | '0, /* xor_in */', |
| 501 | ]), |
| 502 | Conditional(self.opt, 4*' ', self.opt.reflect_out is None, [ |
| 503 | '0, /* reflect_out */', |
| 504 | ]), |
| 505 | Conditional(self.opt, 4*' ', self.opt.xor_out is None, [ |
| 506 | '0, /* xor_out */', |
| 507 | ]), |
| 508 | Conditional(self.opt, 4*' ', self.opt.width is None, [ |
| 509 | '', |
| 510 | '0, /* crc_mask */', |
| 511 | '0, /* msb_mask */', |
| 512 | '0, /* crc_shift */', |
| 513 | ]), |
| 514 | '};', |
| 515 | ]), |
| 516 | '{crc_t} crc;'.format(**self.sym), |
| 517 | '', |
| 518 | Conditional2(self.opt, '', self.opt.undefined_crc_parameters, [ |
| 519 | 'get_config(argc, argv, &cfg);', |
| 520 | ], [ |
| 521 | 'get_config(argc, argv);', |
| 522 | ]), |
| 523 | Conditional(self.opt, '', _use_crc_table_gen(self.opt), [ |
| 524 | '{crc_table_gen_function}(&cfg);'.format(**self.sym), |
| 525 | ]), |
| 526 | 'crc = {0}({1});'.format(self.sym['crc_init_function'], '' if _use_constant_crc_init(self.sym) else '&cfg'), |
| 527 | 'crc = {0}({1}crc, (void *)str, strlen(str));'.format(self.sym['crc_update_function'], '' if _use_cfg_in_crc_update(self.opt) else '&cfg, '), |
| 528 | 'crc = {0}({1}crc);'.format(self.sym['crc_finalize_function'], '' if _use_cfg_in_finalize(self.opt) else '&cfg, '), |
| 529 | '', |
| 530 | 'if (verbose) {', |
| 531 | CodeGen(self.opt, 4*' ', [ |
| 532 | 'print_params({0});'.format('&cfg' if self.opt.undefined_crc_parameters else ''), |
| 533 | ]), |
| 534 | '}', |
| 535 | Conditional2(self.opt, '', self.opt.c_std == 'C89', [ |
| 536 | 'printf("0x%lx\\n", (unsigned long int)crc);', |
| 537 | ], [ |
| 538 | 'printf("0x%llx\\n", (unsigned long long int)crc);', |
| 539 | ]), |
| 540 | 'return 0;', |
| 541 | ]), |
| 542 | '}', |
| 543 | ] |
| 544 | return out |
| 545 | |
| 546 | def _getopt_template(self): |
| 547 | """ |
| 548 | Add getopt functions. |
| 549 | """ |
| 550 | out = [ |
| 551 | Conditional(self.opt, '', self.opt.reflect_in is None or self.opt.reflect_out is None, [ |
| 552 | '', |
| 553 | '', |
| 554 | 'static {c_bool} atob(const char *str)'.format(**self.sym), |
| 555 | '{', |
| 556 | CodeGen(self.opt, 4*' ', [ |
| 557 | 'if (!str) {', |
| 558 | CodeGen(self.opt, 4*' ', [ |
| 559 | 'return 0;', |
| 560 | ]), |
| 561 | '}', |
| 562 | 'if (isdigit(str[0])) {', |
| 563 | CodeGen(self.opt, 4*' ', [ |
| 564 | 'return ({c_bool})atoi(str);'.format(**self.sym), |
| 565 | ]), |
| 566 | '}', |
| 567 | 'if (tolower(str[0]) == \'t\') {', |
| 568 | CodeGen(self.opt, 4*' ', [ |
| 569 | 'return {c_true};'.format(**self.sym), |
| 570 | ]), |
| 571 | '}', |
| 572 | 'return {c_false};'.format(**self.sym), |
| 573 | ]), |
| 574 | '}', |
| 575 | ]), |
| 576 | Conditional(self.opt, '', self.opt.poly is None or self.opt.xor_in is None or self.opt.xor_out is None, [ |
| 577 | '', |
| 578 | '', |
| 579 | 'static crc_t xtoi(const char *str)', |
| 580 | '{', |
| 581 | CodeGen(self.opt, 4*' ', [ |
| 582 | 'crc_t ret = 0;', |
| 583 | '', |
| 584 | 'if (!str) {', |
| 585 | CodeGen(self.opt, 4*' ', [ |
| 586 | 'return 0;', |
| 587 | ]), |
| 588 | '}', |
| 589 | 'if (str[0] == \'0\' && tolower(str[1]) == \'x\') {', |
| 590 | CodeGen(self.opt, 4*' ', [ |
| 591 | 'str += 2;', |
| 592 | 'while (*str) {', |
| 593 | CodeGen(self.opt, 4*' ', [ |
| 594 | 'if (isdigit(*str))', |
| 595 | CodeGen(self.opt, 4*' ', [ |
| 596 | 'ret = 16 * ret + *str - \'0\';', |
| 597 | ]), |
| 598 | 'else if (isxdigit(*str))', |
| 599 | CodeGen(self.opt, 4*' ', [ |
| 600 | 'ret = 16 * ret + tolower(*str) - \'a\' + 10;', |
| 601 | ]), |
| 602 | 'else', |
| 603 | CodeGen(self.opt, 4*' ', [ |
| 604 | 'return ret;', |
| 605 | ]), |
| 606 | 'str++;', |
| 607 | ]), |
| 608 | '}', |
| 609 | ]), |
| 610 | '} else if (isdigit(*str)) {', |
| 611 | CodeGen(self.opt, 4*' ', [ |
| 612 | 'while (*str) {', |
| 613 | CodeGen(self.opt, 4*' ', [ |
| 614 | 'if (isdigit(*str))', |
| 615 | CodeGen(self.opt, 4*' ', [ |
| 616 | 'ret = 10 * ret + *str - \'0\';', |
| 617 | ]), |
| 618 | 'else', |
| 619 | CodeGen(self.opt, 4*' ', [ |
| 620 | 'return ret;', |
| 621 | ]), |
| 622 | 'str++;', |
| 623 | ]), |
| 624 | '}', |
| 625 | ]), |
| 626 | '}', |
| 627 | 'return ret;', |
| 628 | ]), |
| 629 | '}', |
| 630 | ]), |
| 631 | '', |
| 632 | '', |
| 633 | Conditional2(self.opt, '', self.opt.undefined_crc_parameters, [ |
| 634 | 'static int get_config(int argc, char *argv[], {cfg_t} *cfg)'.format(**self.sym), |
| 635 | ], [ |
| 636 | 'static int get_config(int argc, char *argv[])', |
| 637 | ]), |
| 638 | '{', |
| 639 | CodeGen(self.opt, 4*' ', [ |
| 640 | 'int c;', |
| 641 | 'int option_index;', |
| 642 | 'static struct option long_options[] = {', |
| 643 | CodeGen(self.opt, 4*' ', [ |
| 644 | Conditional(self.opt, '', self.opt.width is None, [ |
| 645 | '{"width", 1, 0, \'w\'},', |
| 646 | ]), |
| 647 | Conditional(self.opt, '', self.opt.poly is None, [ |
| 648 | '{"poly", 1, 0, \'p\'},', |
| 649 | ]), |
| 650 | Conditional(self.opt, '', self.opt.reflect_in is None, [ |
| 651 | '{"reflect-in", 1, 0, \'n\'},', |
| 652 | ]), |
| 653 | Conditional(self.opt, '', self.opt.xor_in is None, [ |
| 654 | '{"xor-in", 1, 0, \'i\'},', |
| 655 | ]), |
| 656 | Conditional(self.opt, '', self.opt.reflect_out is None, [ |
| 657 | '{"reflect-out", 1, 0, \'u\'},', |
| 658 | ]), |
| 659 | Conditional(self.opt, '', self.opt.xor_out is None, [ |
| 660 | '{"xor-out", 1, 0, \'o\'},', |
| 661 | ]), |
| 662 | '{"verbose", 0, 0, \'v\'},', |
| 663 | '{"check-string", 1, 0, \'s\'},', |
| 664 | Conditional(self.opt, '', self.opt.width is None, [ |
| 665 | '{"table-idx-with", 1, 0, \'t\'},', |
| 666 | ]), |
| 667 | '{0, 0, 0, 0}', |
| 668 | ]), |
| 669 | '};', |
| 670 | '', |
| 671 | 'while (1) {', |
| 672 | CodeGen(self.opt, 4*' ', [ |
| 673 | 'option_index = 0;', |
| 674 | '', |
| 675 | 'c = getopt_long(argc, argv, "w:p:n:i:u:o:s:vt", long_options, &option_index);', |
| 676 | 'if (c == -1)', |
| 677 | CodeGen(self.opt, 4*' ', [ |
| 678 | 'break;', |
| 679 | ]), |
| 680 | '', |
| 681 | 'switch (c) {', |
| 682 | CodeGen(self.opt, 4*' ', [ |
| 683 | 'case 0:', |
| 684 | CodeGen(self.opt, 4*' ', [ |
| 685 | 'printf("option %s", long_options[option_index].name);', |
| 686 | 'if (optarg)', |
| 687 | CodeGen(self.opt, 4*' ', [ |
| 688 | 'printf(" with arg %s", optarg);', |
| 689 | ]), |
| 690 | 'printf("\\n");', |
| 691 | 'break;', |
| 692 | ]), |
| 693 | Conditional(self.opt, '', self.opt.width is None, [ |
| 694 | 'case \'w\':', |
| 695 | CodeGen(self.opt, 4*' ', [ |
| 696 | 'cfg->width = atoi(optarg);', |
| 697 | 'break;', |
| 698 | ]), |
| 699 | ]), |
| 700 | Conditional(self.opt, '', self.opt.poly is None, [ |
| 701 | 'case \'p\':', |
| 702 | CodeGen(self.opt, 4*' ', [ |
| 703 | 'cfg->poly = xtoi(optarg);', |
| 704 | 'break;', |
| 705 | ]), |
| 706 | ]), |
| 707 | Conditional(self.opt, '', self.opt.reflect_in is None, [ |
| 708 | 'case \'n\':', |
| 709 | CodeGen(self.opt, 4*' ', [ |
| 710 | 'cfg->reflect_in = atob(optarg);', |
| 711 | 'break;', |
| 712 | ]), |
| 713 | ]), |
| 714 | Conditional(self.opt, '', self.opt.xor_in is None, [ |
| 715 | 'case \'i\':', |
| 716 | CodeGen(self.opt, 4*' ', [ |
| 717 | 'cfg->xor_in = xtoi(optarg);', |
| 718 | 'break;', |
| 719 | ]), |
| 720 | ]), |
| 721 | Conditional(self.opt, '', self.opt.reflect_out is None, [ |
| 722 | 'case \'u\':', |
| 723 | CodeGen(self.opt, 4*' ', [ |
| 724 | 'cfg->reflect_out = atob(optarg);', |
| 725 | 'break;', |
| 726 | ]), |
| 727 | ]), |
| 728 | Conditional(self.opt, '', self.opt.xor_out is None, [ |
| 729 | 'case \'o\':', |
| 730 | CodeGen(self.opt, 4*' ', [ |
| 731 | 'cfg->xor_out = xtoi(optarg);', |
| 732 | 'break;', |
| 733 | ]), |
| 734 | ]), |
| 735 | 'case \'s\':', |
| 736 | CodeGen(self.opt, 4*' ', [ |
| 737 | 'memcpy(str, optarg, strlen(optarg) < sizeof(str) ? strlen(optarg) + 1 : sizeof(str));', |
| 738 | 'str[sizeof(str) - 1] = \'\\0\';', |
| 739 | 'break;', |
| 740 | ]), |
| 741 | 'case \'v\':', |
| 742 | CodeGen(self.opt, 4*' ', [ |
| 743 | 'verbose = {c_true};'.format(**self.sym), |
| 744 | 'break;', |
| 745 | ]), |
| 746 | Conditional(self.opt, '', self.opt.width is None, [ |
| 747 | 'case \'t\':', |
| 748 | CodeGen(self.opt, 4*' ', [ |
| 749 | '/* ignore --table_idx_width option */', |
| 750 | 'break;', |
| 751 | ]), |
| 752 | ]), |
| 753 | 'case \'?\':', |
| 754 | CodeGen(self.opt, 4*' ', [ |
| 755 | 'return -1;', |
| 756 | ]), |
| 757 | 'case \':\':', |
| 758 | CodeGen(self.opt, 4*' ', [ |
| 759 | 'fprintf(stderr, "missing argument to option %c\\n", c);', |
| 760 | 'return -1;', |
| 761 | ]), |
| 762 | 'default:', |
| 763 | CodeGen(self.opt, 4*' ', [ |
| 764 | 'fprintf(stderr, "unhandled option %c\\n", c);', |
| 765 | 'return -1;', |
| 766 | ]), |
| 767 | ]), |
| 768 | '}', |
| 769 | ]), |
| 770 | '}', |
| 771 | Conditional(self.opt, '', self.opt.width is None, [ |
| 772 | 'cfg->msb_mask = (crc_t)1u << (cfg->width - 1);', |
| 773 | 'cfg->crc_mask = (cfg->msb_mask - 1) | cfg->msb_mask;', |
| 774 | 'cfg->crc_shift = cfg->width < 8 ? 8 - cfg->width : 0;', |
| 775 | ]), |
| 776 | '', |
| 777 | Conditional(self.opt, '', self.opt.poly is None, [ |
| 778 | 'cfg->poly &= {cfg_mask};'.format(**self.sym), |
| 779 | ]), |
| 780 | Conditional(self.opt, '', self.opt.xor_in is None, [ |
| 781 | 'cfg->xor_in &= {cfg_mask};'.format(**self.sym), |
| 782 | ]), |
| 783 | Conditional(self.opt, '', self.opt.xor_out is None, [ |
| 784 | 'cfg->xor_out &= {cfg_mask};'.format(**self.sym), |
| 785 | ]), |
| 786 | 'return 0;', |
| 787 | ]), |
| 788 | '}', |
| 789 | ] |
| 790 | return CodeGen(self.opt, '', out) |
| 791 | |
| 792 | |
| 793 | def _includes(opt): |
| 794 | """ |
| 795 | Return the #include directives for the user-defined list of include files. |
| 796 | """ |
| 797 | includes = [] |
| 798 | if opt.include_files is not None and len(opt.include_files) > 0: |
| 799 | for include_file in opt.include_files: |
| 800 | if include_file[0] == '"' or include_file[0] == '<': |
| 801 | includes.append('#include {0}'.format(include_file)) |
| 802 | else: |
| 803 | includes.append('#include "{0}"'.format(include_file)) |
| 804 | return includes |
| 805 | |
| 806 | |
| 807 | def _crc_algo_define(opt, sym): |
| 808 | """ |
| 809 | Get the the identifier for header files. |
| 810 | """ |
| 811 | name = sym['crc_algorithm'].upper().replace('-', '_') |
| 812 | return 'CRC_ALGO_' + name |
| 813 | |
| 814 | |
| 815 | def _use_cfg(opt): |
| 816 | """ |
| 817 | Return True if a cfg_t structure is to be used. |
| 818 | """ |
| 819 | return opt.undefined_crc_parameters |
| 820 | |
| 821 | |
| 822 | def _use_constant_crc_init(sym): |
| 823 | """ |
| 824 | Return True if the inintial value is constant. |
| 825 | """ |
| 826 | return sym['crc_init_value'] is not None |
| 827 | |
| 828 | |
| 829 | def _use_reflect_func(opt): |
| 830 | """ |
| 831 | Return True if the reflect function is to be used. |
| 832 | """ |
| 833 | if opt.reflect_out == None or opt.reflect_in == None: |
| 834 | return True |
| 835 | elif opt.algorithm == opt.algo_table_driven: |
| 836 | if opt.reflect_in != opt.reflect_out: |
| 837 | return True |
| 838 | elif opt.algorithm == opt.algo_bit_by_bit: |
| 839 | if opt.reflect_in: |
| 840 | return True |
| 841 | if opt.reflect_out: |
| 842 | return True |
| 843 | elif opt.algorithm == opt.algo_bit_by_bit_fast: |
| 844 | if opt.reflect_in: |
| 845 | return True |
| 846 | if opt.reflect_out: |
| 847 | return True |
| 848 | return False |
| 849 | |
| 850 | |
| 851 | def _use_static_reflect_func(opt): |
| 852 | """ |
| 853 | Whether a static reflect function is to be used. |
| 854 | """ |
| 855 | if opt.algorithm == opt.algo_table_driven: |
| 856 | return False |
| 857 | elif opt.reflect_out is not None and opt.algorithm == opt.algo_bit_by_bit_fast: |
| 858 | return False |
| 859 | else: |
| 860 | return True |
| 861 | |
| 862 | |
| 863 | def _use_crc_table_gen(opt): |
| 864 | """ |
| 865 | Return True if the table generator function is to be generated. |
| 866 | """ |
| 867 | if opt.algorithm == opt.algo_table_driven: |
| 868 | return opt.width is None or opt.poly is None or opt.reflect_in is None |
| 869 | else: |
| 870 | return False |
| 871 | |
| 872 | |
| 873 | def _crc_init_function_def(opt, sym): |
| 874 | """ |
| 875 | The definition for the init function. |
| 876 | """ |
| 877 | if _use_constant_crc_init(sym): |
| 878 | return '{crc_t} {crc_init_function}(void)'.format(**sym) |
| 879 | else: |
| 880 | return '{crc_t} {crc_init_function}(const {cfg_t} *cfg)'.format(**sym) |
| 881 | |
| 882 | |
| 883 | def _use_cfg_in_crc_update(opt): |
| 884 | """ |
| 885 | Return True if the update function uses the cfg_t parameter. |
| 886 | """ |
| 887 | if opt.algorithm in set([opt.algo_bit_by_bit, opt.algo_bit_by_bit_fast]): |
| 888 | if opt.width is not None and opt.poly is not None and opt.reflect_in is not None: |
| 889 | return True |
| 890 | elif opt.algorithm == opt.algo_table_driven: |
| 891 | if opt.width is not None and opt.reflect_in is not None: |
| 892 | return True |
| 893 | return False |
| 894 | |
| 895 | |
| 896 | def _crc_update_function_def(opt, sym): |
| 897 | """ |
| 898 | The definition of the update function. |
| 899 | """ |
| 900 | if _use_cfg_in_crc_update(opt): |
| 901 | return '{crc_t} {crc_update_function}({crc_t} crc, const void *data, size_t data_len)'.format(**sym) |
| 902 | else: |
| 903 | return '{crc_t} {crc_update_function}(const {cfg_t} *cfg, {crc_t} crc, const void *data, size_t data_len)'.format(**sym) |
| 904 | |
| 905 | |
| 906 | def _use_cfg_in_finalize(opt): |
| 907 | """ |
| 908 | Return True if the cfg_t parameter is used in the finalize function. |
| 909 | """ |
| 910 | if opt.algorithm == opt.algo_bit_by_bit: |
| 911 | if opt.width is not None and opt.poly is not None and opt.reflect_out is not None and opt.xor_out is not None: |
| 912 | return True |
| 913 | elif opt.algorithm == opt.algo_bit_by_bit_fast: |
| 914 | if opt.width is not None and opt.reflect_out is not None and opt.xor_out is not None: |
| 915 | return True |
| 916 | elif opt.algorithm == opt.algo_table_driven: |
| 917 | if opt.width is not None and opt.reflect_in is not None and opt.reflect_out is not None and opt.xor_out is not None: |
| 918 | return True |
| 919 | return False |
| 920 | |
| 921 | |
| 922 | def _use_inline_crc_finalize(opt): |
| 923 | """ |
| 924 | Return True if the init function can be inlined. |
| 925 | """ |
| 926 | if opt.algorithm in set([opt.algo_bit_by_bit_fast, opt.algo_table_driven]) and \ |
| 927 | (opt.width is not None and opt.reflect_in is not None and opt.reflect_out is not None and opt.xor_out is not None): |
| 928 | return True |
| 929 | else: |
| 930 | return False |
| 931 | |
| 932 | |
| 933 | def _use_constant_crc_table(opt): |
| 934 | """ |
| 935 | Return True is the CRC table is constant. |
| 936 | """ |
| 937 | if opt.width is not None and opt.poly is not None and opt.reflect_in is not None: |
| 938 | return True |
| 939 | else: |
| 940 | return False |
| 941 | |
| 942 | |
| 943 | def _crc_finalize_function_def(opt, sym): |
| 944 | """ |
| 945 | The definition of the finalize function. |
| 946 | """ |
| 947 | if _use_cfg_in_finalize(opt): |
| 948 | return '{crc_t} {crc_finalize_function}({crc_t} crc)'.format(**sym) |
| 949 | else: |
| 950 | return '{crc_t} {crc_finalize_function}(const {cfg_t} *cfg, {crc_t} crc)'.format(**sym) |
| 951 | |
| 952 | |
| 953 | def _crc_final_value(opt, sym): |
| 954 | """ |
| 955 | The return value for the finalize function. |
| 956 | """ |
| 957 | if opt.algorithm == opt.algo_table_driven: |
| 958 | if opt.reflect_in == opt.reflect_out: |
| 959 | return expr.Xor('crc', sym['crc_xor_out']).simplify() |
| 960 | else: |
| 961 | reflect_fun = expr.FunctionCall(sym['crc_reflect_function'], ['crc', sym['crc_width']]) |
| 962 | return expr.Xor(reflect_fun, sym['crc_xor_out']).simplify() |
| 963 | elif opt.reflect_out: |
| 964 | reflect_fun = expr.FunctionCall(sym['crc_reflect_function'], ['crc', sym['crc_width']]) |
| 965 | return expr.Xor(reflect_fun, sym['crc_xor_out']).simplify() |
| 966 | else: |
| 967 | return expr.Xor('crc', sym['crc_xor_out']).simplify() |
| 968 | |
| 969 | |
| 970 | def _crc_table(opt, sym): |
| 971 | """ |
| 972 | Return the code for the CRC table or the generator function. |
| 973 | """ |
| 974 | if opt.algorithm != opt.algo_table_driven: |
| 975 | return [] |
| 976 | return [ |
| 977 | '', '', |
| 978 | Comment(opt, '', [ |
| 979 | 'Static table used for the table_driven implementation.', |
| 980 | Conditional(opt, '', opt.undefined_crc_parameters, [ |
| 981 | 'Must be initialised with the {crc_table_gen_function} function.'.format(**sym), |
| 982 | ]), |
| 983 | ]), |
| 984 | Conditional2(opt, '', _use_constant_crc_table(opt), [ |
| 985 | Conditional2(opt, '', opt.slice_by > 1, [ |
| 986 | 'static const {crc_t} crc_table[{crc_slice_by}][{crc_table_width}] = {crc_table_init};'.format(**sym), |
| 987 | ], [ |
| 988 | 'static const {crc_t} crc_table[{crc_table_width}] = {crc_table_init};'.format(**sym), |
| 989 | ]), |
| 990 | ], [ |
| 991 | 'static {crc_t} crc_table[{crc_table_width}];'.format(**sym), |
| 992 | ]), |
| 993 | ] |
| 994 | |
| 995 | |
| 996 | def _crc_table_gen(opt, sym): |
| 997 | """ |
| 998 | Return the code for the CRC table or the generator function. |
| 999 | """ |
| 1000 | if opt.algorithm != opt.algo_table_driven or _use_constant_crc_table(opt): |
| 1001 | return [] |
| 1002 | return [ |
| 1003 | '', '', |
| 1004 | 'void {crc_table_gen_function}(const {cfg_t} *cfg)'.format(**sym), |
| 1005 | '{', |
| 1006 | CodeGen(opt, 4*' ', [ |
| 1007 | '{crc_t} crc;'.format(**sym), |
| 1008 | 'unsigned int i, j;', |
| 1009 | '', |
| 1010 | 'for (i = 0; i < {cfg_table_width}; i++) '.format(**sym) + '{', |
| 1011 | CodeGen(opt, 4*' ', [ |
| 1012 | Conditional2(opt, '', opt.reflect_in is None, [ |
| 1013 | 'if (cfg->reflect_in) {', |
| 1014 | CodeGen(opt, 4*' ', [ |
| 1015 | 'crc = {crc_reflect_function}(i, {cfg_table_idx_width});'.format(**sym), |
| 1016 | ]), |
| 1017 | '} else {', |
| 1018 | CodeGen(opt, 4*' ', [ |
| 1019 | 'crc = i;', |
| 1020 | ]), |
| 1021 | '}', |
| 1022 | ], [ |
| 1023 | Conditional2(opt, '', opt.reflect_in, [ |
| 1024 | 'crc = {crc_reflect_function}(i, {cfg_table_idx_width});'.format(**sym), |
| 1025 | ], [ |
| 1026 | 'crc = i;', |
| 1027 | ]), |
| 1028 | ]), |
| 1029 | 'crc <<= {0};'.format(expr.Parenthesis(expr.Add(expr.Sub(sym['cfg_width'], sym['cfg_table_idx_width']), sym['cfg_shift'])).simplify()), |
| 1030 | 'for (j = 0; j < {cfg_table_idx_width}; j++) '.format(**sym) + '{', |
| 1031 | CodeGen(opt, 4*' ', [ |
| 1032 | 'if (crc & {cfg_msb_mask_shifted}) '.format(**sym) + '{', |
| 1033 | CodeGen(opt, 4*' ', [ |
| 1034 | 'crc = {0};'.format(expr.Xor(expr.Parenthesis(expr.Shl('crc', 1)), sym['cfg_poly_shifted']).simplify()), |
| 1035 | ]), |
| 1036 | '} else {', |
| 1037 | CodeGen(opt, 4*' ', [ |
| 1038 | 'crc = crc << 1;', |
| 1039 | ]), |
| 1040 | '}', |
| 1041 | ]), |
| 1042 | '}', |
| 1043 | Conditional(opt, '', opt.reflect_in is None, [ |
| 1044 | 'if (cfg->reflect_in) {', |
| 1045 | Conditional2(opt, 4*' ', sym.tbl_shift is None or sym.tbl_shift > 0, [ |
| 1046 | 'crc = {0};'.format(expr.Shl(expr.FunctionCall(sym['crc_reflect_function'], [expr.Shr('crc', sym['cfg_shift']), sym['cfg_width']]), sym['cfg_shift']).simplify()), |
| 1047 | ], [ |
| 1048 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1049 | ]), |
| 1050 | '}', |
| 1051 | ]), |
| 1052 | Conditional(opt, '', opt.reflect_in, [ |
| 1053 | Conditional2(opt, 4*' ', sym.tbl_shift is None or sym.tbl_shift > 0, [ |
| 1054 | 'crc = {0};'.format(expr.Shl(expr.FunctionCall(sym['crc_reflect_function'], [expr.Shr('crc', sym['cfg_shift']), sym['cfg_width']]), sym['cfg_shift']).simplify()), |
| 1055 | ], [ |
| 1056 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1057 | ]), |
| 1058 | ]), |
| 1059 | 'crc_table[i] = {0};'.format(expr.Shr(expr.Parenthesis(expr.And('crc', sym['cfg_mask_shifted'])), sym['cfg_shift'])), |
| 1060 | ]), |
| 1061 | '}', |
| 1062 | ]), |
| 1063 | '}', |
| 1064 | ] |
| 1065 | |
| 1066 | |
| 1067 | def _crc_reflect_function_gen(opt, sym): |
| 1068 | """ |
| 1069 | Return the code for the reflect functon. |
| 1070 | """ |
| 1071 | if not _use_reflect_func(opt): |
| 1072 | return [] |
| 1073 | if not (opt.reflect_in is None or opt.reflect_in or \ |
| 1074 | opt.reflect_out is None or opt.reflect_out): |
| 1075 | return [] |
| 1076 | return [ |
| 1077 | '', '', |
| 1078 | '{crc_t} {crc_reflect_function}({crc_t} data, size_t data_len)'.format(**sym), |
| 1079 | '{', |
| 1080 | CodeGen(opt, 4*' ', [ |
| 1081 | 'unsigned int i;', |
| 1082 | '{crc_t} ret;'.format(**sym), |
| 1083 | '', |
| 1084 | 'ret = data & 0x01;', |
| 1085 | 'for (i = 1; i < data_len; i++) {', |
| 1086 | CodeGen(opt, 4*' ', [ |
| 1087 | 'data >>= 1;', |
| 1088 | 'ret = (ret << 1) | (data & 0x01);', |
| 1089 | ]), |
| 1090 | '}', |
| 1091 | 'return ret;', |
| 1092 | ]), |
| 1093 | '}', |
| 1094 | ] |
| 1095 | |
| 1096 | |
| 1097 | def _crc_init_function_gen(opt, sym): |
| 1098 | """ |
| 1099 | Return the code for the init function. |
| 1100 | """ |
| 1101 | if _use_constant_crc_init(sym): |
| 1102 | return [] |
| 1103 | out = [ |
| 1104 | '', '', |
| 1105 | _crc_init_function_def(opt, sym), |
| 1106 | '{', |
| 1107 | CodeGen(opt, 4*' ', [ |
| 1108 | Conditional(opt, '', opt.algorithm == opt.algo_bit_by_bit, [ |
| 1109 | 'unsigned int i;', |
| 1110 | '{c_bool} bit;'.format(**sym), |
| 1111 | '{crc_t} crc = {cfg_xor_in};'.format(**sym), |
| 1112 | 'for (i = 0; i < {cfg_width}; i++) '.format(**sym) + '{', |
| 1113 | CodeGen(opt, 4*' ', [ |
| 1114 | 'bit = crc & 0x01;', |
| 1115 | 'if (bit) {', |
| 1116 | CodeGen(opt, 4*' ', [ |
| 1117 | 'crc = ((crc ^ {cfg_poly}) >> 1) | {cfg_msb_mask};'.format(**sym), |
| 1118 | ]), |
| 1119 | '} else {', |
| 1120 | CodeGen(opt, 4*' ', [ |
| 1121 | 'crc >>= 1;', |
| 1122 | ]), |
| 1123 | '}', |
| 1124 | ]), |
| 1125 | '}', |
| 1126 | 'return crc & {cfg_mask};'.format(**sym), |
| 1127 | ]), |
| 1128 | Conditional(opt, '', opt.algorithm == opt.algo_bit_by_bit_fast, [ |
| 1129 | 'return {cfg_xor_in} & {cfg_mask};'.format(**sym), |
| 1130 | ]), |
| 1131 | Conditional(opt, '', opt.algorithm == opt.algo_table_driven, [ |
| 1132 | Conditional2(opt, '', opt.reflect_in is None, [ |
| 1133 | 'if ({cfg_reflect_in}) '.format(**sym) + '{', |
| 1134 | CodeGen(opt, 4*' ', [ |
| 1135 | 'return {crc_reflect_function}({cfg_xor_in} & {cfg_mask}, {cfg_width});'.format(**sym), |
| 1136 | ]), |
| 1137 | '} else {', |
| 1138 | CodeGen(opt, 4*' ', [ |
| 1139 | 'return {cfg_xor_in} & {cfg_mask};'.format(**sym), |
| 1140 | ]), |
| 1141 | '}', |
| 1142 | ], [ |
| 1143 | Conditional2(opt, '', opt.algorithm == opt.reflect_in, [ |
| 1144 | 'return {crc_reflect_function}({cfg_xor_in} & {cfg_mask}, {cfg_width});'.format(**sym), |
| 1145 | ], [ |
| 1146 | 'return {cfg_xor_in} & {cfg_mask};'.format(**sym), |
| 1147 | ]), |
| 1148 | ]), |
| 1149 | ]), |
| 1150 | ]), |
| 1151 | '}', |
| 1152 | ] |
| 1153 | return out |
| 1154 | |
| 1155 | |
| 1156 | def _crc_update_function_gen(opt, sym): |
| 1157 | """ |
| 1158 | Return the code for the update function. |
| 1159 | """ |
| 1160 | out = [ |
| 1161 | '', '', |
| 1162 | _crc_update_function_def(opt, sym), |
| 1163 | '{', |
| 1164 | CodeGen(opt, 4*' ', [ 'const unsigned char *d = (const unsigned char *)data;' ]), |
| 1165 | ] |
| 1166 | if opt.algorithm == opt.algo_bit_by_bit: |
| 1167 | out += [ |
| 1168 | CodeGen(opt, 4*' ', [ |
| 1169 | 'unsigned int i;', |
| 1170 | '{c_bool} bit;'.format(**sym), |
| 1171 | 'unsigned char c;', |
| 1172 | '', |
| 1173 | 'while (data_len--) {', |
| 1174 | Conditional2(opt, 4*' ', opt.reflect_in is None, [ |
| 1175 | 'if (' + sym['cfg_reflect_in'] + ') {', |
| 1176 | CodeGen(opt, 4*' ', [ |
| 1177 | 'c = {crc_reflect_function}(*d++, 8);'.format(**sym), |
| 1178 | ]), |
| 1179 | '} else {', |
| 1180 | CodeGen(opt, 4*' ', [ |
| 1181 | 'c = *d++;', |
| 1182 | ]), |
| 1183 | '}', |
| 1184 | ], [ |
| 1185 | Conditional2(opt, '', opt.reflect_in, [ |
| 1186 | 'c = {crc_reflect_function}(*d++, 8);'.format(**sym), |
| 1187 | ], [ |
| 1188 | 'c = *d++;', |
| 1189 | ]), |
| 1190 | ]), |
| 1191 | |
| 1192 | CodeGen(opt, 4*' ', [ |
| 1193 | 'for (i = 0; i < 8; i++) {', |
| 1194 | CodeGen(opt, 4*' ', [ |
| 1195 | Conditional2(opt, '', opt.c_std == 'C89', [ |
| 1196 | 'bit = !!(crc & {cfg_msb_mask});'.format(**sym), |
| 1197 | ], [ |
| 1198 | 'bit = crc & {cfg_msb_mask};'.format(**sym), |
| 1199 | ]), |
| 1200 | 'crc = (crc << 1) | ((c >> (7 - i)) & 0x01);', |
| 1201 | 'if (bit) {', |
| 1202 | CodeGen(opt, 4*' ', [ |
| 1203 | 'crc ^= {cfg_poly};'.format(**sym), |
| 1204 | ]), |
| 1205 | '}', |
| 1206 | ]), |
| 1207 | '}', |
| 1208 | 'crc &= {cfg_mask};'.format(**sym), |
| 1209 | ]), |
| 1210 | '}', |
| 1211 | 'return crc & {cfg_mask};'.format(**sym), |
| 1212 | ]), |
| 1213 | ] |
| 1214 | |
| 1215 | if opt.algorithm == opt.algo_bit_by_bit_fast: |
| 1216 | out += [ |
| 1217 | CodeGen(opt, 4*' ', [ |
| 1218 | 'unsigned int i;', |
| 1219 | '{c_bool} bit;'.format(**sym), |
| 1220 | 'unsigned char c;', |
| 1221 | '', |
| 1222 | 'while (data_len--) {', |
| 1223 | CodeGen(opt, 4*' ', [ |
| 1224 | Conditional2(opt, '', opt.reflect_in == None, [ |
| 1225 | 'if (' + sym['cfg_reflect_in'] + ') {', |
| 1226 | CodeGen(opt, 4*' ', [ |
| 1227 | 'c = {crc_reflect_function}(*d++, 8);'.format(**sym), |
| 1228 | ]), |
| 1229 | '} else {', |
| 1230 | CodeGen(opt, 4*' ', [ |
| 1231 | 'c = *d++;', |
| 1232 | ]), |
| 1233 | '}', |
| 1234 | ], [ |
| 1235 | 'c = *d++;', |
| 1236 | ]), |
| 1237 | Conditional2(opt, '', opt.reflect_in, [ |
| 1238 | 'for (i = 0x01; i & 0xff; i <<= 1) {', |
| 1239 | ], [ |
| 1240 | 'for (i = 0x80; i > 0; i >>= 1) {', |
| 1241 | ]), |
| 1242 | CodeGen(opt, 4*' ', [ |
| 1243 | Conditional2(opt, '', opt.c_std == 'C89', [ |
| 1244 | 'bit = !!({0});'.format(expr.And('crc', sym['cfg_msb_mask']).simplify()), |
| 1245 | ], [ |
| 1246 | 'bit = {0};'.format(expr.And('crc', sym['cfg_msb_mask']).simplify()), |
| 1247 | ]), |
| 1248 | 'if (c & i) {', |
| 1249 | CodeGen(opt, 4*' ', [ |
| 1250 | 'bit = !bit;', |
| 1251 | ]), |
| 1252 | '}', |
| 1253 | 'crc <<= 1;', |
| 1254 | 'if (bit) {', |
| 1255 | CodeGen(opt, 4*' ', [ |
| 1256 | 'crc ^= {cfg_poly};'.format(**sym), |
| 1257 | ]), |
| 1258 | '}', |
| 1259 | ]), |
| 1260 | '}', |
| 1261 | 'crc &= {cfg_mask};'.format(**sym) |
| 1262 | ]), |
| 1263 | '}', |
| 1264 | 'return {0};'.format(expr.And('crc', sym['cfg_mask']).simplify()), |
| 1265 | ]), |
| 1266 | ] |
| 1267 | |
| 1268 | if opt.algorithm == opt.algo_table_driven: |
| 1269 | out += [ |
| 1270 | CodeGen(opt, 4*' ', [ |
| 1271 | 'unsigned int tbl_idx;', |
| 1272 | '', |
| 1273 | Conditional2(opt, '', opt.reflect_in == None, [ |
| 1274 | 'if (cfg->reflect_in) {', |
| 1275 | CodeGen(opt, 4*' ', [ |
| 1276 | 'while (data_len--) {', |
| 1277 | CodeGen(opt, 4*' ', [ |
| 1278 | _crc_table_core_algorithm_reflected(opt, sym), |
| 1279 | 'd++;', |
| 1280 | ]), |
| 1281 | '}', |
| 1282 | ]), |
| 1283 | '} else {', |
| 1284 | CodeGen(opt, 4*' ', [ |
| 1285 | 'while (data_len--) {', |
| 1286 | CodeGen(opt, 4*' ', [ |
| 1287 | _crc_table_core_algorithm_nonreflected(opt, sym), |
| 1288 | 'd++;', |
| 1289 | ]), |
| 1290 | '}', |
| 1291 | ]), |
| 1292 | '}', |
| 1293 | ], [ |
| 1294 | Conditional(opt, '', opt.slice_by > 1, [ |
| 1295 | '/* Align to a multiple of {crc_slice_by} bytes */'.format(**sym), |
| 1296 | 'while (data_len && (((uintptr_t)(const void *)d) % {crc_slice_by} != 0))'.format(**sym) + ' {', |
| 1297 | CodeGen(opt, 4*' ', [ |
| 1298 | _crc_table_core_algorithm(opt, sym), |
| 1299 | 'data_len--;', |
| 1300 | ]), |
| 1301 | '}', |
| 1302 | '', |
| 1303 | _crc_table_slice_by_algorithm(opt, sym), |
| 1304 | '/* Remaining bytes with the standard algorithm */', |
| 1305 | 'd = (const unsigned char *)d32;', |
| 1306 | ]), |
| 1307 | 'while (data_len--) {', |
| 1308 | CodeGen(opt, 4*' ', [ |
| 1309 | _crc_table_core_algorithm(opt, sym), |
| 1310 | ]), |
| 1311 | '}', |
| 1312 | ]), |
| 1313 | 'return {0};'.format(expr.And('crc', sym['cfg_mask']).simplify()), |
| 1314 | ]), |
| 1315 | ] |
| 1316 | out += [ |
| 1317 | '}', |
| 1318 | ] |
| 1319 | return out |
| 1320 | |
| 1321 | |
| 1322 | |
| 1323 | def _crc_finalize_function_gen(opt, sym): |
| 1324 | """ |
| 1325 | Return the code for the finalize function. |
| 1326 | """ |
| 1327 | if _use_inline_crc_finalize(opt): |
| 1328 | return [] |
| 1329 | out = [ |
| 1330 | '', '', |
| 1331 | _crc_finalize_function_def(opt, sym), |
| 1332 | '{', |
| 1333 | ] |
| 1334 | if opt.algorithm in set([opt.algo_bit_by_bit, opt.algo_bit_by_bit_fast]): |
| 1335 | out += [ |
| 1336 | Conditional(opt, 4*' ', opt.algorithm == opt.algo_bit_by_bit, [ |
| 1337 | 'unsigned int i;', |
| 1338 | '{c_bool} bit;'.format(**sym), |
| 1339 | '', |
| 1340 | 'for (i = 0; i < ' + sym['cfg_width'] + '; i++) {', |
| 1341 | CodeGen(opt, 4*' ', [ |
| 1342 | Conditional2(opt, '', opt.c_std == 'C89', [ |
| 1343 | 'bit = !!(crc & {cfg_msb_mask});'.format(**sym) |
| 1344 | ], [ |
| 1345 | 'bit = crc & {cfg_msb_mask};'.format(**sym), |
| 1346 | ]), |
| 1347 | 'crc <<= 1;', |
| 1348 | 'if (bit) {', |
| 1349 | CodeGen(opt, 4*' ', [ |
| 1350 | 'crc ^= {cfg_poly};'.format(**sym), |
| 1351 | ]), |
| 1352 | '}', |
| 1353 | ]), |
| 1354 | '}', |
| 1355 | Conditional(opt, '', opt.reflect_out is None, [ |
| 1356 | 'if (' + sym['cfg_reflect_out'] + ') {', |
| 1357 | CodeGen(opt, 4*' ', [ |
| 1358 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1359 | ]), |
| 1360 | '}', |
| 1361 | ]), |
| 1362 | Conditional(opt, '', opt.reflect_out, [ |
| 1363 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1364 | ]), |
| 1365 | ]), |
| 1366 | |
| 1367 | Conditional(opt, 4*' ', opt.algorithm == opt.algo_bit_by_bit_fast, [ |
| 1368 | Conditional(opt, '', opt.reflect_out is None, [ |
| 1369 | 'if (' + sym['cfg_reflect_out'] + ') {', |
| 1370 | CodeGen(opt, 4*' ', [ |
| 1371 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1372 | ]), |
| 1373 | '}', |
| 1374 | ]), |
| 1375 | Conditional(opt, '', opt.reflect_out, [ |
| 1376 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1377 | ]), |
| 1378 | ]), |
| 1379 | ] |
| 1380 | |
| 1381 | if opt.algorithm == opt.algo_table_driven: |
| 1382 | if opt.reflect_in is None or opt.reflect_out is None: |
| 1383 | if opt.reflect_in is None and opt.reflect_out is None: |
| 1384 | cond = 'cfg->reflect_in != cfg->reflect_out' |
| 1385 | elif opt.reflect_out is None: |
| 1386 | cond = '!' if opt.reflect_in else '' + 'cfg->reflect_out' |
| 1387 | else: |
| 1388 | cond = '!' if opt.reflect_out else '' + 'cfg->reflect_in' |
| 1389 | out += [ |
| 1390 | CodeGen(opt, 4*' ', [ |
| 1391 | 'if (' + cond + ') {', |
| 1392 | CodeGen(opt, 4*' ', [ |
| 1393 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1394 | ]), |
| 1395 | '}', |
| 1396 | ]), |
| 1397 | ] |
| 1398 | elif opt.reflect_in != opt.reflect_out: |
| 1399 | out += [ |
| 1400 | 'crc = {crc_reflect_function}(crc, {cfg_width});'.format(**sym), |
| 1401 | ] |
| 1402 | out += [ |
| 1403 | CodeGen(opt, 4*' ', [ |
| 1404 | 'return {0};'.format(expr.And(expr.Parenthesis(expr.Xor('crc', sym['cfg_xor_out'])), sym['cfg_mask']).simplify()), |
| 1405 | ]), |
| 1406 | '}', |
| 1407 | ] |
| 1408 | return out |
| 1409 | |
| 1410 | def _crc_table_core_algorithm(opt, sym): |
| 1411 | """ |
| 1412 | Return the core of the table-driven algorithm. |
| 1413 | """ |
| 1414 | out = [] |
| 1415 | out += [ |
| 1416 | Conditional2(opt, '', opt.reflect_in, [ |
| 1417 | _crc_table_core_algorithm_reflected(opt, sym), |
| 1418 | ], [ |
| 1419 | _crc_table_core_algorithm_nonreflected(opt, sym), |
| 1420 | ]), |
| 1421 | 'd++;', |
| 1422 | ] |
| 1423 | return CodeGen(opt, '', out) |
| 1424 | |
| 1425 | def _crc_table_core_algorithm_reflected(opt, sym): |
| 1426 | """ |
| 1427 | Return the core loop of the table-driven algorithm, reflected variant. |
| 1428 | """ |
| 1429 | out = [] |
| 1430 | if opt.width is not None and opt.tbl_idx_width is not None and opt.width <= opt.tbl_idx_width: |
| 1431 | crc_xor_expr = '0' |
| 1432 | else: |
| 1433 | crc_xor_expr = '(crc >> {cfg_table_idx_width})'.format(**sym) |
| 1434 | |
| 1435 | if opt.tbl_idx_width == 8: |
| 1436 | if opt.slice_by > 1: |
| 1437 | crc_lookup = 'crc_table[0][tbl_idx]' |
| 1438 | else: |
| 1439 | crc_lookup = 'crc_table[tbl_idx]' |
| 1440 | out += [ |
| 1441 | Conditional2(opt, '', opt.width is None or opt.width > 8, [ |
| 1442 | 'tbl_idx = (crc ^ *d) & {crc_table_mask};'.format(**sym), |
| 1443 | ], [ |
| 1444 | 'tbl_idx = crc ^ *d;', |
| 1445 | ]), |
| 1446 | 'crc = {0};'.format(expr.And(expr.Parenthesis(expr.Xor(crc_lookup, expr.Parenthesis(expr.Shr('crc', sym['cfg_table_idx_width'])))), sym['cfg_mask']).simplify()), |
| 1447 | ] |
| 1448 | else: |
| 1449 | crc_lookup = 'crc_table[tbl_idx & {crc_table_mask}]'.format(**sym) |
| 1450 | for i in range(8 // opt.tbl_idx_width): |
| 1451 | out += [ |
| 1452 | 'tbl_idx = {0};'.format(expr.Xor('crc', expr.Parenthesis(expr.Shr('*d', expr.Parenthesis(expr.Mul(i, sym['cfg_table_idx_width']))))).simplify()), |
| 1453 | 'crc = {0};'.format(expr.Xor(crc_lookup, crc_xor_expr).simplify()) |
| 1454 | ] |
| 1455 | return CodeGen(opt, '', out) |
| 1456 | |
| 1457 | def _crc_table_core_algorithm_nonreflected(opt, sym): |
| 1458 | """ |
| 1459 | Return the core loop of the table-driven algorithm, non-reflected variant. |
| 1460 | """ |
| 1461 | out = [] |
| 1462 | if opt.width == None: |
| 1463 | crc_shifted_right = expr.Parenthesis(expr.Shr('crc', expr.Parenthesis(expr.Sub(sym['cfg_width'], sym['cfg_table_idx_width'])))).simplify() |
| 1464 | elif opt.width < 8: |
| 1465 | shift_val = opt.width - opt.tbl_idx_width |
| 1466 | if shift_val < 0: |
| 1467 | crc_shifted_right = expr.Parenthesis(expr.Shl('crc', -shift_val)).simplify() |
| 1468 | else: |
| 1469 | crc_shifted_right = expr.Parenthesis(expr.Shr('crc', shift_val)).simplify() |
| 1470 | else: |
| 1471 | shift_val = opt.width - opt.tbl_idx_width |
| 1472 | crc_shifted_right = expr.Parenthesis(expr.Shr('crc', shift_val)).simplify() |
| 1473 | |
| 1474 | if opt.width is not None and opt.tbl_idx_width is not None and opt.width <= opt.tbl_idx_width: |
| 1475 | crc_xor_expr = '0' |
| 1476 | else: |
| 1477 | crc_xor_expr = '(crc << {cfg_table_idx_width})'.format(**sym) |
| 1478 | |
| 1479 | if opt.tbl_idx_width == 8: |
| 1480 | if opt.slice_by > 1: |
| 1481 | crc_lookup = 'crc_table[0][tbl_idx]' |
| 1482 | else: |
| 1483 | crc_lookup = 'crc_table[tbl_idx]' |
| 1484 | out += [ |
| 1485 | Conditional2(opt, '', opt.width is None or opt.width > 8, [ |
| 1486 | 'tbl_idx = {0};'.format(expr.And(expr.Parenthesis(expr.Xor(crc_shifted_right, '*d')), sym['crc_table_mask']).simplify()) |
| 1487 | ], [ |
| 1488 | 'tbl_idx = {0};'.format(expr.Xor(crc_shifted_right, '*d').simplify()) |
| 1489 | ]), |
| 1490 | 'crc = {0};'.format(expr.And(expr.Parenthesis(expr.Xor(crc_lookup, crc_xor_expr)), sym['cfg_mask']).simplify()) |
| 1491 | ] |
| 1492 | else: |
| 1493 | crc_lookup = 'crc_table[tbl_idx & {crc_table_mask}]'.format(**sym) |
| 1494 | for i in range(8 // opt.tbl_idx_width): |
| 1495 | str_idx = '{0:d}'.format(8 - (i + 1) * opt.tbl_idx_width) |
| 1496 | out += [ |
| 1497 | 'tbl_idx = {0};'.format(expr.Xor(crc_shifted_right, expr.Parenthesis(expr.Shr('*d', str_idx)))), |
| 1498 | 'crc = {0};'.format(expr.Xor(crc_lookup, crc_xor_expr).simplify()), |
| 1499 | ] |
| 1500 | return CodeGen(opt, '', out) |
| 1501 | |
| 1502 | def _crc_table_slice_by_algorithm(opt, sym): |
| 1503 | update_be = [] |
| 1504 | for i in range(opt.slice_by // 4): |
| 1505 | vard = 'd{0}'.format(opt.slice_by // 4 - i) |
| 1506 | for j in range(4): |
| 1507 | idx1 = i * 4 + j |
| 1508 | idx2 = expr.And(expr.Parenthesis(expr.Shr(vard, j*8)), expr.Terminal(255, '0xffu')).simplify() |
| 1509 | update_be.append('crc_table[{0}][{1}]{2}'.format(idx1, idx2, ' ^' if idx1 < opt.slice_by - 1 else ';')) |
| 1510 | |
| 1511 | update_le = [] |
| 1512 | for i in range(opt.slice_by // 4): |
| 1513 | vard = 'd{0}'.format(opt.slice_by // 4 - i) |
| 1514 | for j in range(4): |
| 1515 | idx1 = i * 4 + j |
| 1516 | idx2 = expr.And(expr.Parenthesis(expr.Shr(vard, 24 - j*8)), expr.Terminal(255, '0xffu')).simplify() |
| 1517 | update_le.append('crc_table[{0}][{1}]{2}'.format(idx1, idx2, ' ^' if idx1 < opt.slice_by - 1 else ';')) |
| 1518 | |
| 1519 | out = [ |
| 1520 | 'const uint32_t *d32 = (const uint32_t *)d;', |
| 1521 | 'while (data_len >= {crc_slice_by})'.format(**sym), |
| 1522 | '{', |
| 1523 | CodeGen(opt, 4*' ', [ |
| 1524 | CodeGen(opt, None, [ |
| 1525 | '#if __BYTE_ORDER == __BIG_ENDIAN', |
| 1526 | ]), |
| 1527 | '{crc_t} d1 = *d32++ ^ le16toh(crc);'.format(**sym), |
| 1528 | Conditional(opt, '', opt.slice_by >= 8, [ |
| 1529 | '{crc_t} d2 = *d32++;'.format(**sym), |
| 1530 | ]), |
| 1531 | Conditional(opt, '', opt.slice_by >= 16, [ |
| 1532 | '{crc_t} d3 = *d32++;'.format(**sym), |
| 1533 | '{crc_t} d4 = *d32++;'.format(**sym), |
| 1534 | ]), |
| 1535 | 'crc =', |
| 1536 | CodeGen(opt, 4*' ', update_be), |
| 1537 | CodeGen(opt, None, [ |
| 1538 | '#else', |
| 1539 | ]), |
| 1540 | '{crc_t} d1 = *d32++ ^ crc;'.format(**sym), |
| 1541 | Conditional(opt, '', opt.slice_by >= 8, [ |
| 1542 | '{crc_t} d2 = *d32++;'.format(**sym), |
| 1543 | ]), |
| 1544 | Conditional(opt, '', opt.slice_by >= 16, [ |
| 1545 | '{crc_t} d3 = *d32++;'.format(**sym), |
| 1546 | '{crc_t} d4 = *d32++;'.format(**sym), |
| 1547 | ]), |
| 1548 | 'crc =', |
| 1549 | CodeGen(opt, 4*' ', update_le), |
| 1550 | CodeGen(opt, None, [ |
| 1551 | '#endif', |
| 1552 | ]), |
| 1553 | '', |
| 1554 | 'data_len -= {crc_slice_by};'.format(**sym), |
| 1555 | ]), |
| 1556 | '}', |
| 1557 | '', |
| 1558 | ] |
| 1559 | return CodeGen(opt, '', out) |