Changeset 619 for Deliverables/D2.2/8051/src/ASM
- Timestamp:
- Mar 2, 2011, 3:27:41 PM (10 years ago)
- Location:
- Deliverables/D2.2/8051/src/ASM
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
Deliverables/D2.2/8051/src/ASM/ASM.mli
r486 r619 113 113 type preamble = (string * int) list 114 114 115 (* has_main currently unused *) 116 type 'a pretty_program = 117 { ppreamble : preamble ; 118 pexit_label : string ; 119 pcode : 'a list ; 120 phas_main : bool } 121 115 122 type program = 116 { preamble : preamble;117 exit_label : Label.t ;118 code : labelled_instruction list;119 has_main : bool }123 { code : BitVectors.byte list ; 124 cost_labels : string BitVectors.WordMap.t ; 125 exit_addr : BitVectors.word ; 126 has_main : bool } -
Deliverables/D2.2/8051/src/ASM/ASMCosts.ml
r486 r619 1 1 2 2 let error_prefix = "ASMCosts" 3 let error s = Error.global_error error_prefix s 4 let warning s = Error.warning error_prefix s 3 let warning s = prerr_endline (error_prefix ^ s) 5 4 6 5 7 6 type instruction_nature = 8 | Cost of CostLabel.t 9 | Goto of Label.t | Branch of Label.t 10 | Direct_fun_call of Label.t | Return 7 | Goto of BitVectors.word | Branch of BitVectors.word 8 | Direct_fun_call of BitVectors.word | Return 11 9 | Other 12 10 13 let inst_nature = function 14 | `Cost lbl -> Cost lbl 15 | `Call lbl -> Direct_fun_call lbl 16 | `Jmp lbl -> Goto lbl 17 | `WithLabel (`JC (`Label lbl)) 18 | `WithLabel (`JNC (`Label lbl)) 19 | `WithLabel (`JB (_, `Label lbl)) 20 | `WithLabel (`JNB (_, `Label lbl)) 21 | `WithLabel (`JBC (_, `Label lbl)) 22 | `WithLabel (`JZ (`Label lbl)) 23 | `WithLabel (`JNZ (`Label lbl)) 24 | `WithLabel (`CJNE (_, `Label lbl)) 25 | `WithLabel (`DJNZ (_, `Label lbl)) -> Branch lbl 11 let inst_nature pc = function 12 | `LCALL (`ADDR16 addr16) -> Direct_fun_call addr16 13 | `ACALL (`ADDR11 addr11) -> 14 Direct_fun_call (Physical.addr16_of_addr11 pc addr11) 15 | `LJMP (`ADDR16 addr16) -> Goto addr16 16 | `AJMP (`ADDR11 addr11) -> Goto (Physical.addr16_of_addr11 pc addr11) 17 | `SJMP (`REL addr) -> 18 let _, addr = BitVectors.half_add pc (BitVectors.sign_extension addr) in 19 Goto addr 20 | `JMP idptr -> Other (* Indirect jump; precondition: every possible 21 destination should start with its own label *) 22 | `JC addr 23 | `JNC addr 24 | `JB (_,addr) 25 | `JNB (_,addr) 26 | `JBC (_,addr) 27 | `JZ addr 28 | `JNZ addr 29 | `CJNE (_,addr) 30 | `DJNZ (_,addr) -> 31 let `REL addr = addr in 32 let _, addr = BitVectors.half_add pc (BitVectors.sign_extension addr) in 33 Branch addr 26 34 | `RET -> Return 27 35 | _ -> Other 28 36 29 37 30 let pc_of_label p = 31 let f pc map = function 32 | `Label lab -> StringTools.Map.add lab pc map 33 | _ -> map 34 in 35 MiscPottier.foldi f StringTools.Map.empty p.ASM.code 36 37 38 let inst_cost = function 39 | `Cost _ | `Label _ -> 0 40 | _ -> 1 41 42 43 let block_cost pc_of_label p = 44 let rec aux pc = 45 if pc >= List.length p.ASM.code then 0 38 (* TODO: do not consider the very first instruction as ending the block since it 39 contains the cost label whose cost we are trying to compute! *) 40 let block_cost mem costs = 41 let rec aux oldpc = 42 if BitVectors.WordMap.mem oldpc costs then 0 46 43 else 47 let inst = List.nth p.ASM.code pc in 48 let cost = match inst_nature inst with 49 | Cost _ | Return -> 0 50 | Goto lbl -> 51 let pc = StringTools.Map.find lbl pc_of_label in 52 aux pc 53 | Branch lbl -> 54 let pc1 = pc + 1 in 55 let pc2 = StringTools.Map.find lbl pc_of_label in 56 let cost1 = aux pc1 in 57 let cost2 = aux pc2 in 58 let cost = max cost1 cost2 in 59 if cost1 <> cost2 then 60 warning 61 (Printf.sprintf 44 let inst,pc,inst_cost = ASMInterpret.fetch mem oldpc in 45 let cost = match inst_nature oldpc inst with 46 | Return -> 0 47 | Goto pc -> aux pc 48 | Branch pc2 -> 49 let pc1 = 50 snd (BitVectors.half_add pc (BitVectors.vect_of_int 1 `Sixteen)) in 51 let cost1 = aux pc1 in 52 let cost2 = aux pc2 in 53 if cost1 <> cost2 then 54 warning 55 (Printf.sprintf 62 56 "Warning: branching to %s has cost %d; continuing has cost %d.\n" 63 lblcost2 cost1) ;64 cost65 | _ -> aux (pc+1) 57 "*fixme*"(*pc2*) cost2 cost1) ; 58 max cost1 cost2 59 | _ -> aux pc 66 60 in 67 cost + inst_cost inst61 cost + inst_cost 68 62 in 69 63 aux 70 64 71 65 72 let rec init_function p pc = 73 let inst = List.nth p.ASM.code pc in 74 match inst_nature inst with 75 | Cost lbl -> (lbl, 0, pc+1) 76 | _ -> 77 let (lbl, cost, pc) = init_function p (pc+1) in 78 (lbl, cost + (inst_cost inst), pc) 66 let traverse_code mem p = 67 let rec aux pc code = 68 let _,newpc,_ = ASMInterpret.fetch mem pc in 69 match code with 70 | [] -> CostLabel.Map.empty 71 | _::tl when BitVectors.WordMap.mem pc p.ASM.cost_labels -> 72 let lbl = BitVectors.WordMap.find pc p.ASM.cost_labels in 73 let cost = block_cost mem p.ASM.cost_labels pc in 74 let costs_mapping = aux newpc tl in 75 CostLabel.Map.add lbl cost costs_mapping 76 | _::tl -> aux newpc tl 77 in 78 aux (BitVectors.zero `Sixteen) p.ASM.code 79 79 80 80 81 let traverse_code pc_of_label p = 82 let rec aux pc = 83 if pc >= List.length p.ASM.code then CostLabel.Map.empty 84 else 85 match inst_nature (List.nth p.ASM.code pc) with 86 | Cost lbl -> 87 let cost = block_cost pc_of_label p (pc+1) in 88 let costs_mapping = aux (pc+1) in 89 CostLabel.Map.add lbl cost costs_mapping 90 | _ -> aux (pc+1) 81 let first_cost_label mem costs = 82 let rec aux oldpc = 83 try (BitVectors.WordMap.find oldpc costs, 0) 84 with 85 | Not_found -> 86 let inst,pc,inst_cost = ASMInterpret.fetch mem oldpc in 87 match inst_nature oldpc inst with 88 | Direct_fun_call pc -> 89 let (lbl, cost) = aux pc in 90 (lbl, inst_cost + cost) 91 | Return 92 | Goto _ 93 | Branch _ -> 94 assert false (* no such instructions before calling main *) 95 | Other -> 96 let (lbl, cost) = aux pc in 97 (lbl, inst_cost + cost) 91 98 in 92 aux 099 aux (BitVectors.zero `Sixteen) 93 100 94 101 95 let first_cost_label pc_of_label p = 96 let rec aux pc = 97 if pc >= List.length p.ASM.code then assert false (* should not happen *) 98 else 99 match inst_nature (List.nth p.ASM.code pc) with 100 | Cost lbl -> lbl 101 | Direct_fun_call lbl -> aux (StringTools.Map.find lbl pc_of_label) 102 | _ -> aux (pc+1) 103 in 104 aux 0 105 106 let initialize_cost pc_of_label p costs_mapping = 107 let lbl = first_cost_label pc_of_label p in 102 let initialize_cost mem costs costs_mapping = 103 let (lbl, cost) = first_cost_label mem costs in 108 104 let old_cost = 109 if CostLabel.Map.mem lbl costs_mapping then 110 CostLabel.Map.find lbl costs_mapping 111 else 0 in 112 let init = 1 (* cost of the preamble *) in 113 let new_cost = old_cost + init in 105 assert (CostLabel.Map.mem lbl costs_mapping) ; 106 CostLabel.Map.find lbl costs_mapping in 107 let new_cost = old_cost + cost in 114 108 CostLabel.Map.add lbl new_cost costs_mapping 115 109 116 110 117 111 let compute p = 118 let pc_of_label = pc_of_label pin119 let costs_mapping = traverse_code pc_of_labelp in120 if p.ASM.has_main then initialize_cost pc_of_label pcosts_mapping112 let mem = ASMInterpret.load_code_memory p.ASM.code in 113 let costs_mapping = traverse_code mem p in 114 if p.ASM.has_main then initialize_cost mem p.ASM.cost_labels costs_mapping 121 115 else costs_mapping -
Deliverables/D2.2/8051/src/ASM/ASMInterpret.ml
r486 r619 2 2 open Physical;; 3 3 open ASM;; 4 open ASMPrinter;;5 4 open IntelHex;; 6 5 open Util;; … … 56 55 (* let _ = prerr_endline <*> string_of_line $ line in *) 57 56 (time + 1),debug_continuation) 58 59 module IntMap = Map.Make(struct type t = int let compare = compare end);; 60 type costs = CostLabel.t IntMap.t 61 57 62 58 (* no differentiation between internal and external code memory *) 63 59 type status = 64 60 { 65 61 (* Memory *) 66 code_memory: WordMap.map; (* can be reduced *)62 code_memory: Physical.WordMap.map; (* can be reduced *) 67 63 low_internal_ram: Byte7Map.map; 68 64 high_internal_ram: Byte7Map.map; 69 external_ram: WordMap.map;65 external_ram: Physical.WordMap.map; 70 66 71 67 (* Program counter *) … … 134 130 es_running: bool; 135 131 136 exit_ pc: word option;137 cost s: costs;132 exit_addr : BitVectors.word; 133 cost_labels : string BitVectors.WordMap.t 138 134 } 139 135 … … 225 221 226 222 let initialize = { 227 code_memory = WordMap.empty;223 code_memory = Physical.WordMap.empty; 228 224 low_internal_ram = Byte7Map.empty; 229 225 high_internal_ram = Byte7Map.empty; 230 external_ram = WordMap.empty;226 external_ram = Physical.WordMap.empty; 231 227 232 228 pc = zero `Sixteen; … … 287 283 es_running = false; 288 284 289 costs = IntMap.empty;290 exit_pc = None;285 exit_addr = BitVectors.zero `Sixteen; 286 cost_labels = BitVectors.WordMap.empty 291 287 } 292 288 … … 387 383 let next pc = 388 384 let _carry, res = half_add pc (vect_of_int 1 `Sixteen) in 389 res, WordMap.find pc pmem385 res, Physical.WordMap.find pc pmem 390 386 in 391 387 let pc,instr = next pc in … … 693 689 let pc,b2 = next pc in 694 690 `XRL(`U2(`DIRECT b1, `DATA b2)), pc, 2 695 | _,_ -> assert false 691 | (true,false,true,false),(false,true,false,true) -> 692 (* undefined opcode *) assert false 696 693 ;; 697 694 … … 927 924 ;; 928 925 929 let fold_lefti f = 930 let rec aux i acc = 931 function 932 [] -> acc 933 | he::tl -> aux (i+1) (f i acc he) tl 934 in 935 aux 0 936 ;; 937 938 let load_code_memory = fold_lefti (fun i mem v -> WordMap.add (vect_of_int i `Sixteen) v mem) WordMap.empty 939 940 let load_mem mem exit_pc costs status = 941 { status with code_memory = mem ; 942 exit_pc = exit_pc ; 943 costs = costs } 944 let load l exit_pc costs = load_mem (load_code_memory l) exit_pc costs 945 946 module StringMap = Map.Make(String);; 947 926 let load_code_memory = MiscPottier.foldi (fun i mem v -> Physical.WordMap.add (vect_of_int i `Sixteen) v mem) Physical.WordMap.empty 927 928 let load_mem mem status = { status with code_memory = mem } 929 let load l = load_mem (load_code_memory l) 948 930 949 931 let assembly_jump addr_of = … … 965 947 (fun (datalabels,addr) (name,size) -> 966 948 let addr16 = vect_of_int addr `Sixteen in 967 String Map.add name addr16 datalabels, addr+size968 ) (String Map.empty,0) p.ASM.preamble949 StringTools.Map.add name addr16 datalabels, addr+size 950 ) (StringTools.Map.empty,0) p.ASM.ppreamble 969 951 in 970 let pc, labels,costs =952 let pc,exit_addr,labels,costs = 971 953 List.fold_left 972 (fun (pc, labels,costs) i ->954 (fun (pc,exit_addr,labels,costs) i -> 973 955 match i with 974 `Label s -> pc, StringMap.add s pc labels, costs 975 | `Cost s -> pc, labels, IntMap.add pc s costs 976 | `Mov (_,_) -> pc, labels, costs 956 `Label s when s = p.ASM.pexit_label -> 957 pc, pc, StringTools.Map.add s pc labels, costs 958 | `Label s -> 959 pc, exit_addr, StringTools.Map.add s pc labels, costs 960 | `Cost s -> pc, exit_addr, labels, BitVectors.WordMap.add pc s costs 961 | `Mov (_,_) -> pc, exit_addr, labels, costs 977 962 | `Jmp _ 978 | `Call _ -> pc + 3, labels, costs (*CSC: very stupid: always expand to worst opcode *) 963 | `Call _ -> 964 (snd (half_add pc (BitVectors.vect_of_int 3 `Sixteen))), 965 exit_addr, labels, costs 966 (*CSC: very stupid: always expand to worst opcode *) 979 967 | `WithLabel i -> 980 981 982 983 984 (pc + int_of_vect pc',labels, costs)968 let fake_addr _ = `REL (zero `Eight) in 969 let fake_jump = assembly_jump fake_addr i in 970 let i',pc',_ = fetch (load_code_memory (assembly1 fake_jump)) (vect_of_int 0 `Sixteen) in 971 assert (fake_jump = i'); 972 (snd (half_add pc pc'), exit_addr, labels, costs) 985 973 | #instruction as i -> 986 974 let i',pc',_ = fetch (load_code_memory (assembly1 i)) (vect_of_int 0 `Sixteen) in 987 975 assert (i = i'); 988 (pc + int_of_vect pc',labels, costs) 989 ) (0,StringMap.empty,IntMap.empty) p.ASM.code 976 (snd (half_add pc pc'),exit_addr,labels, costs) 977 ) 978 (BitVectors.zero `Sixteen,BitVectors.zero `Sixteen, 979 StringTools.Map.empty, BitVectors.WordMap.empty) p.ASM.pcode 990 980 in 991 if pc >= 65536 then 992 raise CodeTooLarge 993 else 994 List.flatten (List.map 995 (function 996 `Label _ 997 | `Cost _ -> [] 998 | `WithLabel i -> 999 let addr_of (`Label s) = 1000 let addr = StringMap.find s labels in 1001 (* NOT IMPLEMENTED YET; NEEDS SMART ALGORITHM *) 1002 assert (addr < 256); 1003 `REL (vect_of_int addr `Eight) 1004 in 1005 assembly1 (assembly_jump addr_of i) 1006 | `Mov (`DPTR,s) -> 1007 let addrr16 = StringMap.find s datalabels in 1008 assembly1 (`MOV (`U4 (`DPTR,`DATA16 addrr16))) 1009 | `Jmp s -> 1010 let pc_offset = StringMap.find s labels in 1011 assembly1 (`LJMP (`ADDR16 (vect_of_int pc_offset `Sixteen))) 1012 | `Call s -> 1013 let pc_offset = StringMap.find s labels in 1014 assembly1 (`LCALL (`ADDR16 (vect_of_int pc_offset `Sixteen))) 1015 | #instruction as i -> assembly1 i) p.ASM.code), 1016 vect_of_int (StringMap.find p.ASM.exit_label labels) `Sixteen, 1017 costs 981 let code = 982 List.flatten (List.map 983 (function 984 `Label _ 985 | `Cost _ -> [] 986 | `WithLabel i -> 987 let addr_of (`Label s) = 988 let addr = StringTools.Map.find s labels in 989 (* NOT IMPLEMENTED YET; NEEDS SMART ALGORITHM *) 990 `REL (assert false) (*addr*) 991 in 992 assembly1 (assembly_jump addr_of i) 993 | `Mov (`DPTR,s) -> 994 let addrr16 = StringTools.Map.find s datalabels in 995 assembly1 (`MOV (`U4 (`DPTR,`DATA16 addrr16))) 996 | `Jmp s -> 997 let pc_offset = StringTools.Map.find s labels in 998 assembly1 (`LJMP (`ADDR16 pc_offset)) 999 | `Call s -> 1000 let pc_offset = StringTools.Map.find s labels in 1001 assembly1 (`LCALL (`ADDR16 pc_offset )) 1002 | #instruction as i -> assembly1 i) p.ASM.pcode) in 1003 { ASM.code = code ; ASM.cost_labels = costs ; 1004 ASM.exit_addr = exit_addr ; ASM.has_main = p.ASM.phas_main } 1018 1005 ;; 1019 1006 … … 1048 1035 assert false for now. Try to understand what DEC really does *) 1049 1036 let cry,addr = half_add dpr (mk_word (vect_of_int 0 `Eight) status.acc) in 1050 WordMap.find addr status.external_ram1037 Physical.WordMap.find addr status.external_ram 1051 1038 | `A_PC -> 1052 1039 (* CSC: what is the right behaviour in case of overflow? 1053 1040 assert false for now *) 1054 1041 let cry,addr = half_add status.pc (mk_word (vect_of_int 0 `Eight) status.acc) in 1055 WordMap.find addr status.external_ram1042 Physical.WordMap.find addr status.external_ram 1056 1043 | `EXT_INDIRECT b -> 1057 1044 let addr = get_register status (false,false,b) in 1058 WordMap.find (mk_word (zero `Eight) addr) status.external_ram1045 Physical.WordMap.find (mk_word (zero `Eight) addr) status.external_ram 1059 1046 | `EXT_IND_DPTR -> 1060 1047 let dpr = mk_word status.dph status.dpl in 1061 WordMap.find dpr status.external_ram1048 Physical.WordMap.find dpr status.external_ram 1062 1049 ;; 1063 1050 … … 1131 1118 let dpr = mk_word status.dph status.dpl in 1132 1119 { status with external_ram = 1133 WordMap.add dpr v status.external_ram }1120 Physical.WordMap.add dpr v status.external_ram } 1134 1121 | `EXT_INDIRECT b -> 1135 1122 let addr = get_register status (false,false,b) in 1136 1123 { status with external_ram = 1137 WordMap.add (mk_word (zero `Eight) addr) v status.external_ram }1124 Physical.WordMap.add (mk_word (zero `Eight) addr) v status.external_ram } 1138 1125 ;; 1139 1126 … … 1741 1728 let dptr = mk_word status.dph status.dpl in 1742 1729 let cry, addr = half_add dptr big_acc in 1743 let lookup = WordMap.find addr status.code_memory in1730 let lookup = Physical.WordMap.find addr status.code_memory in 1744 1731 { status with acc = lookup } 1745 1732 | `MOVC (`A, `A_PC) -> … … 1750 1737 let status = { status with pc = inc_pc } in 1751 1738 let cry,addr = half_add inc_pc big_acc in 1752 let lookup = WordMap.find addr status.code_memory in1739 let lookup = Physical.WordMap.find addr status.code_memory in 1753 1740 { status with acc = lookup } 1754 1741 (* data transfer *) … … 1813 1800 status 1814 1801 | `RET -> 1815 let high_bits = read_at_sp status in1816 let new_sp,cy,_,_ = subb8_with_c status.sp (vect_of_int 1 `Eight) false in1817 let status = { status with sp = new_sp } in1818 let low_bits = read_at_sp status in1819 let new_sp,_,_,_ = subb8_with_c status.sp (vect_of_int 1 `Eight) cy in1820 let status = { status with sp = new_sp } in1821 { status with pc = mk_word high_bits low_bits }1822 (*1823 1802 (* DPM: What happens when we underflow? *) 1824 1803 let high_bits = read_at_sp status in … … 1829 1808 let status = { status with sp = new_sp } in 1830 1809 { status with pc = mk_word high_bits low_bits } 1831 *)1832 1810 | `RETI -> 1833 1811 let high_bits = read_at_sp status in … … 1846 1824 let status = { status with sp = new_sp } in 1847 1825 let status = write_at_sp status pc_upper_byte in 1848 let n1, n2 = from_byte pc_upper_byte in 1849 let (b1,b2,b3,_) = from_word11 a in 1850 let (p1,p2,p3,p4),(p5,_,_,_) = from_nibble n1, from_nibble n2 in 1851 let addr = mk_word (mk_byte (mk_nibble p1 p2 p3 p4) (mk_nibble p5 b1 b2 b3)) pc_lower_byte in 1826 let addr = addr16_of_addr11 status.pc a in 1852 1827 { status with pc = addr } 1853 1828 | `LCALL (`ADDR16 addr) -> … … 1861 1836 { status with pc = addr } 1862 1837 | `AJMP (`ADDR11 a) -> 1863 let pc_upper_byte, pc_lower_byte = from_word status.pc in 1864 let n1, n2 = from_byte pc_upper_byte in 1865 let (p1,p2,p3,p4),(p5,_,_,_) = from_nibble n1, from_nibble n2 in 1866 let (b1,b2,b3,b) = from_word11 a in 1867 let addr = mk_word (mk_byte (mk_nibble p1 p2 p3 p4) (mk_nibble p5 b1 b2 b3)) b in 1868 let cry, new_pc = half_add status.pc addr in 1869 { status with pc = new_pc } 1838 let addr = addr16_of_addr11 status.pc a in 1839 { status with pc = addr } 1870 1840 | `LJMP (`ADDR16 a) -> 1871 1841 { status with pc = a } … … 1954 1924 ;; 1955 1925 1956 let eq_pc pc1 pc2 = 1957 let to_int = BitVectors.int_of_vect in 1958 to_int pc1 = to_int pc2 1959 1960 let end_of_program st = match st.exit_pc with 1961 | None -> false 1962 | Some exit_pc -> eq_pc st.pc exit_pc 1963 1964 let print_result st = 1965 Printf.printf "Result : DPL = %d DPH = %d\n%!" 1966 (BitVectors.int_of_vect st.dpl) (BitVectors.int_of_vect st.dph) 1967 1968 let print_instr instr = 1969 Printf.printf "%s\n%!" (ASMPrinter.pp_instruction instr) 1926 1927 let load_program p = 1928 let st = load p.ASM.code initialize in 1929 { st with exit_addr = p.ASM.exit_addr ; cost_labels = p.ASM.cost_labels } 1970 1930 1971 1931 let observe_trace trace_ref st = 1972 let pc = st.pc in1973 let (instr, _, _) = fetch st.code_memory pc in1974 let ipc = BitVectors.int_of_vect pc in1975 (* <DEBUG> *)1976 print_result st ;1977 Printf.printf "%d: %!" ipc ;1978 print_instr instr ;1979 (* </DEBUG> *)1980 1932 let cost_label = 1981 if IntMap.mem ipc st.costs then [IntMap.find ipc st.costs] 1933 if BitVectors.WordMap.mem st.pc st.cost_labels then 1934 [BitVectors.WordMap.find st.pc st.cost_labels] 1982 1935 else [] in 1983 1936 trace_ref := cost_label @ !trace_ref ; 1984 if end_of_program st then raise Halt else st 1985 1986 let interpret p = 1937 if st.pc = st.exit_addr (* <=> end of program *) then raise Halt else st 1938 1939 let result st = 1940 let i = BitVectors.int_of_vect st.dpl in 1941 IntValue.Int8.of_int i 1942 1943 let interpret print_result p = 1987 1944 if p.ASM.has_main then 1988 let (insts, exit_pc, costs) = assembly p in 1989 let st = load insts (Some exit_pc) costs initialize in 1945 let st = load_program p in 1990 1946 let trace = ref [] in 1991 1947 let callback = observe_trace trace in 1992 1948 let st = execute callback st in 1993 (* <DEBUG> *) 1994 print_result st ; 1995 (* </DEBUG> *) 1996 List.rev !trace 1997 else [] 1998 1999 let parse_and_interpret_hex file = 2000 let intel_hex = IntelHex.intel_hex_of_file file in 2001 let physical = IntelHex.process_intel_hex intel_hex in 2002 let st = load_mem physical None IntMap.empty initialize in 2003 let callback = observe_trace (ref []) in 2004 ignore (execute callback st) 1949 let res = result st in 1950 if print_result then 1951 Printf.printf "8051: %s\n%!" (IntValue.Int8.to_string res) ; 1952 (res, List.rev !trace) 1953 else (IntValue.Int8.zero, []) -
Deliverables/D2.2/8051/src/ASM/ASMInterpret.mli
r486 r619 3 3 4 4 exception CodeTooLarge 5 5 6 6 type time = int;; 7 7 type line = [ `P1 of byte … … 18 18 (* In: reception time, line of input, new continuation, 19 19 Out: transmission time, output line, expected duration until reply, 20 20 new continuation. 21 21 *) 22 22 type continuation = 23 23 [`In of time * line * epsilon * continuation] option * 24 [`Out of (time -> line -> time * continuation) ];; 25 26 module IntMap: Map.S with type key = int 27 type costs = CostLabel.t IntMap.t 24 [`Out of (time -> line -> time * continuation) ];; 28 25 29 26 type status = 30 { 31 (* Memory *) 32 code_memory: WordMap.map; (* can be reduced *) 33 low_internal_ram: Byte7Map.map; 34 high_internal_ram: Byte7Map.map; 35 external_ram: WordMap.map; 27 { 28 (* Memory *) 29 code_memory: WordMap.map; (* can be reduced *) 30 low_internal_ram: Byte7Map.map; 31 high_internal_ram: Byte7Map.map; 32 external_ram: WordMap.map; 33 34 (* Program counter *) 35 pc: word; 36 37 (* SFRs *) 38 sp: byte; 39 dpl: byte; 40 dph: byte; 41 pcon: byte; 42 tcon: byte; 43 tmod: byte; 44 tl0: byte; 45 tl1: byte; 46 th0: byte; 47 th1: byte; 48 p1: byte; 49 scon: byte; 50 sbuf: byte; 51 ie: byte; 52 p3: byte; 53 ip: byte; 54 psw: byte; 55 acc: byte; 56 b: byte; 57 t2con: byte; (* 8052 only *) 58 rcap2l: byte; (* 8052 only *) 59 rcap2h: byte; (* 8052 only *) 60 tl2: byte; (* 8052 only *) 61 th2: byte; (* 8052 only *) 62 63 (* Latches for the output lines *) 64 p1_latch: byte; 65 p3_latch: byte; 66 67 (* Fields for tracking the state of the processor. *) 68 69 (* IO specific *) 70 previous_p1_val: bool; 71 previous_p3_val: bool; 72 73 serial_epsilon_out: epsilon option; 74 serial_epsilon_in: epsilon option; 75 76 io_epsilon: epsilon; 77 78 serial_v_in: [`Eight of byte | `Nine of (BitVectors.bit * byte) ] option; 79 serial_v_out: [`Eight of byte | `Nine of (BitVectors.bit * byte) ] option; 80 81 serial_k_out: continuation option; 82 83 io: continuation; 84 expected_out_time: [ `None | `Now | `At of time ]; 85 86 (* Timer and clock specific *) 87 clock: time; 88 timer0: word; 89 timer1: word; 90 timer2: word; (* can be missing *) 91 92 esi_running: bool; 93 t0i_running: bool; 94 t1i_running: bool; 95 e0i_running: bool; 96 e1i_running: bool; 97 es_running: bool; 36 98 37 (* Program counter *) 38 pc: word; 39 40 (* SFRs *) 41 sp: byte; 42 dpl: byte; 43 dph: byte; 44 pcon: byte; 45 tcon: byte; 46 tmod: byte; 47 tl0: byte; 48 tl1: byte; 49 th0: byte; 50 th1: byte; 51 p1: byte; 52 scon: byte; 53 sbuf: byte; 54 ie: byte; 55 p3: byte; 56 ip: byte; 57 psw: byte; 58 acc: byte; 59 b: byte; 60 t2con: byte; (* 8052 only *) 61 rcap2l: byte; (* 8052 only *) 62 rcap2h: byte; (* 8052 only *) 63 tl2: byte; (* 8052 only *) 64 th2: byte; (* 8052 only *) 65 66 (* Latches for the output lines *) 67 p1_latch: byte; 68 p3_latch: byte; 69 70 (* Fields for tracking the state of the processor. *) 71 72 (* IO specific *) 73 previous_p1_val: bool; 74 previous_p3_val: bool; 75 76 serial_epsilon_out: epsilon option; 77 serial_epsilon_in: epsilon option; 78 79 io_epsilon: epsilon; 80 81 serial_v_in: [`Eight of byte | `Nine of (BitVectors.bit * byte) ] option; 82 serial_v_out: [`Eight of byte | `Nine of (BitVectors.bit * byte) ] option; 83 84 serial_k_out: continuation option; 85 86 io: continuation; 87 expected_out_time: [ `None | `Now | `At of time ]; 88 89 (* Timer and clock specific *) 90 clock: time; 91 timer0: word; 92 timer1: word; 93 timer2: word; (* can be missing *) 94 95 esi_running: bool; 96 t0i_running: bool; 97 t1i_running: bool; 98 e0i_running: bool; 99 e1i_running: bool; 100 es_running: bool; 101 102 exit_pc: word option; 103 costs: costs; 104 } 105 99 exit_addr : BitVectors.word; 100 cost_labels : string BitVectors.WordMap.t 101 } 102 106 103 val string_of_status: status -> string 107 104 108 val assembly: ASM.program -> BitVectors.byte list (*ASM.instruction list * symbol_table *) * word (* exit pc *) * string IntMap.t 105 106 val assembly: 107 [< ASM.labelled_instruction] ASM.pretty_program -> ASM.program 109 108 110 109 (* 111 val link:112 (ASM.instruction list * symbol_table * cost_map) list -> BitVectors.byte list110 val link: 111 (ASM.instruction list * symbol_table * cost_map) list -> BitVectors.byte list 113 112 *) 114 113 115 114 val initialize: status 116 117 val load_mem: Physical.WordMap.map -> word option -> costs -> status -> status 118 val load: BitVectors.byte list -> word option -> costs -> status -> status 119 115 116 val load_code_memory: BitVectors.byte list -> Physical.WordMap.map 117 val load_mem: Physical.WordMap.map -> status -> status 118 val load: BitVectors.byte list -> status -> status 119 120 120 exception Halt (* to be raised to stop execution *) 121 121 122 122 (* the callback function is used to observe the execution 123 123 trace; it can raise Hold to stop execution. Otherwise 124 124 the processor never halts. *) 125 125 val execute: (status -> unit) -> status -> status 126 126 127 127 val fetch: Physical.WordMap.map -> word -> ASM.instruction * word * int 128 128 129 val interpret : ASM.program -> AST.trace 130 131 val parse_and_interpret_hex : string -> unit 129 val load_program : ASM.program -> status 130 val interpret : bool -> ASM.program -> AST.trace -
Deliverables/D2.2/8051/src/ASM/ASMPrinter.ml
r486 r619 1 open BitVectors;;2 open ASM;;3 1 4 let pp_arg = 5 function 6 `A -> "A" 7 | `B -> "B" 8 | `C -> "C" 9 | `DPTR -> "DPTR" 10 | `ADDR11 x -> hex_string_of_vect x 11 | `ADDR16 x -> hex_string_of_vect x 12 | `DATA x -> "#0" ^ hex_string_of_vect x ^ "h" 13 | `DATA16 x -> "#0" ^ hex_string_of_vect x ^ "h" 14 | `BIT x -> "bit " ^ hex_string_of_vect (x: byte) 15 | `NBIT x -> "nbit " ^ hex_string_of_vect (x: byte) 16 | `REG (r1, r2, r3) -> "R" ^ string_of_int (int_of_vect (mk_nibble false r1 r2 r3)) 17 | `REL x -> hex_string_of_vect x 18 | `A_DPTR -> "@DPTR" 19 | `A_PC -> "@PC" 20 | `DIRECT x -> "0" ^ (hex_string_of_vect (x: byte)) ^ "h" 21 | `EXT_INDIRECT x -> "ext_indirect " ^ string_of_bool x 22 | `EXT_IND_DPTR -> "@DPTR" 23 (* DPM: weird: this seems to be reversed in mcu8051ide: change made. *) 24 | `INDIRECT x -> if not x then "@R0" else "@R1" 25 | `IND_DPTR -> "@DPTR" 26 | `Label s -> s 27 ;; 28 29 let pp_jump = 30 function 31 `CJNE (`U1 (a1,a2),a3) -> "cjne " ^ pp_arg a1 ^ ", " ^ pp_arg a2 ^ ", " ^ pp_arg a3 32 | `CJNE (`U2 (a1,a2),a3) -> "cjne " ^ pp_arg a1 ^ ", " ^ pp_arg a2 ^ ", " ^ pp_arg a3 33 | `DJNZ (a1,a2) -> "djnz " ^ pp_arg a1 ^ ", " ^ pp_arg a2 34 | `JB (a1,a2) -> "jb " ^ pp_arg a1 ^ ", " ^ pp_arg a2 35 | `JBC (a1,a2) -> "jbc " ^ pp_arg a1 ^ ", " ^ pp_arg a2 36 | `JC a1 -> "jc " ^ pp_arg a1 37 | `JNB (a1,a2) -> "jnb " ^ pp_arg a1 ^ ", " ^ pp_arg a2 38 | `JNC a1 -> "jnc " ^ pp_arg a1 39 | `JNZ a1 -> "jnz " ^ pp_arg a1 40 | `JZ a1 -> "jz " ^ pp_arg a1 41 42 let pp_instruction = 43 function 44 `Label l -> l ^ ":" 45 | `Cost l -> l ^ ":" 46 | `Jmp j -> "ljmp " ^ j 47 | `Call j -> "lcall " ^ j 48 | `WithLabel i -> pp_jump i 49 | `Begin_fun -> "\n; Begin function" 50 | `End_fun -> "; End function\n" 51 | (#jump as i) -> pp_jump i 52 | `Mov (a1,a2) -> "mov " ^ pp_arg a1 ^ ", " ^ a2 53 | `ACALL a1 -> "acall " ^ pp_arg a1 54 | `ADD (a1,a2) -> "add " ^ pp_arg a1 ^ ", " ^ pp_arg a2 55 | `ADDC (a1,a2) -> "addc " ^ pp_arg a1 ^ ", " ^ pp_arg a2 56 | `AJMP a1 -> "ajmp " ^ pp_arg a1 57 | `ANL (`U1 (a1,a2)) -> "anl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 58 | `ANL (`U2 (a1,a2)) -> "anl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 59 | `ANL (`U3 (a1,a2)) -> "anl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 60 | `CLR a1 -> "clr " ^ pp_arg a1 61 | `CPL a1 -> "cpl " ^ pp_arg a1 62 | `DA a1 -> "da " ^ pp_arg a1 63 | `DEC a1 -> "dec " ^ pp_arg a1 64 | `DIV (a1,a2) -> "div AB" 65 | `INC a1 -> "inc " ^ pp_arg a1 66 | `JMP a1 -> "jmp " ^ pp_arg a1 67 | `LCALL a1 -> "lcall " ^ pp_arg a1 68 | `LJMP a1 -> "ljmp " ^ pp_arg a1 69 | `MOV (`U1 (a1,a2)) -> "mov " ^ pp_arg a1 ^ ", " ^ pp_arg a2 70 | `MOV (`U2 (a1,a2)) -> "mov " ^ pp_arg a1 ^ ", " ^ pp_arg a2 71 | `MOV (`U3 (a1,a2)) -> "mov " ^ pp_arg a1 ^ ", " ^ pp_arg a2 72 | `MOV (`U4 (a1,a2)) -> "mov " ^ pp_arg a1 ^ ", " ^ pp_arg a2 73 | `MOV (`U5 (a1,a2)) -> "mov " ^ pp_arg a1 ^ ", " ^ pp_arg a2 74 | `MOV (`U6 (a1,a2)) -> "mov " ^ pp_arg a1 ^ ", " ^ pp_arg a2 75 | `MOVC (a1,a2) -> "movc " ^ pp_arg a1 ^ ", " ^ pp_arg a2 76 | `MOVX (`U1 (a1,a2)) -> "movx " ^ pp_arg a1 ^ ", " ^ pp_arg a2 77 | `MOVX (`U2 (a1,a2)) -> "movx " ^ pp_arg a1 ^ ", " ^ pp_arg a2 78 | `MUL(a1, a2) -> "mul AB" 79 | `NOP -> "nop" 80 | `ORL (`U1(a1,a2)) -> "orl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 81 | `ORL (`U2(a1,a2)) -> "orl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 82 | `ORL (`U3(a1,a2)) -> "orl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 83 | `POP a1 -> "pop " ^ pp_arg a1 84 | `PUSH a1 -> "push " ^ pp_arg a1 85 | `RET -> "ret" 86 | `RETI -> "reti" 87 | `RL a1 -> "rl " ^ pp_arg a1 88 | `RLC a1 -> "rlc " ^ pp_arg a1 89 | `RR a1 -> "rr " ^ pp_arg a1 90 | `RRC a1 -> "rrc " ^ pp_arg a1 91 | `SETB a1 -> "setb " ^ pp_arg a1 92 | `SJMP a1 -> "sjmp " ^ pp_arg a1 93 | `SUBB (a1,a2) -> "subb " ^ pp_arg a1 ^ ", " ^ pp_arg a2 94 | `SWAP a1 -> "swap " ^ pp_arg a1 95 | `XCH (a1,a2) -> "xch " ^ pp_arg a1 ^ ", " ^ pp_arg a2 96 | `XCHD(a1,a2) -> "xchd " ^ pp_arg a1 ^ ", " ^ pp_arg a2 97 | `XRL(`U1(a1,a2)) -> "xrl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 98 | `XRL(`U2(a1,a2)) -> "xrl " ^ pp_arg a1 ^ ", " ^ pp_arg a2 2 (** This module provides a function to print [ASM] programs. *) 99 3 100 4 let print_program p = 101 let f s i = Printf.sprintf "%s%s\n" s (pp_instruction i) in 102 "Org 0\n\n" ^ (List.fold_left f "" p.ASM.code) ^ "\nEND\n" 5 let code_memory = ASMInterpret.load_code_memory p.ASM.code in 6 let intel_hex = IntelHex.pack_exported_code_memory 16 65536 code_memory in 7 IntelHex.string_of_intel_hex_format intel_hex -
Deliverables/D2.2/8051/src/ASM/ASMPrinter.mli
r486 r619 1 val pp_arg: 2 [< `A 3 | `ADDR11 of 'a BitVectors.vect 4 | `ADDR16 of 'b BitVectors.vect 5 | `A_DPTR 6 | `A_PC 7 | `B 8 | `BIT of BitVectors.byte 9 | `C 10 | `DATA of 'c BitVectors.vect 11 | `DATA16 of 'd BitVectors.vect 12 | `DIRECT of BitVectors.byte 13 | `DPTR 14 | `EXT_INDIRECT of bool 15 | `EXT_IND_DPTR 16 | `INDIRECT of bool 17 | `IND_DPTR 18 | `NBIT of BitVectors.byte 19 | `REG of BitVectors.bit * BitVectors.bit * BitVectors.bit 20 | `REL of 'e BitVectors.vect ] -> string 21 val pp_instruction: [< ASM.labelled_instruction] -> string 1 2 (** This module provides a function to print [ASM] programs. *) 22 3 23 4 val print_program : ASM.program -> string -
Deliverables/D2.2/8051/src/ASM/BitVectors.ml
r486 r619 155 155 (* CSC: only works properly with bytes!!! *) 156 156 let hex_string_of_vect v = Printf.sprintf "%0 2X" (int_of_vect v);; 157 158 module WordMap = 159 Map.Make (struct type t = word let compare = compare end);; -
Deliverables/D2.2/8051/src/ASM/BitVectors.mli
r486 r619 54 54 val shift_right : 'a vect -> 'a vect 55 55 val shift_left : 'a vect -> 'a vect 56 57 module WordMap: Map.S with type key = word -
Deliverables/D2.2/8051/src/ASM/I8051.ml
r486 r619 44 44 | Mul -> Val.mul 45 45 | Divu -> Val.divu 46 | Modu -> Val.modu 46 | Modu -> Val.modulou 47 47 48 48 let op1 = function … … 57 57 (res2, Val.or_op of1 of2) 58 58 | Sub -> 59 let (res1, uf1) = Val.sub_and_ of v1 v2 in60 let (res2, uf2) = Val.sub_and_ of res1 carry in59 let (res1, uf1) = Val.sub_and_uf v1 v2 in 60 let (res2, uf2) = Val.sub_and_uf res1 carry in 61 61 (res2, Val.or_op uf1 uf2) 62 62 | And -> (Val.and_op v1 v2, carry) -
Deliverables/D2.2/8051/src/ASM/IntelHex.ml
r486 r619 3 3 open Util;; 4 4 open Parser;; 5 open Printf;; 5 6 6 7 exception WrongFormat of string … … 32 33 | '9' -> 9 | 'A' -> 10 | 'B' -> 11 33 34 | 'C' -> 12 | 'D' -> 13 | 'E' -> 14 34 | 'F' -> 15 | _ -> assert false 35 | 'F' -> 15 | 'a' -> 10 | 'b' -> 11 36 | 'c' -> 12 | 'd' -> 13 | 'e' -> 14 37 | 'f' -> 15 | _ -> assert false 35 38 36 39 let intel_hex_entry_type_of_int = … … 93 96 aux (false, (vect_of_int 0 `Eight)) r 94 97 95 let c hecksum_validhex_entry =98 let calculate_checksum hex_entry = 96 99 let ty = (flip vect_of_int $ `Eight) $ int_of_intel_hex_entry_type hex_entry.record_type in 97 100 let addr1,addr2 = from_word hex_entry.record_addr in 98 101 let _, total = add_bytes (hex_entry.record_length :: addr1 :: addr2 :: ty :: hex_entry.data_field) in 99 102 let _,total = half_add (vect_of_int 1 `Eight) $ complement total in 100 hex_entry.data_checksum = total 101 103 total 104 105 let checksum_valid hex_entry = 106 let total = calculate_checksum hex_entry in 107 hex_entry.data_checksum = total 102 108 103 109 let prs_intel_hex_record = … … 135 141 let string_of_intel_hex_entry entry = 136 142 let length_string = hex_string_of_vect entry.record_length in 137 let addr_string = hex_string_of_vect entry.record_addrin138 let checksum_string = hex_string_of_vect entry.data_checksumin139 let type_string = Printf.sprintf "%0 143 let addr_string = Printf.sprintf "%04X" (int_of_vect entry.record_addr) in 144 let checksum_string = Printf.sprintf "%02X" (int_of_vect entry.data_checksum) in 145 let type_string = Printf.sprintf "%02d" (int_of_intel_hex_entry_type entry.record_type) in 140 146 let data_string = String.concat "" (List.map hex_string_of_vect entry.data_field) in 141 147 ":" ^ length_string ^ addr_string ^ type_string ^ data_string ^ checksum_string … … 188 194 aux Physical.WordMap.empty 189 195 ;; 196 197 (* DPM: this needs some comment: 198 We aim to extract code memory into segmented lists of bytes, with a maximum 199 length (chunk_size). The code memory map has a fixed size (max_addressable) 200 on the 8051. Further, the chunks we extract get segmented when we find an 201 unitialized zone in the code memory. 202 *) 203 let export_code_memory chunk_size max_addressable code_mem = 204 let rec aux chunk address start_address rbuff lbuff = 205 if address = max_addressable then 206 (start_address, List.rev rbuff)::lbuff 207 else if chunk = 0 then 208 aux chunk_size address address [] ((start_address, List.rev rbuff)::lbuff) 209 else 210 let code = Physical.WordMap.find (vect_of_int address `Sixteen) code_mem in 211 aux (chunk - 1) (address + 1) start_address (code::rbuff) lbuff 212 in 213 List.rev (aux chunk_size 0 0 [] []) 214 ;; 215 216 let clean_exported_code_memory = List.filter (fun x -> snd x <> []) 217 ;; 218 219 let calculate_data_checksum (record_length, record_addr, record_type, data_field) = 220 let ty = (flip vect_of_int $ `Eight) $ int_of_intel_hex_entry_type record_type in 221 let addr1,addr2 = from_word record_addr in 222 let _, total = add_bytes (record_length :: addr1 :: addr2 :: ty :: data_field) in 223 let _,total = half_add (vect_of_int 0 `Eight) $ complement total in 224 total 225 ;; 226 227 let process_exported_code_memory = 228 List.map (fun x -> 229 let record_length = vect_of_int (List.length (snd x)) `Eight in 230 let record_addr = vect_of_int (fst x) `Sixteen in 231 let record_type = Data in 232 let data_field = snd x in 233 let temp_record = 234 { record_length = record_length; 235 record_addr = record_addr; 236 record_type = record_type; 237 data_field = data_field; 238 data_checksum = zero `Eight 239 } in 240 { temp_record with data_checksum = calculate_checksum temp_record }) 241 ;; 242 243 let pack_exported_code_memory chunk_size max_addressable code_mem = 244 let export = export_code_memory chunk_size max_addressable code_mem in 245 let cleaned = clean_exported_code_memory export in 246 let processed = process_exported_code_memory cleaned in 247 let end_buffer = 248 [{ record_length = zero `Eight; 249 record_addr = zero `Sixteen; 250 record_type = End; 251 data_field = []; 252 data_checksum = vect_of_int 255 `Eight 253 }] in 254 processed @ end_buffer 255 ;; 256 257 let file_of_intel_hex path fmt = 258 let str_fmt = string_of_intel_hex_format fmt in 259 let channel = open_out path in 260 fprintf channel "%s\n" str_fmt; 261 close_out channel 262 ;; -
Deliverables/D2.2/8051/src/ASM/IntelHex.mli
r486 r619 11 11 12 12 val intel_hex_of_file: string -> intel_hex_format 13 val file_of_intel_hex: string -> intel_hex_format -> unit 13 14 val process_intel_hex: intel_hex_format -> Physical.WordMap.map 15 16 val pack_exported_code_memory: int -> int -> Physical.WordMap.map -> intel_hex_format 17 val file_of_intel_hex: string -> intel_hex_format -> unit -
Deliverables/D2.2/8051/src/ASM/Parser.ml
r486 r619 84 84 x = '4' || x = '5' || x = '6' || x = '7' || 85 85 x = '8' || x = '9' || x = 'A' || x = 'B' || 86 x = 'C' || x = 'D' || x = 'E' || x = 'F') 86 x = 'C' || x = 'D' || x = 'E' || x = 'F' || 87 x = 'a' || x = 'b' || x = 'c' || x = 'd' || 88 x = 'e' || x = 'f') 87 89 -
Deliverables/D2.2/8051/src/ASM/Physical.ml
r486 r619 10 10 val find : key -> map -> byte 11 11 val add : key -> byte -> map -> map 12 val fold : (key -> byte -> 'b -> 'b) -> map -> 'b -> 'b 13 val equal: (byte -> byte -> bool) -> map -> map -> bool 12 14 end 13 15 ;; … … 21 23 find k m 22 24 with Not_found -> zero `Eight 25 let fold = fold 26 let equal = equal 23 27 end;; 24 28 … … 31 35 find k m 32 36 with Not_found -> zero `Eight 37 let fold = fold 38 let equal = equal 33 39 end;; 34 40 … … 97 103 | _ -> assert false 98 104 ;; 105 106 let addr16_of_addr11 pc a = 107 let pc_upper, _ = from_word pc in 108 let n1, n2 = from_byte pc_upper in 109 let (b1,b2,b3,b) = from_word11 a in 110 let (p1,p2,p3,p4),(p5,_,_,_) = from_nibble n1, from_nibble n2 in 111 mk_word (mk_byte (mk_nibble p1 p2 p3 p4) (mk_nibble p5 b1 b2 b3)) b 112 ;; -
Deliverables/D2.2/8051/src/ASM/Physical.mli
r486 r619 10 10 val find : key -> map -> byte 11 11 val add : key -> byte -> map -> map 12 val fold : (key -> byte -> 'b -> 'b) -> map -> 'b -> 'b 13 val equal: (byte -> byte -> bool) -> map -> map -> bool 12 14 end 13 15 ;; … … 26 28 val dec: byte -> byte (* with roll-over *) 27 29 val inc: byte -> byte (* with roll-over *) 30 31 val addr16_of_addr11: word -> word11 -> word
Note: See TracChangeset
for help on using the changeset viewer.