5 type map = (Label.t * address) list
17 | `Backpatch of int * (address -> map -> int list) (* (size,fun current_address map -> [...]) *)
20 type t = [ base | label ]
23 if 0 <=n && n <= 0xFF then
29 if 0 <= n && n <= 0xFFFF then
48 let backpatch size f =
51 (** encode "base" to bytes *)
52 let (&/) = Int32.logand
53 let (|/) = Int32.logor
54 let (>>) = Int32.shift_right_logical
56 let split_byte nth value size =
57 List.map (fun i-> nth value (i*8)) @@ range 0 size
60 split_byte (fun n i-> (n lsr i) land 0xFF)
62 let split_byte_int64 value size =
63 List.map Int64.to_int @@
65 (fun n i->(Int64.logand (Int64.shift_right_logical n i) 0xFFL))
68 let rec of_base : base -> int list =
77 split_byte_int64 (Int64.bits_of_float f) 8
78 | `U30 x | `U32 x | `S32 x ->
86 else if 0l < x && x <= 0x7Fl then
87 Some (Int32.to_int (x &/ 0x7Fl),0l)
92 Int32.to_int ((x &/ 0x7Fl) |/ 0x80l) in
93 Some (current,next)) x
95 let rec of_label addr map =
101 of_label addr ((t,addr)::map) xs in
103 | `Backpatch (size, patch)::xs ->
105 of_label (addr+size) map xs in
106 (fun m -> patch addr m @ f m),map'
107 | #base as base::xs ->
111 of_label (addr + List.length bytes) map xs in
112 (fun m -> bytes @ f m),map'
114 let find : map -> Label.t -> address = flip List.assoc
116 let label_ref label =
117 backpatch 3 (fun addr m -> of_base @@ `S24 (find m label - (addr + 3)))
124 let rec output_bytes ch bytes =
127 +> List.iter (output_byte ch)