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 () =
|
||||
(* 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
|
||||
|
||||
|
|
Reference in a new issue