switch
This commit is contained in:
parent
f960f9c23b
commit
f455643dc0
1 changed files with 33 additions and 2 deletions
|
@ -506,8 +506,39 @@ module InstructionSelector : InstructionSelector = struct
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let switch ?default ~discriminant ~cases () =
|
let switch ?default ~discriminant ~cases () =
|
||||||
(* TODO *)
|
(* Switch *)
|
||||||
failwith "Students! This is your job! (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
|
end
|
||||||
|
|
||||||
|
|
Reference in a new issue