From 51169f5f9ab178a4ddfe9dac461405a71c9c0f94 Mon Sep 17 00:00:00 2001 From: Mike Vink Date: Wed, 22 May 2024 08:49:29 +0200 Subject: organise --- 3/6_control/20_op_bias.c | 10 +++++++ 3/6_control/21_test_cmov.c | 20 +++++++++++++ 3/6_control/22_loop.c | 51 ++++++++++++++++++++++++++++++++++ 3/6_control/23_reverse_engineer_loop.c | 28 +++++++++++++++++++ 3/6_control/24_while_loop.c | 24 ++++++++++++++++ 3/6_control/absdiff_goto.c | 39 ++++++++++++++++++++++++++ 3/6_control/comp.c | 36 ++++++++++++++++++++++++ 3/6_control/cond.c | 6 ++++ 3/6_control/missing.c | 13 +++++++++ 9 files changed, 227 insertions(+) create mode 100644 3/6_control/20_op_bias.c create mode 100644 3/6_control/21_test_cmov.c create mode 100644 3/6_control/22_loop.c create mode 100644 3/6_control/23_reverse_engineer_loop.c create mode 100644 3/6_control/24_while_loop.c create mode 100644 3/6_control/absdiff_goto.c create mode 100644 3/6_control/comp.c create mode 100644 3/6_control/cond.c create mode 100644 3/6_control/missing.c (limited to '3/6_control') diff --git a/3/6_control/20_op_bias.c b/3/6_control/20_op_bias.c new file mode 100644 index 0000000..b071eb9 --- /dev/null +++ b/3/6_control/20_op_bias.c @@ -0,0 +1,10 @@ +#define OP < + +// x <- %rdi +// %rbx <- 15 + (x), bias to round towards zero +// ZF, SF <- %rdi & %rdi, check if pos or neg +// %rbx <- x if x >= 0, set to unbiased if pos +// %rbx <- %rbx >> 4, divide by 16 +short arith(short x) { + return x / 16; +} diff --git a/3/6_control/21_test_cmov.c b/3/6_control/21_test_cmov.c new file mode 100644 index 0000000..a90d178 --- /dev/null +++ b/3/6_control/21_test_cmov.c @@ -0,0 +1,20 @@ +#include + +// Remember that jumps flip conditionals +// Also testq rdi rdi and jge test if the sign bit is set +short test(short x, short y) { + short val = 12 + y; + if (x < 0) { + if (x >= y) + val = x | y; + else + val = x * y; + } else if (y >= 10) { + val = x / y; + } + return val; +} + +int main(void) { + return 0; +} diff --git a/3/6_control/22_loop.c b/3/6_control/22_loop.c new file mode 100644 index 0000000..73c7710 --- /dev/null +++ b/3/6_control/22_loop.c @@ -0,0 +1,51 @@ +#include +#include +#include +// do +// body +// while (test); +// +// loop: +// body +// t = test; +// if (t) +// goto loop; + +typedef int64_t fact_t; + +long fact_do(long n) +{ + long result = 1; + do { + result *= n; + n = n-1; + } while (n > 1); + return result; +} + +int tmult_ok(fact_t x, fact_t y) +{ + fact_t p = x*y; + return !x || p/x == y; +} + +fact_t fact_do_int(size_t n) +{ + fact_t result = 1; + do { + if (tmult_ok(result, n)) { + result *= n; + n = n-1; + } else { + printf("would overflow this iter, n=%ld\n", n); + n = 0; + } + } while (n > 1); + return result; +} + +int main(void) { + size_t f = 20; + printf("result: %ld, max: %ld, less: %d", fact_do_int(f), INT64_MAX, fact_do_int(f) < INT64_MAX); + return 0; +} diff --git a/3/6_control/23_reverse_engineer_loop.c b/3/6_control/23_reverse_engineer_loop.c new file mode 100644 index 0000000..922b317 --- /dev/null +++ b/3/6_control/23_reverse_engineer_loop.c @@ -0,0 +1,28 @@ +short dw_loop(short x) +{ + short y = x/9; + short *p = &x; + short n = 4*x; + do { + x += y; + (*p) += 5; + n += 2; + } while (n > 0); + return x; +} + +// x in %rdi +// dw_loop: +// movq %rdi, %rdx # %rbx <- x +// movq %rdi, %rcx # %rcx <- x +// idivq $9, %rcx # %rcx (y) <- x / 9 +// leaq (,%rdi,4), %rdx # %rdx (n) <- x * 4 +// .L2: +// leaq 5(%rbx,%rcx), %rcx # %rbx (x) <- 5 + %rbx (x) + %rcx (y) +// subq $1, %rdx # %rdx (n) <- n - 1 +// testq %rdx, %rdx # n > 0 ? +// jg .L2 # if n > 0, goto .L2 +// rep; ret +// +// A. x in rbx, y in rcx, n in rdx +// B. The pointer is never used besides incrementing the value at the address. So it is replaced by a incrementing instruction in the loop. diff --git a/3/6_control/24_while_loop.c b/3/6_control/24_while_loop.c new file mode 100644 index 0000000..a3367fc --- /dev/null +++ b/3/6_control/24_while_loop.c @@ -0,0 +1,24 @@ +// while (test) +// body +// +// goto test; +// loop: +// body; +// test: +// t = test; +// if (t) +// goto loop; + +short loop_while(short a, short b) +{ + short result = ; + while () { + result = ; + a = ; + } + return result; +} + +int main(void) { + return 0; +} diff --git a/3/6_control/absdiff_goto.c b/3/6_control/absdiff_goto.c new file mode 100644 index 0000000..dfcb3be --- /dev/null +++ b/3/6_control/absdiff_goto.c @@ -0,0 +1,39 @@ +#include + +// if (!t) +// goto false; +// then- +// goto done; +// false: +// else- +// goto done; +// done: +// ... +long gotodiff_se(long x, long y) +{ + long result; + if (x >= y) + goto x_ge_y; + lt_cnt++; + result = y - x; + return result; + +x_get_y: + ge_cnt++; + result = x - y; + return result; +} + +long gotodiff_se_alternate(long x, long y) +{ + long result; + if (x < y) + goto x_le_y; + ge_cnt++; + result = x - y; + return result; +x_le_y: + lt_cnt++; + result = y - x; + return result; +} diff --git a/3/6_control/comp.c b/3/6_control/comp.c new file mode 100644 index 0000000..beba875 --- /dev/null +++ b/3/6_control/comp.c @@ -0,0 +1,36 @@ +#include + +typedef char data_t; + +#define COMP <= + +// a in rdx, b in rsi +// +// cmpl %esi, %edi (Compare long (double word, or 4 bytes). (a - b) ) +// setl %al (set lower? %rax return value) +// +// COMP is <, and data_t is 32 bits so maybe int or unsigned int or float +// +// cmpw %si, %di (Compare word (a-b), short) +// setge %al (Greater than or equal >=) +// +// cmpb %sil, %dil (Compare byte (a-b)) +// setbe %al (Comp <=) +// +// cmpq %rsi, %rdi (Compare 8 bytes quad words (long , double, char *)) +// setne %al +int comp(data_t a, data_t b) { + return a COMP b; +} + +#define TEST > + +int test(data_t a) { + return a TEST 0; +} + +int main() { + printf("%x hello world", comp(1, 2)); + return 0; +} + diff --git a/3/6_control/cond.c b/3/6_control/cond.c new file mode 100644 index 0000000..8b647bf --- /dev/null +++ b/3/6_control/cond.c @@ -0,0 +1,6 @@ +void cond(short a, short *p) +{ + if (a && *p < a) { + *p = a; + } +} diff --git a/3/6_control/missing.c b/3/6_control/missing.c new file mode 100644 index 0000000..1b8067b --- /dev/null +++ b/3/6_control/missing.c @@ -0,0 +1,13 @@ +short test(short x, short y, short z) { + short val = (z+y) - x; + if (z > 5) { + if (y > 2) { + val = x/z; + } else { + val = x/y; + } + } else if (z < 3) { + val = z/y; + } + return val; +} -- cgit v1.2.3