Per utilizzare il codice occorre comunque caricare “asm.ml” che contiene le definizioni delle istruzioni assembler D-RISC.
(** shortcut to maps ... *) type assoc = Ass of string * int;; (** checks whether a key is in a map *) let rec hasKey k = function [] -> false | Ass(kk,vv)::rm -> if(kk = k) then true else (hasKey k rm);; (** looks up a key in a map*) let rec valueOfKey k labs = match labs with [] -> failwith "key not found" | Ass(kk,vv)::rl -> if(kk=k) then vv else (valueOfKey k rl);; (** execution environment (the state of the processor + the labels compiled. an environment is pc, reg, mem, labels *) type penv = Penv of int ref * int ref array * int ref array * assoc list;; (** pretty print the environment *) let dump penv = match penv with Penv(pc,r,m,a) -> printf "PC=%d \n" !pc; printf "%d registers. #MV = %d \n" (Array.length r) (Array.length m); pp_reg_set r; pp_mem m ;; (** execute one instruction within an environment @param i the instruction to be executed @param env the initial environment. it is modified via side effects *) let step pgm env = let apgm = Array.of_list (prog_to_asm pgm) in match env with Penv(pc,r,m,labs) -> (let i = apgm.(!pc) in match i with ADD(Reg(a),Reg(b),Reg(c)) -> r.(c) := !(r.(a)) + !(r.(b));pc:= !pc+1 | SUB(Reg(a),Reg(b),Reg(c)) -> r.(c) := !(r.(a)) - !(r.(b));pc:= !pc+1 | MUL(Reg(a),Reg(b),Reg(c)) -> r.(c) := !(r.(a)) * !(r.(b));pc:= !pc+1 | DIV(Reg(a),Reg(b),Reg(c)) -> r.(c) := !(r.(a)) / !(r.(b));pc:= !pc+1 | ADDI(Reg(a),Const(b),Reg(c)) -> r.(c) := !(r.(a)) + b;pc:= !pc+1 | SUBI(Reg(a),Const(b),Reg(c)) -> r.(c) := !(r.(a)) - b;pc:= !pc+1 | INC(Reg(a)) -> r.(a) := !(r.(a))+1; pc:= !pc +1 | DEC(Reg(a)) -> r.(a) := !(r.(a))-1; pc:= !pc +1 | LD(Reg(a),Reg(b),Reg(c)) -> let ind = !(r.(a)) + !(r.(b)) in r.(c) := !(m.(ind)); pc := !pc + 1 | LDI(Reg(a),Const(b),Reg(c)) -> let ind = !(r.(a)) + b in r.(c) := !(m.(ind)); pc := !pc + 1 | ST(Reg(a),Reg(b),Reg(c)) -> let ind = !(r.(a)) + !(r.(b)) in m.(ind) := !(r.(c)); pc := !pc + 1 | STI(Reg(a),Const(b),Reg(c)) -> let ind = !(r.(a)) + b in m.(ind) := !(r.(c)); pc := !pc + 1 | CALL(Reg(f), Reg(ret)) -> r.(ret):= !pc + 1; pc := !(r.(f)) | GOTOR(Reg(l)) -> pc := !(r.(l)) | GOTOL(LabLab(ll)) -> let l = valueOfKey ll labs in pc := !pc + l | IFLEQ(Reg(r1),Reg(r2),LabOff(l)) -> if(!(r.(r1)) <= !(r.(r2))) then pc := !pc + l else pc := !pc + 1 | IFLE(Reg(r1),Reg(r2),LabOff(l)) -> if(!(r.(r1)) < !(r.(r2))) then pc := !pc + l else pc := !pc + 1 | IFGEQ(Reg(r1),Reg(r2),LabOff(l)) -> if(!(r.(r1)) >= !(r.(r2))) then pc := !pc + l else pc := !pc + 1 | IFGE(Reg(r1),Reg(r2),LabOff(l)) -> if(!(r.(r1)) > !(r.(r2))) then pc := !pc + l else pc := !pc + 1 | IFEQ(Reg(r1),Reg(r2),LabOff(l)) -> if(!(r.(r1)) = !(r.(r2))) then pc := !pc + l else pc := !pc + 1 | IFNEQ(Reg(r1),Reg(r2),LabOff(l)) -> if(not(!(r.(r1)) = !(r.(r2)))) then pc := !pc + l else pc := !pc + 1 | END -> failwith "Program terminated" | _ -> printf "UNIMPLEMENTED:"; pp_asm i) ;; (** compile labels. Takes a program with labels and returns a map with the label addresses @param pgm the program @param addr the initial address of the program *) let rec labels pgm addr = match pgm with [] -> [] | i::ri -> (match i with Instr(i) -> (labels ri (addr+1)) | LabInstr(LabLab(l),i) -> Ass(l,addr)::(labels ri (addr+1)) | LabInstr(LabOff(l),i) -> (labels ri (addr+1)) ) ;; let create_regs n = Array.create n (ref 0);; let stepper r m ipc prg steps = let pc = ref ipc in let reg = create_regs r in let mem = create_regs m in let penv = Penv(pc,reg,mem,(labels prg 0)) in let aprg = Array.of_list prg in for i=0 to steps do printf "===========> STEP %d: executing " i; (pp_instr !pc aprg.(i)); printf "\n"; step prg penv; dump penv; done ;;