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

Last change on this file since 741 was 741, checked in by ayache, 10 years ago

Bug fix in LINToASM in D2.2's 8051 (negative integers).

File size: 3.8 KB
Line 
1
2(** This module translates a [LIN] program into a [ASM] program. *)
3
4
5(* Fetch the labels found in a LIN program. *)
6
7let statement_labels = function
8  | LIN.St_goto lbl
9  | LIN.St_label lbl
10  | LIN.St_cost lbl
11  | LIN.St_condacc lbl -> Label.Set.singleton lbl
12  | _ -> Label.Set.empty
13
14let funct_labels (_, fun_def) = match fun_def with
15  | LIN.F_int stmts ->
16    let f labels stmt = Label.Set.union labels (statement_labels stmt) in
17    List.fold_left f Label.Set.empty stmts
18  | _ -> Label.Set.empty
19
20let prog_labels p =
21  let f labels funct = Label.Set.union labels (funct_labels funct) in
22  List.fold_left f Label.Set.empty p.LIN.functs
23
24
25let size_of_vect_size = function
26  | `Four -> 4
27  | `Seven -> 7
28  | `Eight -> 8
29  | `Eleven -> 11
30  | `Sixteen -> 16
31
32let vect_of_int i size =
33  let i' =
34    if i < 0 then (MiscPottier.pow 2 (size_of_vect_size size)) + i else i in
35  BitVectors.vect_of_int i' size
36
37let byte_of_int i = vect_of_int i `Eight
38let data_of_int i = `DATA (byte_of_int i)
39let data16_of_int i = `DATA16 (vect_of_int i `Sixteen)
40let acc_addr = I8051.reg_addr I8051.a
41
42
43let translate_statement glbls_addr = function
44  | LIN.St_goto lbl -> [`Jmp lbl]
45  | LIN.St_label lbl -> [`Label lbl]
46  | LIN.St_comment _ -> []
47  | LIN.St_cost lbl -> [`Cost lbl ; `NOP (* TODO: hack! Need to make the difference between cost labels and regular labels. *)]
48  | LIN.St_int (r, i) ->
49    [`MOV (`U3 (I8051.reg_addr r, data_of_int i))]
50  | LIN.St_pop ->
51    [`POP acc_addr]
52  | LIN.St_push ->
53    [`PUSH acc_addr]
54  | LIN.St_addr x ->
55    [`MOV (`U4 (`DPTR, data16_of_int (List.assoc x glbls_addr)))]
56  | LIN.St_from_acc r ->
57    [`MOV (`U3 (I8051.reg_addr r, `A))]
58  | LIN.St_to_acc r ->
59    [`MOV (`U1 (`A, I8051.reg_addr r))]
60  | LIN.St_opaccs I8051.Mul ->
61    [`MUL (`A, `B)]
62  | LIN.St_opaccs I8051.Divu ->
63    [`DIV (`A, `B)]
64  | LIN.St_opaccs I8051.Modu ->
65    assert false (* Should have been translated before. *)
66  | LIN.St_op1 I8051.Cmpl ->
67    [`CPL `A]
68  | LIN.St_op1 I8051.Inc ->
69    [`INC `A]
70  | LIN.St_op2 (I8051.Add, r) ->
71    [`ADD (`A, I8051.reg_addr r)]
72  | LIN.St_op2 (I8051.Addc, r) ->
73    [`ADDC (`A, I8051.reg_addr r)]
74  | LIN.St_op2 (I8051.Sub, r) ->
75    [`SUBB (`A, I8051.reg_addr r)]
76  | LIN.St_op2 (I8051.And, r) ->
77    [`ANL (`U1 (`A, I8051.reg_addr r))]
78  | LIN.St_op2 (I8051.Or, r) ->
79    [`ORL (`U1 (`A, I8051.reg_addr r))]
80  | LIN.St_op2 (I8051.Xor, r) ->
81    [`XRL (`U1 (`A, I8051.reg_addr r))]
82  | LIN.St_clear_carry ->
83    [`CLR `C]
84  | LIN.St_load ->
85    [`MOVX (`U1 (`A, `EXT_IND_DPTR))]
86  | LIN.St_store ->
87    [`MOVX (`U2 (`EXT_IND_DPTR, `A))]
88  | LIN.St_call_id f ->
89    [`Call f]
90  | LIN.St_condacc lbl ->
91    [`WithLabel (`JNZ (`Label lbl))]
92  | LIN.St_return ->
93    [`RET]
94
95let translate_code glbls_addr code =
96  List.flatten (List.map (translate_statement glbls_addr) code)
97
98
99let translate_fun_def glbls_addr (id, def) = match def with
100  | LIN.F_int code -> (`Label id) :: (translate_code glbls_addr code)
101  | _ -> []
102
103let translate_functs glbls_addr exit_label main functs =
104  let preamble = match main with
105    | None -> []
106    | Some main -> [`Call main ; `Label exit_label ; `Jmp exit_label] in
107  preamble @
108    (List.flatten (List.map (translate_fun_def glbls_addr) functs))
109
110
111let globals_addr l =
112  let f (res, offset) (x, size) = ((x, offset) :: res, offset + size) in
113  fst (List.fold_left f ([], 0) l)
114
115
116(* Translating programs.
117
118   Global variables are associated an offset from the base of the external
119   memory. *)
120
121let translate p =
122  let prog_lbls = prog_labels p in
123  let exit_label = Label.Gen.fresh_prefix prog_lbls "_exit" in
124  let glbls_addr = globals_addr p.LIN.vars in
125  let p =
126    { ASM.ppreamble = p.LIN.vars ;
127      ASM.pexit_label = exit_label ;
128      ASM.pcode =
129        translate_functs glbls_addr exit_label p.LIN.main p.LIN.functs ;
130      ASM.phas_main = p.LIN.main <> None } in
131  ASMInterpret.assembly p
Note: See TracBrowser for help on using the repository browser.