#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
// A helper function, which is performed very very rare.
void SaveCode (const uint8_t length, const uint64_t code);
int main (int argc, char * argv [])
{
const uint8_t sideLobeLimit= 1;
const uint8_t length = 13;
const uint64_t beginCode = 1ull << (length - 1);
const uint64_t endCode = (1ull << length) - 1;
const uint64_t mask = (1ull << (length - 1) ) - 1ull;
__asm__ __volatile__ (
"INIT: \n\t" // Prepare for computation.
" xorq %%r8, %%r8 \n\t"
" movb %[length], %%r8b \n\t" // Load length of sequences into CPU register.
" movq %[code], %%r9 \n\t" // Load first sequence of the range into CPU register.
" movq %[maxcode], %%r10 \n\t" // Load last sequence of the range into CPU register.
" movb %[limit], %%r11b \n\t" // Load maximum allowed level of sidelobes into CPU register.
" movq %[mask], %%r12 \n\t" // Load mask for extracting significant bits into CPU register.
"CHECK_CODE: \n\t" // Body of loop through sequence (like the "do-while" loop).
" mov $1, %%cx \n\t" // Set the offset value.
" movq %%r12, %%r13 \n\t" // Set mask into mutable variable.
"NEXT_SHIFT: \n\t" // Beginning of loop through shift of sequence (like the "do-while" loop).
" movq %%r9, %%rdi \n\t" // Shifting sequence.
" shrq %%cl, %%rdi \n\t" // Shift.
" xorq %%r9, %%rdi \n\t" // Counting level of sidelobes.
" andq %%r13, %%rdi \n\t" // Remove extra bits.
" popcntq %%rdi, %%rax \n\t" // al = n (number of the different bits).
" shl $1, %%ax \n\t" // al = 2 * n.
" sub %%r8w, %%ax \n\t" // al = 2 * n - l (l - length of the sequence).
" add %%cx, %%ax \n\t" // al = o + 2 * n - l (o - current offset).
" cwd \n\t" // .
" add %%dx, %%ax \n\t" // .
" xor %%dx, %%ax \n\t" // al =|o + 2 * n - l| (now al contain the sidelobe level).
" cmpb %%r11b, %%al \n\t" // Check if the sidelobe level acceptable?
" jg NEXT_CODE \n\t" // If it is not, then go to the next sequence.
" incb %%cl \n\t" // Increment the offset for creating next shifted sequence.
" cmpb %%cl, %%r8b \n\t" // Check if is it the lass offset.
" jbe SAVE_CODE \n\t" // If it is, then save cureent sequence.
" shrq $1, %%r13 \n\t" // Shift mask for next shifted sequence.
" jmp NEXT_SHIFT \n\t" // End of loop through shift of sequence.
"NEXT_CODE: \n\t" // Control of loop through sequence.
" incq %%r9 \n\t" // Set next sequence.
" cmpq %%r10, %%r9 \n\t" // Check if the sequence inside the range.
" jbe CHECK_CODE \n\t" // If it is, then go to the begining of the loops body.
" jmp QUIT \n\t" // If it is not, then go to the end of procedure.
"SAVE_CODE: \n\t" // Saving sequence with accepted level of sidelobes.
" pushq %%r8 \n\t" // Store registers.
" pushq %%r9 \n\t" // .
" pushq %%r10 \n\t" // .
" pushq %%r11 \n\t" // .
" pushq %%r12 \n\t" // .
" movl %%r8d, %%edi \n\t" // .
" movq %%r9, %%rsi \n\t" // .
" call SaveCode \n\t" // Calling external function for saving the sequence.
" popq %%r12 \n\t" // Restore registers.
" popq %%r11 \n\t" // .
" popq %%r10 \n\t" // .
" popq %%r9 \n\t" // .
" popq %%r8 \n\t" // .
" jmp NEXT_CODE \n\t" // Continue test sequences.
"QUIT: \n\t" // Exit of procedure.
" nop \n\t" // .
:
: [length ] "m" (length),
[code ] "m" (beginCode),
[maxcode] "m" (endCode),
[limit ] "m" (sideLobeLimit),
[mask ] "m" (mask)
: "%rax", "%rcx", "%rdx", "%rdi", "%rsi",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13"
);
return EXIT_SUCCESS;
}
void SaveCode (const uint8_t length, const uint64_t code)
{
uint8_t i = 0;
for (i = 0; i < length; ++i) {
(code >> i) & 0x01 ? printf ("+") : printf ("-");
}
printf ("\n");
}