1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(** Copyright 2024,  Mikhail Gavrilenko, Danila Rudnev-Stepanyan, Daniel Vlasenko*)

(** SPDX-License-Identifier: LGPL-3.0-or-later *)

open Base.Format
open Base
open Machine
open Target

module Emission = struct
  let code : (instr * string) Queue.t = Queue.create ()
  let emit ?(comm = "") push_instr = push_instr (fun i -> Queue.enqueue code (i, comm))

  let flush_queue ppf =
    while not (Queue.is_empty code) do
      let i, comm = Queue.dequeue_exn code in
      (match i with
       | Label _ -> fprintf ppf "%a" pp_instr i
       | _ -> fprintf ppf "  %a" pp_instr i);
      if String.(comm <> "") then fprintf ppf " # %s" comm;
      fprintf ppf "\n"
    done
  ;;

  let emit_tagged_binop op dst r1 r2 =
    match op with
    | "+" ->
      (* (2a+1)+(2b+1)-1 = 2(a+b)+1 *)
      emit add dst r1 r2;
      emit addi dst dst (-1)
    | "-" ->
      (* (2a+1)-(2b+1)+1 = 2(a-b)+1 *)
      emit sub dst r1 r2;
      emit addi dst dst 1
    | "*" ->
      (* a = x >> 1, b = y >> 1 *)
      emit srai (T 2) r1 1;
      emit srai (T 3) r2 1;
      emit mul dst (T 2) (T 3);
      (* a*b *)
      (* (a*b) << 1 | 1  — тегаем обратно *)
      emit add dst dst dst;
      emit addi dst dst 1
    | "=" ->
      emit xor (T 2) r1 r2;
      emit seqz dst (T 2)
    | "<>" ->
      emit xor (T 2) r1 r2;
      emit snez dst (T 2)
    | "<" -> emit slt dst r1 r2
    | ">" -> emit slt dst r2 r1
    | "<=" ->
      emit slt (T 2) r2 r1;
      emit seqz dst (T 2)
    | ">=" ->
      emit slt (T 2) r1 r2;
      emit seqz dst (T 2)
    | _ -> invalid_arg ("Unknown binary operator: " ^ op)
  ;;

  (*миша я переписал через емит чтобы у нас вся оработка шла черз один модуль*)
  (*re: horosho ;)*)
  let emit_prologue name stack_size =
    (* name: *)
    emit label name;
    (* addi sp, sp, -stack_size *)
    emit addi SP SP (-stack_size);
    (* sd ra, (sp + stack_size - word) *)
    emit sd RA (SP, stack_size - Target.word_size);
    (* sd fp(S0), (sp + stack_size - 2*word) *)
    emit sd (S 0) (SP, stack_size - (2 * Target.word_size));
    (* fp := sp + stack_size - 2*word *)
    emit addi (S 0) SP (stack_size - (2 * Target.word_size))
  ;;

  let emit_epilogue stack_size =
    let (_ : 'a) = stack_size in
    (* should be used in future *)
    emit addi SP (S 0) (2 * Target.word_size);
    (* sp = fp + 2*word *)
    emit ld RA (S 0, Target.word_size);
    (* ra = [fp+word] *)
    emit ld (S 0) (S 0, 0);
    (* fp = [fp+0] *)
    emit ret
  ;;
end