From f455643dc027e3e729d570eb869c98694b1072e9 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Tue, 2 Jan 2024 11:50:39 +0100 Subject: [PATCH] switch --- flap/src/x86-64/retrolixToX86_64.ml | 35 +++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/flap/src/x86-64/retrolixToX86_64.ml b/flap/src/x86-64/retrolixToX86_64.ml index d321db1..09e6ece 100644 --- a/flap/src/x86-64/retrolixToX86_64.ml +++ b/flap/src/x86-64/retrolixToX86_64.ml @@ -506,8 +506,39 @@ module InstructionSelector : InstructionSelector = struct ;; let switch ?default ~discriminant ~cases () = - (* TODO *) - failwith "Students! This is your job! (switch)" + (* Switch *) + let add_default_case = + match default with + | None -> [] + | Some ll -> + (* Déplace le discrimant dans R15 *) + [ Instruction (movq ~src:discriminant ~dst:r15) + (* Compare le cas avec R15 (= discriminant) + ">=" avec le nombre total des cas *) + ; Instruction (cmpq ~src1:(liti (Array.length cases)) ~src2:r15) + (* Si condition est vrai : jump vers le label ll *) + ; Instruction (jccl ~cc:AE ~tgt:ll) + ] + in + (* Label pour le switch *) + let switch_label = fresh_label () in + (* On vérifie le cas par défaut *) + add_default_case + (* Une case = 8 octets donc on multiplie par 8 + et on stocke la position du discriminant dans R15 *) + @ mul ~srcl:discriminant ~srcr:(liti 8) ~dst:r15 + (* Charge l'adresse du label du switch dans R15, + avec chaque élément séparer de 4 octets (taille pointeur) *) + @ mov + ~src:(`Addr (addr ~offset:(Lab switch_label) ~base:R15 ~scale:`Four ())) + ~dst:r15 + (* Saute vers l'adresse R15 aka là où on doit mettre le label + et on y met le label du switch *) + @ [ Instruction (jmpi ~tgt:r15) + ; Label switch_label + (* Table de saut pour les adresses des autres cas *************) + ; Directive (Quad (List.map (fun x -> Lab x) (Array.to_list cases))) + ] ;; end