aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLéo Gourdin <leo.gourdin@univ-grenoble-alpes.fr>2020-10-29 14:15:19 +0100
committerLéo Gourdin <leo.gourdin@univ-grenoble-alpes.fr>2020-10-29 14:15:19 +0100
commit8de1a1f5811470bc1d7d1a7b2f0e5193de40698e (patch)
treefccc46231cadc14956a1c50828626433a1c69512
parentaabfd379b2d58afc5b89dfa2d753e56354c1fccb (diff)
downloadcompcert-kvx-8de1a1f5811470bc1d7d1a7b2f0e5193de40698e.tar.gz
compcert-kvx-8de1a1f5811470bc1d7d1a7b2f0e5193de40698e.zip
End of Asmblock translation
-rw-r--r--aarch64/Asmblockgen.v74
-rw-r--r--test/aarch64/README.md15
-rwxr-xr-xtest/aarch64/asmb_aarch64_gen_test.sh111
-rw-r--r--test/aarch64/c/addresses.c32
-rw-r--r--test/aarch64/c/array1.c64
-rw-r--r--test/aarch64/c/array2.c74
-rw-r--r--test/aarch64/c/cpintarray.c108
-rw-r--r--test/aarch64/c/enum1.c52
-rw-r--r--test/aarch64/c/enum2.c50
-rw-r--r--test/aarch64/c/funcs.c2
-rw-r--r--test/aarch64/c/power2.c42
-rw-r--r--test/aarch64/c/random.c50
12 files changed, 613 insertions, 61 deletions
diff --git a/aarch64/Asmblockgen.v b/aarch64/Asmblockgen.v
index 8e095553..fc356d52 100644
--- a/aarch64/Asmblockgen.v
+++ b/aarch64/Asmblockgen.v
@@ -298,12 +298,23 @@ Definition make_epilogue (f: Machblock.function) : bcode :=
(** Add immediate *)
+Definition addimm_aux (insn: Z -> arith_pp)
+ (rd r1: iregsp) (n: Z) (k: bcode) :=
+ let nlo := Zzero_ext 12 n in
+ let nhi := n - nlo in
+ if Z.eqb nhi 0 then
+ insn nlo rd r1 ::bi k
+ else if Z.eqb nlo 0 then
+ insn nhi rd r1 ::bi k
+ else
+ insn nhi rd r1 ::bi insn nlo rd rd ::bi k.
+
Definition addimm32 (rd r1: ireg) (n: int) (k: bcode) : bcode :=
let m := Int.neg n in
if Int.eq n (Int.zero_ext 24 n) then
- Paddimm W (Int.unsigned n) rd r1 ::bi k
+ addimm_aux (Paddimm W) rd r1 (Int.unsigned n) k
else if Int.eq m (Int.zero_ext 24 m) then
- Psubimm W (Int.unsigned m) rd r1 ::bi k
+ addimm_aux (Psubimm W) rd r1 (Int.unsigned m) k
else if Int.lt n Int.zero then
loadimm32 X16 m (Psub W SOnone rd r1 X16 ::bi k)
else
@@ -312,9 +323,9 @@ Definition addimm32 (rd r1: ireg) (n: int) (k: bcode) : bcode :=
Definition addimm64 (rd r1: iregsp) (n: int64) (k: bcode) : bcode :=
let m := Int64.neg n in
if Int64.eq n (Int64.zero_ext 24 n) then
- Paddimm X (Int64.unsigned n) rd r1 ::bi k
+ addimm_aux (Paddimm X) rd r1 (Int64.unsigned n) k
else if Int64.eq m (Int64.zero_ext 24 m) then
- Psubimm X (Int64.unsigned m) rd r1 ::bi k
+ addimm_aux (Psubimm X) rd r1 (Int64.unsigned m) k
else if Int64.lt n Int64.zero then
loadimm64 X16 m (Psubext (EOuxtx Int.zero) rd r1 X16 ::bi k)
else
@@ -1120,42 +1131,26 @@ Definition transl_instr_basic (f: Machblock.function) (i: Machblock.basic_inst)
loadind XSP ofs ty dst k
| MBsetstack src ofs ty =>
storeind src XSP ofs ty k
+ | MBgetparam ofs ty dst =>
+ do c <- loadind X29 ofs ty dst k;
+ OK (if ep then c else loadptr_bc XSP f.(fn_link_ofs) X29 c)
| MBop op args res =>
transl_op op args res k
| MBload _ chunk addr args dst =>
transl_load chunk addr args dst k
- (*| MBstore chunk addr args src =>*)
- (*transl_store chunk addr args src k*)
- | _ => Error(msg "Not implemented yet")
- (*| MBgetparam ofs ty dst =>*)
- (*[> load via the frame pointer if it is valid <]*)
- (*do c <- loadind FP ofs ty dst k;*)
- (*OK (if ep then c*)
- (*else (loadind_ptr SP f.(fn_link_ofs) FP) ::i c)*)
- (*| MBop op args res =>*)
- (*transl_op op args res k*)
+ | MBstore chunk addr args src =>
+ transl_store chunk addr args src k
end.
(** Translation of a code sequence *)
-(* TODO to remove ? *)
-(*Definition fp_is_parent (before: bool) (i: Machblock.basic_inst) : bool :=*)
- (*match i with*)
- (*| MBgetstack ofs ty dst => before && negb (mreg_eq dst MFP)*)
- (*| MBsetstack src ofs ty => before*)
- (*| MBgetparam ofs ty dst => negb (mreg_eq dst MFP)*)
- (*| MBop op args res => before && negb (mreg_eq res MFP)*)
- (*| MBload trapping_mode chunk addr args dst => before && negb (mreg_eq dst MFP)*)
- (*| MBstore chunk addr args res => before*)
- (*end.*)
-
Definition it1_is_parent (before: bool) (i: Machblock.basic_inst) : bool :=
match i with
- | MBgetstack ofs ty dst => before && negb (mreg_eq dst R29)
- (*| Msetstack src ofs ty => before*)
- (*| Mgetparam ofs ty dst => negb (mreg_eq dst R29)*)
+ (*| MBgetstack ofs ty dst => before && negb (mreg_eq dst R29)*)
+ | MBsetstack src ofs ty => before
+ | MBgetparam ofs ty dst => negb (mreg_eq dst R29)
| MBop op args res => before && negb (mreg_eq res R29)
- | MBload trapping_mode chunk addr args dst => before && negb (mreg_eq dst R29)
+ (*| MBload trapping_mode chunk addr args dst => before && negb (mreg_eq dst R29)*)
| _ => false
end.
@@ -1204,28 +1199,31 @@ Obligation 1.
rewrite <- Heq_anonymous. constructor.
Qed.
-Definition transl_control (f: Machblock.function) (ctl: control_flow_inst) (ep: bool) : res (bcode*control) :=
+Definition transl_control (f: Machblock.function) (ctl: control_flow_inst) : res (bcode*control) :=
match ctl with
- | MBcall sig (inl r) => do r1 <- ireg_of r; OK (nil, PCtlFlow (Pblr r1 sig))
+ | MBcall sig (inl r) => do r1 <- ireg_of r;
+ OK (nil, PCtlFlow (Pblr r1 sig))
| MBcall sig (inr symb) => OK (nil, PCtlFlow (Pbl symb sig))
- | MBtailcall sig (inr symb) => Error (msg "NYI MBtailcall sig (inr symb)")
- | MBtailcall sig (inl r) => Error (msg "NYI MBtailcall sig (inl r)")
- | MBbuiltin ef args res => Error (msg "NYI MBbuiltin ef args res")
+ | MBtailcall sig (inr symb) => OK(make_epilogue f, PCtlFlow (Pbs symb sig))
+ | MBtailcall sig (inl r) => do r1 <- ireg_of r;
+ OK (make_epilogue f, PCtlFlow (Pbr r1 sig))
+ | MBbuiltin ef args res => OK (nil, Pbuiltin ef (List.map (map_builtin_arg dreg_of) args) (map_builtin_res dreg_of res))
| MBgoto lbl => OK (nil, PCtlFlow (Pb lbl))
| MBcond cond args lbl => transl_cond_branch cond args lbl nil
| MBreturn => OK (make_epilogue f, PCtlFlow (Pret RA))
- | MBjumptable arg tbl => Error (msg "NYI MBjumptable arg tbl")
+ | MBjumptable arg tbl => do r <- ireg_of arg;
+ OK (nil, PCtlFlow (Pbtbl r tbl))
end.
-Definition transl_exit (f: Machblock.function) (ext: option control_flow_inst) (ep: bool) : res (bcode*option control) :=
+Definition transl_exit (f: Machblock.function) (ext: option control_flow_inst) : res (bcode*option control) :=
match ext with
- Some ctl => do (b,c) <- transl_control f ctl ep; OK (b, Some c)
+ Some ctl => do (b,c) <- transl_control f ctl; OK (b, Some c)
| None => OK (nil, None)
end.
Definition transl_block (f: Machblock.function) (fb: Machblock.bblock) (ep: bool) (k:bblocks): res (list bblock) :=
let stub := false in (* TODO: FIXME *)
- do (bdy, ex) <- transl_exit f fb.(Machblock.exit) stub;
+ do (bdy, ex) <- transl_exit f fb.(Machblock.exit);
do bdy' <- transl_basic_code f fb.(Machblock.body) ep bdy;
OK (cons_bblocks fb.(Machblock.header) bdy' ex k)
.
diff --git a/test/aarch64/README.md b/test/aarch64/README.md
new file mode 100644
index 00000000..f943489c
--- /dev/null
+++ b/test/aarch64/README.md
@@ -0,0 +1,15 @@
+# Testing the Machblock --> Asmblock translation
+1. Get the reference version of compcert-aarch in the father's directory if this repo (checkout `aarch64-ref`)
+2. Compile both repo for aarch64
+3. CD in this folder (`test/aarch64`)
+4. Launch `./asmb_aarch64_gen_test.sh`
+
+## Options
+The script takes following options :
+- `-c` to clear generated files at the end
+- `-w` to suppress warnings from Compcert
+
+## Tests files
+The variable `DIRS` in the script takes the list of directories containing c files.
+The tests under `test/aarch64/c` are simpler and useful to debug only one feature at a time.
+Most of them comes from [here](https://cis.temple.edu/~ingargio/cis71/code/).
diff --git a/test/aarch64/asmb_aarch64_gen_test.sh b/test/aarch64/asmb_aarch64_gen_test.sh
index 19149265..f816204e 100755
--- a/test/aarch64/asmb_aarch64_gen_test.sh
+++ b/test/aarch64/asmb_aarch64_gen_test.sh
@@ -1,38 +1,105 @@
#!/bin/bash
CLEAN=0
-while getopts ':c' 'OPTKEY'; do
+WOFF=0
+while getopts ':cw' 'OPTKEY'; do
case ${OPTKEY} in
c) CLEAN=1;;
+ w) WOFF=1;;
esac
done
-FILES=c/*
+DIRS=(
+ c/*.c # Special simple tests
+ ../c/*.c
+ ../clightgen/*.c
+ ../compression/*.c
+ ../cse2/*.c
+
+ # Monniaux test directory
+ ../monniaux/binary_search/*.c
+ ../monniaux/complex/*.c
+ #../monniaux/crypto-algorithms/*.c # Warnings
+ ../monniaux/cse2/*.c
+ #../monniaux/des/*.c # Unsupported feature?
+ ../monniaux/expect/*.c
+ ../monniaux/fill_buffer/*.c
+ ../monniaux/genann/*.c
+ #../monniaux/heptagon_radio_transmitter/*.c # Warnings
+ ../monniaux/idea/*.c
+ ../monniaux/jumptable/*.c
+ ../monniaux/licm/*.c
+ ../monniaux/longjmp/*.c
+ ../monniaux/loop/*.c
+ ../monniaux/lustrev4_lustrec_heater_control/*.c
+ ../monniaux/lustrev4_lv4_heater_control/*.c
+ ../monniaux/lustrev4_lv6-en-2cgc_heater_control/*.c
+ #../monniaux/lustrev6-carlightV2/*.c # Warnings
+ #../monniaux/lustrev6-convertible-2cgc/*.c # Unsupported feature?
+ ../monniaux/lustrev6-convertible-en-2cgc/*.c
+ #../monniaux/lustrev6-convertible/*.c # Warnings
+ ../monniaux/madd/*.c
+ #../monniaux/math/*.c # Unsupported feature?
+ ../monniaux/memcpy/*.c
+ #../monniaux/micro-bunzip/*.c # Warnings
+ ../monniaux/moves/*.c
+ ../monniaux/multithreaded_volatile/*.c
+ ../monniaux/nand/*.c
+ #../monniaux/ncompress/*.c # Warnings
+ ../monniaux/number_theoretic_transform/*.c
+ ../monniaux/predicated/*.c
+ ../monniaux/regalloc/*.c
+ ../monniaux/rotate/*.c
+ ../monniaux/scheduling/*.c
+ ../monniaux/send_through/*.c
+ ../monniaux/tiny-AES-c/*.c
+ ../monniaux/varargs/*.c
+ ../monniaux/xor_and_mat/*.c
+ #../monniaux/zlib-1.2.11/*.c # Warnings
+)
+#FILES=../c/*.c
CCOMP_BBLOCKS="../../ccomp"
CCOMP_REF="../../../CompCert_master/ccomp"
-for f in $FILES
+COUNT=0
+
+if [ $WOFF -eq 1 ]
+then
+ CCOMP_BBLOCKS="${CCOMP_BBLOCKS} -w"
+ CCOMP_REF="${CCOMP_REF} -w"
+fi
+
+for files in ${DIRS[@]}
do
- BNAME=$(basename -s .c $f)
- SNAME="$BNAME".s
- SREFNAME="$BNAME"_ref.s
- ./$CCOMP_BBLOCKS -S $f -o $SNAME
- ./$CCOMP_REF -dmach -S $f -o $SREFNAME
- #diff -I '^//*' <(cut -c-5 $SNAME) <(cut -c-5 $SREFNAME) > /dev/null 2>&1
- diff -I '^//*' $SNAME $SREFNAME > /dev/null 2>&1
-
- error=$?
- if [ $error -eq 0 ]
- then
- echo "[$BNAME] OK"
- elif [ $error -eq 1 ]
- then
- echo "[$BNAME] FAIL"
- diff -I '^//*' -y $SNAME $SREFNAME
- else
- echo "[WARNING] There was something wrong with the diff command !"
- fi
+ for f in $files
+ do
+ BNAME=$(basename -s .c $f)
+ SNAME="$BNAME".s
+ SREFNAME="$BNAME"_ref.s
+ ./$CCOMP_BBLOCKS -S $f -o $SNAME
+ ./$CCOMP_REF -dmach -S $f -o $SREFNAME
+ #diff -I '^//*' <(cut -c-5 $SNAME) <(cut -c-5 $SREFNAME) > /dev/null 2>&1
+ diff -I '^//*' $SNAME $SREFNAME > /dev/null 2>&1
+
+ error=$?
+ if [ $error -eq 0 ]
+ then
+ echo "[$BNAME] OK"
+ COUNT=$((COUNT + 1))
+ elif [ $error -eq 1 ]
+ then
+ echo "[$BNAME] FAIL"
+ diff -I '^//*' -y $SNAME $SREFNAME
+ exit 1
+ else
+ echo "[$BNAME] FAIL"
+ echo "[WARNING] There was something wrong with the diff command !"
+ exit 1
+ fi
+ done
done
+echo "[TOTAL] $COUNT tests PASSED"
+
if [ $CLEAN -eq 1 ]
then
rm *.s *.mach
diff --git a/test/aarch64/c/addresses.c b/test/aarch64/c/addresses.c
new file mode 100644
index 00000000..e3cb5201
--- /dev/null
+++ b/test/aarch64/c/addresses.c
@@ -0,0 +1,32 @@
+/* addresses.c -- Playing with addresses of variables and their contents:
+ * what is done by C with variables, addresses, and values.
+ */
+
+#include <stdio.h>
+
+void moo(int a, int * b);
+
+int main(void) {
+ int x;
+ int *y;
+
+ x=1;
+ y=&x;
+ printf("Address of x = %d, value of x = %d\n", &x, x);
+ printf("Address of y = %d, value of y = %d, value of *y = %d\n", &y, y, *y);
+ moo(9,y);
+}
+
+void moo(int a, int *b){
+ printf("Address of a = %d, value of a = %d\n", &a, a);
+ printf("Address of b = %d, value of b = %d, value of *b = %d\n", &b, b, *b);
+}
+
+/* Output from running this program on my computer:
+
+Address of x = 536869640, value of x = 1
+Address of y = 536869632, value of y = 536869640, value of *y = 1
+Address of a = 536869608, value of a = 9
+Address of b = 536869600, value of b = 536869640, value of *b = 1
+
+ */
diff --git a/test/aarch64/c/array1.c b/test/aarch64/c/array1.c
new file mode 100644
index 00000000..5840ca66
--- /dev/null
+++ b/test/aarch64/c/array1.c
@@ -0,0 +1,64 @@
+/* array1.c -- Simple operations with arrays.
+ */
+
+#include <stdio.h>
+#define N 10
+
+void oneWay(void);
+void anotherWay(void);
+
+int main(void) {
+ printf("\noneWay:\n");
+ oneWay();
+ printf("\nantherWay:\n");
+ anotherWay();
+}
+
+/*Array initialized with aggregate */
+void oneWay(void) {
+ int vect[N] = {1,2,3,4,5,6,7,8,9,0};
+ int i;
+
+ for (i=0; i<N; i++)
+ printf("i = %2d vect[i] = %2d\n", i, vect[i]);
+}
+
+/*Array initialized with loop */
+void anotherWay(void) {
+ int vect[N];
+ int i;
+
+ for (i=0; i<N; i++)
+ vect[i] = i+1;
+
+ for (i=0; i<N; i++)
+ printf("i = %2d vect[i] = %2d\n", i, vect[i]);
+}
+
+/* The output of this program is
+
+oneWay:
+i = 0 vect[i] = 1
+i = 1 vect[i] = 2
+i = 2 vect[i] = 3
+i = 3 vect[i] = 4
+i = 4 vect[i] = 5
+i = 5 vect[i] = 6
+i = 6 vect[i] = 7
+i = 7 vect[i] = 8
+i = 8 vect[i] = 9
+i = 9 vect[i] = 0
+
+antherWay:
+i = 0 vect[i] = 1
+i = 1 vect[i] = 2
+i = 2 vect[i] = 3
+i = 3 vect[i] = 4
+i = 4 vect[i] = 5
+i = 5 vect[i] = 6
+i = 6 vect[i] = 7
+i = 7 vect[i] = 8
+i = 8 vect[i] = 9
+i = 9 vect[i] = 10
+
+ */
diff --git a/test/aarch64/c/array2.c b/test/aarch64/c/array2.c
new file mode 100644
index 00000000..389e1596
--- /dev/null
+++ b/test/aarch64/c/array2.c
@@ -0,0 +1,74 @@
+/* array2.c -- Read/writing/reversing integer arrays
+ */
+
+#include <stdio.h>
+
+#define NMAX 10
+
+void intSwap(int *x, int *y);
+int getIntArray(int a[], int nmax, int sentinel);
+void printIntArray(int a[], int n);
+void reverseIntArray(int a[], int n);
+
+int main(void) {
+ int x[NMAX];
+ int hmny;
+
+ hmny = getIntArray(x, NMAX, 0);
+ printf("The array was: \n");
+ printIntArray(x,hmny);
+ reverseIntArray(x,hmny);
+ printf("after reverse it is:\n");
+ printIntArray(x,hmny);
+}
+
+void intSwap(int *x, int *y)
+ /* It swaps the content of x and y */
+{
+ int temp = *x;
+ *x = *y;
+ *y = temp;
+}
+
+void printIntArray(int a[], int n)
+ /* n is the number of elements in the array a.
+ * These values are printed out, five per line. */
+{
+ int i;
+
+ for (i=0; i<n; ){
+ printf("\t%d ", a[i++]);
+ if (i%5==0)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+int getIntArray(int a[], int nmax, int sentinel)
+ /* It reads up to nmax integers and stores then in a; sentinel
+ * terminates input. */
+{
+ int n = 0;
+ int temp;
+
+ do {
+ printf("Enter integer [%d to terminate] : ", sentinel);
+ scanf("%d", &temp);
+ if (temp==sentinel) break;
+ if (n==nmax)
+ printf("array is full\n");
+ else
+ a[n++] = temp;
+ }while (1);
+ return n;
+}
+
+void reverseIntArray(int a[], int n)
+ /* It reverse the order of the first n elements of a */
+{
+ int i;
+
+ for(i=0;i<n/2;i++){
+ intSwap(&a[i],&a[n-i-1]);
+ }
+}
diff --git a/test/aarch64/c/cpintarray.c b/test/aarch64/c/cpintarray.c
new file mode 100644
index 00000000..8049fdfb
--- /dev/null
+++ b/test/aarch64/c/cpintarray.c
@@ -0,0 +1,108 @@
+/* cpintarray.c -- Example showing how addresses and arrays are alike
+ */
+
+#include <stdio.h>
+#define SIZE 8
+
+void cpIntArray(int *a, int *b, int n)
+/*It copies n integers starting at b into a*/
+{
+ for(;n>0;n--)
+ *a++=*b++;
+}
+
+
+void printIntArray(int a[], int n)
+ /* n is the number of elements in the array a.
+ * These values are printed out, five per line. */
+{
+ int i;
+
+ for (i=0; i<n; ){
+ printf("\t%d ", a[i++]);
+ if (i%5==0)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+int getIntArray(int a[], int nmax, int sentinel)
+ /* It reads up to nmax integers and stores then in a; sentinel
+ * terminates input. */
+{
+ int n = 0;
+ int temp;
+
+ do {
+ printf("Enter integer [%d to terminate] : ", sentinel);
+ scanf("%d", &temp);
+ if (temp==sentinel) break;
+ if (n==nmax)
+ printf("array is full\n");
+ else
+ a[n++] = temp;
+ }while (1);
+ return n;
+}
+
+int main(void){
+ int x[SIZE], nx;
+ int y[SIZE], ny;
+
+ printf("Read the x array:\n");
+ nx = getIntArray(x,SIZE,0);
+ printf("The x array is:\n");
+ printIntArray(x,nx);
+
+ printf("Read the y array:\n");
+ ny = getIntArray(y,SIZE,0);
+ printf("The y array is:\n");
+ printIntArray(y,ny);
+
+ cpIntArray(x+2,y+3,4);
+ /*Notice the expression 'x+2'. x is interpreted as the address for
+ the beginning of the x array. +2 sais to increment that address
+ by two units, in accordance with the type of x, which is
+ an integer array. Thus we move from x to two integer locations
+ past it, that is to the location of x[2]. The same reasoning applied
+ to 'y+3'.
+ */
+ printf("Printing x after having copied 4 elements\n"
+ "from y starting at y[3] into x starting at x[2]\n");
+ printIntArray(x,nx);
+}
+
+/* Here is the interaction in a run of this program:
+
+Read the x array:
+Enter integer [0 to terminate] : 1
+Enter integer [0 to terminate] : 3
+Enter integer [0 to terminate] : 5
+Enter integer [0 to terminate] : 7
+Enter integer [0 to terminate] : 9
+Enter integer [0 to terminate] : 11
+Enter integer [0 to terminate] : 13
+Enter integer [0 to terminate] : 15
+Enter integer [0 to terminate] : 0
+The x array is:
+ 1 3 5 7 9
+ 11 13 15
+Read the y array:
+Enter integer [0 to terminate] : 2
+Enter integer [0 to terminate] : 4
+Enter integer [0 to terminate] : 6
+Enter integer [0 to terminate] : 8
+Enter integer [0 to terminate] : 10
+Enter integer [0 to terminate] : 12
+Enter integer [0 to terminate] : 14
+Enter integer [0 to terminate] : 16
+Enter integer [0 to terminate] : 0
+The y array is:
+ 2 4 6 8 10
+ 12 14 16
+Printing x after having copied 4 elements
+from y starting at y[3] into x starting at x[2]
+ 1 3 8 10 12
+ 14 13 15
+
+ */
diff --git a/test/aarch64/c/enum1.c b/test/aarch64/c/enum1.c
new file mode 100644
index 00000000..d1f6b48d
--- /dev/null
+++ b/test/aarch64/c/enum1.c
@@ -0,0 +1,52 @@
+/* enum1.c -- Starting to use enumerated types: Printing for each
+ * day of the week, today, yesterday, and tomorrow, both
+ * as a string and as a number.
+ */
+
+#include <stdio.h>
+
+/* Introducing an enumerated data type */
+enum days {monday,tuesday,wednesday,thursday,friday,saturday,sunday};
+typedef enum days days; // This allows us to use "days" as an abbreviation
+ // for "enum days"
+
+/* Two useful functions */
+days yesterday(days today){
+ return (today+6)%7;
+}
+days tomorrow(days today){
+ return (today+1)%7;
+}
+
+// A useful array: thedays is an array of constant (i.e you cannot
+// modify them) pointers to constant (i.e. you cannot modify them) strings
+const char * const thedays[] =
+ {"monday", "tuesday", "wednesday", "thursday",
+ "friday", "saturday", "sunday"};
+
+int main(void){
+ days today;
+
+ printf("today \tyesterday \ttomorrow\n"
+ "============================================\n");
+ for (today=monday;today<=sunday;today++)
+ printf("%s = %d \t %s = %d \t %s = %d\n",
+ thedays[today], today,
+ thedays[yesterday(today)], yesterday(today),
+ thedays[tomorrow(today)], tomorrow(today));
+}
+
+/*
+ The output is:
+
+today yesterday tomorrow
+============================================
+monday = 0 sunday = 6 tuesday = 1
+tuesday = 1 monday = 0 wednesday = 2
+wednesday = 2 tuesday = 1 thursday = 3
+thursday = 3 wednesday = 2 friday = 4
+friday = 4 thursday = 3 saturday = 5
+saturday = 5 friday = 4 sunday = 6
+sunday = 6 saturday = 5 monday = 0
+
+*/
diff --git a/test/aarch64/c/enum2.c b/test/aarch64/c/enum2.c
new file mode 100644
index 00000000..a18acb80
--- /dev/null
+++ b/test/aarch64/c/enum2.c
@@ -0,0 +1,50 @@
+/* enum2.c -- Starting to use enumerated types: Printing for each
+ * day of the week, today, yesterday, and tomorrow, both
+ * as a string and as a number. We use typedef
+ */
+
+#include <stdio.h>
+
+/* Introducing an enumerated data type */
+typedef enum {monday,tuesday,wednesday,thursday,friday,saturday,sunday} days;
+
+/* Two useful functions */
+days yesterday(days today);
+days tomorrow(days today);
+
+char *thedays[] = {"monday", "tuesday", "wednesday", "thursday",
+ "friday", "saturday", "sunday"};
+
+int main(void){
+ days today;
+
+ printf("today \tyesterday \ttomorrow\n"
+ "============================================\n");
+ for (today=monday;today<=sunday;today++)
+ printf("%s = %d \t %s = %d \t %s = %d\n",
+ thedays[today], today,
+ thedays[yesterday(today)], yesterday(today),
+ thedays[tomorrow(today)], tomorrow(today));
+}
+
+days yesterday(days today){
+ return (today+6)%7;
+}
+days tomorrow(days today){
+ return (today+1)%7;
+}
+
+/*
+ The output is:
+
+today yesterday tomorrow
+============================================
+monday = 0 sunday = 6 tuesday = 1
+tuesday = 1 monday = 0 wednesday = 2
+wednesday = 2 tuesday = 1 thursday = 3
+thursday = 3 wednesday = 2 friday = 4
+friday = 4 thursday = 3 saturday = 5
+saturday = 5 friday = 4 sunday = 6
+sunday = 6 saturday = 5 monday = 0
+
+*/
diff --git a/test/aarch64/c/funcs.c b/test/aarch64/c/funcs.c
index fba46033..49e610d6 100644
--- a/test/aarch64/c/funcs.c
+++ b/test/aarch64/c/funcs.c
@@ -20,7 +20,7 @@ int main (void) {
int getint(void) {
int a;
- /*printf("Please enter an integer > ");*/
+ printf("Please enter an integer > ");
scanf("%d", &a);
return(a);
}
diff --git a/test/aarch64/c/power2.c b/test/aarch64/c/power2.c
new file mode 100644
index 00000000..64707df9
--- /dev/null
+++ b/test/aarch64/c/power2.c
@@ -0,0 +1,42 @@
+/* power2.c -- Print out powers of 2: 1, 2, 4, 8, .. up to 2^N
+ */
+
+#include <stdio.h>
+#define N 16
+
+int main(void) {
+ int n; /* The current exponent */
+ int val = 1; /* The current power of 2 */
+
+ printf("\t n \t 2^n\n");
+ printf("\t================\n");
+ for (n=0; n<=N; n++) {
+ printf("\t%3d \t %6d\n", n, val);
+ val = 2*val;
+ }
+ return 0;
+}
+
+/* It prints out :
+
+ n 2^n
+ ================
+ 0 1
+ 1 2
+ 2 4
+ 3 8
+ 4 16
+ 5 32
+ 6 64
+ 7 128
+ 8 256
+ 9 512
+ 10 1024
+ 11 2048
+ 12 4096
+ 13 8192
+ 14 16384
+ 15 32768
+ 16 65536
+
+*/
diff --git a/test/aarch64/c/random.c b/test/aarch64/c/random.c
new file mode 100644
index 00000000..50aa5737
--- /dev/null
+++ b/test/aarch64/c/random.c
@@ -0,0 +1,50 @@
+/* Generating random number sequences using the formula (linear congruence)
+ x[k+1] = (a*x[k] + c)mod m
+ where a, c, and m are parameters set by the user and passed as command line
+ parameters together with a seed i.e. x[0]
+ As a simple example try a=7, c=1, m=13, and seed=5
+ A more sophisticated selection would be a=69069, c=0,
+ m=2^32=4294967296, and seed=31
+ It will print out, in a sort of random order, up to m-1 distinct values.
+ Then it loops.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static long seed = 13;
+static long a;
+static long c;
+static long m;
+
+void random_init(long s) {
+ if (s != 0) seed = s;
+}
+
+long random() {
+ seed = (a*seed + c)%m;
+ return seed;
+ }
+
+int main(int argc, char * argv[]) {
+ if (argc != 5) {
+ printf("usage: %s a, c, m, seed\n", argv[0]);
+ return 1;
+ }
+ a = atoi(argv[1]);
+ c = atoi(argv[2]);
+ m = atoi(argv[3]);
+ long s = atoi(argv[4]);
+ random_init(s);
+ int k;
+ for (k = 0; k < m-1; k++) {
+ printf("%8ld", random());
+ if (k % 8 == 7) { // after 8 elements go to a new line
+ printf("\n");
+ sleep(1); // sleep for a second
+ }
+ }
+ printf("\n");
+ return 0;
+}