source: Deliverables/D2.2/8051/src/LIN/LINToASM.ml @ 1542

Last change on this file since 1542 was 1542, checked in by tranquil, 8 years ago

merge of indexed labels branch

File size: 5.6 KB
Line 
1
2(** This module translates a [LIN] program into a [ASM] program. *)
3
4
5let error_prefix = "LIN to ASM"
6let error s = Error.global_error error_prefix s
7
8
9(* Translation environment *)
10
11type env =
12    { externals : AST.ident list ;
13      exit_lbl : Label.t ;
14      fresh : unit -> string }
15
16let make_env externals exit_lbl fresh =
17  { externals = externals ;
18    exit_lbl = exit_lbl ;
19    fresh = fresh }
20
21
22(* Fetch the labels found in a LIN program. *)
23
24let statement_labels = function
25  | LIN.St_goto lbl
26  | LIN.St_label lbl
27  | LIN.St_condacc lbl -> Label.Set.singleton lbl
28    (* taking the atom as a fresh prefix will be generated *)
29  | LIN.St_cost lbl -> Label.Set.singleton (lbl.CostLabel.name)
30  | _ -> Label.Set.empty
31
32let funct_labels (_, fun_def) = match fun_def with
33  | LIN.F_int stmts ->
34    let f labels stmt = Label.Set.union labels (statement_labels stmt) in
35    List.fold_left f Label.Set.empty stmts
36  | _ -> Label.Set.empty
37
38let prog_labels p =
39  let f labels funct = Label.Set.union labels (funct_labels funct) in
40  List.fold_left f Label.Set.empty p.LIN.functs
41
42
43let size_of_vect_size = function
44  | `Four -> 4
45  | `Seven -> 7
46  | `Eight -> 8
47  | `Eleven -> 11
48  | `Sixteen -> 16
49
50let vect_of_int i size =
51  let i' =
52    if i < 0 then (MiscPottier.pow 2 (size_of_vect_size size)) + i else i in
53  BitVectors.vect_of_int i' size
54
55let byte_of_int i = vect_of_int i `Eight
56let data_of_int i = `DATA (byte_of_int i)
57let data16_of_int i = `DATA16 (vect_of_int i `Sixteen)
58let acc_addr = I8051.reg_addr I8051.a
59let dpl_addr = I8051.reg_addr I8051.dpl
60let dph_addr = I8051.reg_addr I8051.dph
61let st0_addr = I8051.reg_addr I8051.st0
62let st1_addr = I8051.reg_addr I8051.st1
63
64
65let translate_statement env = function
66  | LIN.St_goto lbl -> [`Jmp lbl]
67  | LIN.St_label lbl -> [`Label lbl]
68  | LIN.St_comment _ -> []
69  | LIN.St_cost lbl ->
70    (* TODO: hack! Need to make the difference between cost labels and regular
71       labels. *)
72    [`Cost lbl ; `NOP ]
73  | LIN.St_ind_0 i -> [`Index i ; `NOP (* TODO: hack! *)]
74  | LIN.St_ind_inc i -> [`Inc i ; `NOP (* TODO: hack! *)]
75  | LIN.St_int (r, i) ->
76    [`MOV (`U3 (I8051.reg_addr r, data_of_int i))]
77  | LIN.St_pop ->
78    [`POP acc_addr]
79  | LIN.St_push ->
80    [`PUSH acc_addr]
81  | LIN.St_addr x when List.mem x env.externals ->
82    error ("Primitive or external " ^ x ^ " is not supported.")
83  | LIN.St_addr x ->
84    [`Mov (`DPTR, x)]
85  | LIN.St_from_acc r ->
86    [`MOV (`U3 (I8051.reg_addr r, `A))]
87  | LIN.St_to_acc r ->
88    [`MOV (`U1 (`A, I8051.reg_addr r))]
89  | LIN.St_opaccs I8051.Mul ->
90    [`MUL (`A, `B)]
91  | LIN.St_opaccs I8051.DivuModu ->
92    [`DIV (`A, `B)]
93  | LIN.St_op1 I8051.Cmpl ->
94    [`CPL `A]
95  | LIN.St_op1 I8051.Inc ->
96    [`INC `A]
97  | LIN.St_op2 (I8051.Add, r) ->
98    [`ADD (`A, I8051.reg_addr r)]
99  | LIN.St_op2 (I8051.Addc, r) ->
100    [`ADDC (`A, I8051.reg_addr r)]
101  | LIN.St_op2 (I8051.Sub, r) ->
102    [`SUBB (`A, I8051.reg_addr r)]
103  | LIN.St_op2 (I8051.And, r) ->
104    [`ANL (`U1 (`A, I8051.reg_addr r))]
105  | LIN.St_op2 (I8051.Or, r) ->
106    [`ORL (`U1 (`A, I8051.reg_addr r))]
107  | LIN.St_op2 (I8051.Xor, r) ->
108    [`XRL (`U1 (`A, I8051.reg_addr r))]
109  | LIN.St_clear_carry ->
110    [`CLR `C]
111  | LIN.St_set_carry ->
112    [`SETB `C]
113  | LIN.St_load ->
114    [`MOVX (`U1 (`A, `EXT_IND_DPTR))]
115  | LIN.St_store ->
116    [`MOVX (`U2 (`EXT_IND_DPTR, `A))]
117  | LIN.St_call_id x when List.mem x env.externals ->
118    error ("Primitive or external " ^ x ^ " is not supported.")
119  | LIN.St_call_id f ->
120    [`Call f]
121  | LIN.St_call_ptr ->
122    let lbl = env.fresh () in
123    [`MOV (`U3 (st0_addr, dpl_addr)) ; (* save DPL *)
124     `MOV (`U3 (st1_addr, dph_addr)) ; (* save DPH *)
125     `Mov (`DPTR, lbl) ;               (* DPTR <- return address *)
126     `PUSH dpl_addr ;                  (* push DPL *)
127     `PUSH dph_addr ;                  (* push DPH *)
128     `MOV (`U3 (dpl_addr, st0_addr)) ; (* restore DPL *)
129     `MOV (`U3 (dph_addr, st1_addr)) ; (* restore DPH *)
130     `MOV (`U1 (`A, data_of_int 0)) ;  (* A <- 0 *)
131     `JMP `IND_DPTR ;                  (* jump to A+DPTR *)
132     `Label lbl]                       (* return address *)
133  | LIN.St_condacc lbl ->
134    [`WithLabel (`JNZ (`Label lbl))]
135  | LIN.St_return ->
136    [`RET]
137
138let translate_code env code =
139  List.flatten (List.map (translate_statement env) code)
140
141
142let translate_fun_def env (id, def) =
143  let code = match def with
144  | LIN.F_int code -> translate_code env code
145  | LIN.F_ext ext -> [`NOP] in
146  ((`Label id) :: code)
147
148let translate_functs env main functs =
149  let preamble = match main with
150    | None -> []
151    | Some main ->
152      [`MOV (`U3 (`DIRECT (byte_of_int I8051.isp_addr),
153                  data_of_int I8051.isp_init)) ;
154       `MOV (`U3 (`DIRECT (byte_of_int I8051.spl_addr),
155                  data_of_int I8051.spl_init)) ;
156       `MOV (`U3 (`DIRECT (byte_of_int I8051.sph_addr),
157                  data_of_int I8051.sph_init)) ;
158       `Call main ;
159       `Label env.exit_lbl ; `Jmp env.exit_lbl] in
160  preamble @ (List.flatten (List.map (translate_fun_def env) functs))
161
162
163let init_env p =
164  let f_externals (id, def) = match def with LIN.F_ext _ -> [id] | _ -> [] in
165  let externals =
166    List.fold_left (fun res def -> res @ (f_externals def)) [] p.LIN.functs in
167  let prog_lbls = prog_labels p in
168  let exit_lbl = Label.Gen.fresh_prefix prog_lbls "_exit" in
169  let fresh = Label.make_fresh prog_lbls "_call_ret" in
170  make_env externals exit_lbl fresh
171
172
173(* Translating programs.
174
175   Global variables are associated an offset from the base of the external
176   memory. *)
177
178let translate p =
179  let env = init_env p in
180  let p =
181    { ASM.ppreamble = p.LIN.vars ;
182      ASM.pexit_label = env.exit_lbl ;
183      ASM.pcode = translate_functs env p.LIN.main p.LIN.functs ;
184      ASM.phas_main = p.LIN.main <> None } in
185  ASMInterpret.assembly p
Note: See TracBrowser for help on using the repository browser.