drisc.ml

Back

Per utilizzare il codice occorre comunque caricare “asm.ml” che contiene le definizioni delle istruzioni assembler D-RISC.

"drisc.ml"
(** 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
;;

Back