open Bigarray
let create_array n = Array1.create int32 c_layout n
let empty_array = create_array 0
let array_copy a =
let t = Array1.create int32 c_layout (Array1.dim a) in
Array1.blit a t;
t
let arr = Array.create 65536 [||]
let arr_get n =
let high = Int32.to_int (Int32.shift_right_logical n 16) in
assert (0 <= high && high <= 0xffff);
let low = (Int32.to_int n) land 0xffff in
assert (0 <= low && low <= 0xffff);
let a = arr.(high) in
assert (Array.length a = 65536);
a.(low)
let arr_set n ba =
let high = Int32.to_int (Int32.shift_right_logical n 16) in
assert (0 <= high && high <= 0xffff);
let low = (Int32.to_int n) land 0xffff in
assert (0 <= low && low <= 0xffff);
if Array.length arr.(high) = 0 then
arr.(high) <- Array.create 65536 empty_array;
let a = arr.(high) in
a.(low) <- ba
let code =
let file = Sys.argv.(1) in
let fd = Unix.openfile file [Unix.O_RDONLY] 0 in
let len = Unix.lseek fd 0 Unix.SEEK_END in
ignore (Unix.lseek fd 0 Unix.SEEK_SET);
let arr = Array1.create int32 c_layout (len/4) in
let ch = Unix.in_channel_of_descr fd in
for i = 0 to len/4 - 1 do
let a = input_char ch in
let b = input_char ch in
let c = input_char ch in
let d = input_char ch in
Array1.set arr i
(Int32.logor (Int32.shift_left (Int32.of_int (Char.code a)) 24)
(Int32.logor (Int32.shift_left (Int32.of_int (Char.code b)) 16)
(Int32.logor (Int32.shift_left (Int32.of_int (Char.code c)) 8)
((Int32.of_int (Char.code d))))))
done;
arr
let () = arr_set 0l code
let free_stack = Stack.create ()
let max_stack = ref 1024
let () = for i = 1 to !max_stack - 1 do Stack.push i free_stack done
let alloc n =
if Stack.is_empty free_stack then begin
let nb = !max_stack in
if nb > max_int - 1024 then failwith "jc_um3: overflow in alloc";
max_stack := !max_stack + 1024;
for i = nb to nb + 1023 do Stack.push i free_stack done
end;
let idx = Stack.pop free_stack in
let a = create_array n in
Array1.fill a 0l;
let idxl = Int32.of_int idx in
arr_set idxl a;
idxl
let dealloc idx =
arr_set idx empty_array;
Stack.push (Int32.to_int idx) free_stack
let all_ones =
Int32.logor
(Int32.of_int 0b1111111111111111)
(Int32.shift_left (Int32.of_int 0b1111111111111111) 16)
let int64_of_uint32 n =
if n >= 0l then
Int64.of_int32 n
else
Int64.add (Int64.of_int32 n) (Int64.shift_left Int64.one 32)
let add_uint32 x y =
Int64.to_int32 (Int64.add (int64_of_uint32 x) (int64_of_uint32 y))
let mul_uint32 x y =
Int64.to_int32 (Int64.mul (int64_of_uint32 x) (int64_of_uint32 y))
let div_uint32 x y =
Int64.to_int32 (Int64.div (int64_of_uint32 x) (int64_of_uint32 y))
let reg = Array.create 8 Int32.zero
let decode n =
Int32.to_int (Int32.shift_right_logical n 28),
(Int32.to_int (Int32.shift_right n 6)) land 7,
(Int32.to_int (Int32.shift_right n 3)) land 7,
(Int32.to_int n) land 7
let decode13 n =
(Int32.to_int (Int32.shift_right n 25)) land 7,
Int32.logand n 33554431l
let rec exec pc =
let n = Array1.get (arr_get 0l) pc in
let op,a,b,c = decode n in
(*Format.printf "n=%ld op=%d a=%d b=%d c=%d@." n op a b c;*)
match op with
| 0 ->
if reg.(c) <> 0l then reg.(a) <- reg.(b);
exec (pc+1)
| 1 ->
reg.(a) <-
Array1.get
(arr_get reg.(b))
(Int32.to_int reg.(c));
exec (pc+1)
| 2 ->
Array1.set (arr_get reg.(a)) (Int32.to_int reg.(b)) reg.(c);
exec (pc+1)
| 3 ->
reg.(a) <- add_uint32 reg.(b) reg.(c);
exec (pc+1)
| 4 ->
reg.(a) <- mul_uint32 reg.(b) reg.(c);
exec (pc+1)
| 5 ->
reg.(a) <- div_uint32 reg.(b) reg.(c);
exec (pc+1)
| 6 ->
reg.(a) <- Int32.lognot (Int32.logand reg.(b) reg.(c));
exec (pc+1)
| 7 ->
print_string "halt.\n";
exit 0
| 8 ->
reg.(b) <- alloc (Int32.to_int reg.(c));
exec (pc+1)
| 9 ->
dealloc reg.(c);
exec (pc+1)
| 10 ->
let c = Int32.to_int reg.(c) in
assert (0 <= c && c <= 255);
print_char (Char.chr c); flush stdout;
exec (pc+1)
| 11 ->
begin
try
let ch = input_char stdin in
reg.(c) <- Int32.of_int (Char.code ch)
with End_of_file ->
reg.(c) <- all_ones
end;
exec (pc+1)
| 12 ->
let valb = reg.(b) in
if valb <> 0l then begin
let new_code = arr_get valb in
arr_set 0l (array_copy new_code)
end;
exec (Int32.to_int reg.(c))
| 13 ->
let a,value = decode13 n in
reg.(a) <- value;
exec (pc+1)
| d ->
failwith ("unsupported operation: " ^ string_of_int d)
let () = exec 0