#ifdef GENERATE_ASM_TRACKING_DATA #ifndef COMPILE_ASM extern "C" uint64 asm_tracking_data[num_asm_tracking_data]; extern "C" char* asm_tracking_data_comments[num_asm_tracking_data]; uint64 asm_tracking_data[num_asm_tracking_data]; char* asm_tracking_data_comments[num_asm_tracking_data]; #endif #endif namespace asm_code { //all doubles are arrays with 2 entries. the high entry is first followed by the low entry //so: b, a; u1, u0; v1, v0 //is_lehmer is all 1s or all 0s. ab_threshold is duplicated twice extern "C" int asm_func_gcd_base(double* ab, double* u, double* v, uint64* is_lehmer, double* ab_threshold, uint64* no_progress); #ifdef COMPILE_ASM void compile_asm_gcd_base() { EXPAND_MACROS_SCOPE; asm_function c_func( "gcd_base", 6 ); reg_alloc regs=c_func.regs; reg_vector ab=regs.bind_vector(m, "ab"); reg_vector u=regs.bind_vector(m, "u"); reg_vector v=regs.bind_vector(m, "v"); reg_vector is_lehmer=regs.bind_vector(m, "is_lehmer"); reg_vector ab_threshold=regs.bind_vector(m, "ab_threshold"); m.bind(c_func.args.at(0), "ab_addr"); m.bind(c_func.args.at(1), "u_addr"); m.bind(c_func.args.at(2), "v_addr"); m.bind(c_func.args.at(3), "is_lehmer_addr"); m.bind(c_func.args.at(4), "ab_threshold_addr"); m.bind(c_func.args.at(5), "no_progress_addr"); APPEND_M(str( "MOVDQU `ab, [`ab_addr]" )); APPEND_M(str( "MOVDQU `u, [`u_addr]" )); APPEND_M(str( "MOVDQU `v, [`v_addr]" )); APPEND_M(str( "MOVDQU `is_lehmer, [`is_lehmer_addr]" )); APPEND_M(str( "MOVDQU `ab_threshold, [`ab_threshold_addr]" )); string no_progress_label=m.alloc_label(); string progress_label=m.alloc_label(); string exit_label=m.alloc_label(); gcd_base_continued_fraction(regs, ab, u, v, is_lehmer, ab_threshold, no_progress_label); APPEND_M(str( "JMP #", progress_label )); APPEND_M(str( "#:", no_progress_label )); APPEND_M(str( "MOV QWORD PTR [`no_progress_addr], 1" )); APPEND_M(str( "JMP #", exit_label )); APPEND_M(str( "#:", progress_label )); APPEND_M(str( "MOV QWORD PTR [`no_progress_addr], 0" )); APPEND_M(str( "#:", exit_label )); APPEND_M(str( "MOVDQU [`ab_addr], `ab" )); APPEND_M(str( "MOVDQU [`u_addr], `u" )); APPEND_M(str( "MOVDQU [`v_addr], `v" )); APPEND_M(str( "MOVDQU [`is_lehmer_addr], `is_lehmer" )); APPEND_M(str( "MOVDQU [`ab_threshold_addr], `ab_threshold" )); } #endif //104 bytes struct asm_func_gcd_128_data { //4 uint64 ab_start_0_0; uint64 ab_start_0_8; uint64 ab_start_1_0; uint64 ab_start_1_8; //4 uint64 u_0; uint64 u_1; uint64 v_0; uint64 v_1; //5 uint64 parity; //1 if odd, else 0 uint64 is_lehmer; //1 if true, else 0 uint64 ab_threshold_0; uint64 ab_threshold_8; uint64 no_progress; }; extern "C" int asm_func_gcd_128(asm_func_gcd_128_data* data); #ifdef COMPILE_ASM void compile_asm_gcd_128() { EXPAND_MACROS_SCOPE_PUBLIC; asm_function c_func( "gcd_128", 1 ); reg_alloc regs_parent=c_func.regs; reg_spill spill_data_addr=regs_parent.bind_spill(m, "spill_data_addr"); reg_spill spill_data=regs_parent.bind_spill(m, "spill_data", sizeof(asm_func_gcd_128_data), 8); assert(sizeof(asm_func_gcd_128_data)%8==0); { EXPAND_MACROS_SCOPE; reg_alloc regs=regs_parent; m.bind(c_func.args.at(0), "data_addr"); reg_scalar tmp=regs.bind_scalar(m, "tmp"); APPEND_M(str( "MOV `spill_data_addr, `data_addr" )); for (int x=0;x