%{ open Asm let unsigned = function | Addu | Subu | Mulu | Divu | Sltu | Sleu | Jltru | Jleru -> true | _ -> false let pc = ref 0 let ram = ref 0x8000 let add r i = r := !r + i let lbls2 = ref (Imap.empty) let li u r = function | Imm i -> let c = if u then i < 1 lsl 8 else i >= -(1 lsl 7) && i < 1 lsl 7 in if c then (add pc 2; [Lilz (r,Imm i)]) else (add pc 4; [Lilz (r,Imm (i land 0x00FF)); Liu (r,Imm ((i land 0xFF00) lsr 8))]) | Lab id -> add pc 4; [Lilz (r,Lab id); Liu (r,Labu id)] | _ -> assert false let up = function | Imm i -> Imm i | Lab l -> Labu l | _ -> assert false let explode s = (* string -> char list *) let rec exp i l = if i < 0 then l else exp (i - 1) (s.[i] :: l) in exp (String.length s - 1) [];; %} %token EOF,COLON,TEXT,DATA,BYTE,WORD,ASCIIZ,MINUS,MOVE,JZ,JNZ,LP,RP %token POP,PUSH,INCRI,SHI,JJ,JAL,JR,JALR,LW,SW,LB,SB,NOT,LIL,LILZ,LIU,LIUZ,LRA,LA,LI %token REG %token ROP,RIOP %token ID %token INT %token STR %start program %% program: TEXT is=instr* d=data? EOF { { text = List.flatten is; data = (match d with Some l -> List.flatten l | None -> []); lbls = !lbls2 } } data: DATA d=datas* { d } datas: | l=label_ram d=datas { d } | BYTE bs=int* { List.map (fun i -> add ram 1; i,false) bs } | WORD bs=int* { List.map (fun i -> add ram 2; i,true) bs } | ASCIIZ s=STR { add ram 1; List.map (fun c -> add ram 1; Char.code c, false) (explode s) @ [0, false] } label_ram: id=ID COLON { lbls2 := Imap.add id !ram !lbls2; id } label_pc: id=ID COLON { lbls2 := Imap.add id !pc !lbls2; id } instr: | l=label_pc i=instr { i } | i=_instr { i } _instr: | o=ROP r1=REG r2=REG r3=REG { add pc 2; [R (o,r1,r2,r3)] } | o=RIOP r1=REG r2=REG imm=imm { let l = li (unsigned o) 5 imm in add pc 2; l @ [R (o,r1,r2,5)] } | INCRI r=REG i=int { if i >= - (1 lsl 7) && i < 1 lsl 7 then (add pc 2; [Incri (r,i)]) else let l = li false 5 (Imm i) in (add pc 2; l @ [R (Add,r,r,5)]) } | SHI r=REG i=int { add pc 2; [Shi (r,i)] } | JJ i=imm { add pc 2; [J i] } | LI r=REG i=imm { li false r i } | JR r=REG { add pc 2; [Jr r] } | JAL i=imm { add pc 2; [Jal i] } | JALR r=REG { add pc 2; [Jalr r] } | LW r1=REG i=int LP r2=REG RP { if i >= - (1 lsl 4) && i < 1 lsl 4 then (add pc 2; [Lw (r1,r2,i)]) else let l = li false 5 (Imm i) in (add pc 2; l @ [R (Lwr,r1,r2,5)]) } | SW r1=REG i=int LP r2=REG RP { if i >= - (1 lsl 4) && i < 1 lsl 4 then (add pc 2; [Sw (r1,r2,i)]) else let l = li false 5 (Imm i) in (add pc 2; l @ [R (Swr,r1,r2,5)]) } | LB r1=REG i=int LP r2=REG RP { if i >= - (1 lsl 4) && i < 1 lsl 4 then (add pc 2; [Lb (r1,r2,i)]) else let l = li false 5 (Imm i) in (add pc 2; l @ [R (Lbr,r1,r2,5)]) } | SB r1=REG i=int LP r2=REG RP { if i >= - (1 lsl 4) && i < 1 lsl 4 then (add pc 2; [Sb (r1,r2,i)]) else let l = li false 5 (Imm i) in (add pc 2; l @ [R (Sbr,r1,r2,5)]) } | LW r1=REG l=ID { let l = li false 5 (Lab l) in add pc 2; l @ [Lw (r1,5,0)] } | LB r1=REG l=ID { let l = li false 5 (Lab l) in add pc 2; l @ [Lb (r1,5,0)] } | SW r1=REG l=ID { let l = li false 5 (Lab l) in add pc 2; l @ [Sw (r1,5,0)] } | SB r1=REG l=ID { let l = li false 5 (Lab l) in add pc 2; l @ [Sb (r1,5,0)] } | LRA i=int { assert (i > -(1 lsl 10) && i < 1 lsl 10); add pc 2; [Lra (Imm i)] } | LRA l=ID { add pc 2; [Lra (Lab l)] } | LA r=REG l=ID { li false r (Lab l) } | LIL r=REG i=int { add pc 2; [Lil (r,Imm i)] } | LILZ r=REG i=int { add pc 2; [Lilz (r,Imm i)] } | LIU r=REG i=int { add pc 2; [Liu (r,Imm i)] } | LIUZ r=REG i=int { add pc 2; [Liuz (r,Imm i)] } | MOVE r1=REG r2=REG { add pc 2; [R (Add,r1,r2,0)] } | NOT r1=REG r2=REG { add pc 2; [R (Nor,r1,r2,0)] } | JZ r=REG l=ID { let l = li false 5 (Lab l) in add pc 2; l @ [R (Jer,5,r,0)] } | JNZ r=REG l=ID { let l = li false 5 (Lab l) in add pc 2; l @ [R (Jner,5,r,0)] } | POP r=REG { add pc 4; [Lw (r,7,0); Incri (7,2)] } | PUSH r=REG { add pc 4; [Incri (7,-2); Sw (r,7,0)] } | ASCIIZ s=STR { let bytes = List.map Char.code (explode s) @ [0] in let rec pair = function | a::b::q -> (a, b)::(pair q) | [a] -> [(a, 0)] | [] -> [] in let words = pair bytes in add pc (List.length bytes); List.map (fun (a, b) -> TwoRawBytes (a, b)) words } imm: | id=ID { Lab id } | n=int { Imm n } int: | n=INT { n } | MINUS n=INT { - n }