summaryrefslogblamecommitdiff
path: root/asm/asmpars.mly
blob: 46ca7a734fbbe86135b7e03399997e036ff8369d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  















                         
                 




                              







                                                                                                            
                                                                   
    




                                                     

  

                                                                                    



                          
                  





                           




                                                                
     

                     
      
                              


                                                                    





                                                                
      
                              


                        






































































                                                             
    

                    

    

                       
%{
  open Asm
  
  let unsigned = function
    | Addu
    | Subu
    | Mulu
    | Divu
    | Sltu
    | Sleu
    | Jltru
    | Jleru
      -> true
    | _ -> false
      
  let pc = ref 0
  
  let ram = ref 0
  
  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,Lab id)]
    

  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<Asm.reg> REG
%token<Asm.fmt_r> ROP,RIOP
%token<string> ID
%token<int> INT
%token<string> STR

%start<Asm.program> 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:
	| labeld 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 }
	
labeli:
	id=ID COLON { lbls2 := Imap.add id (!pc,true) !lbls2 }

labeld:
	id=ID COLON { lbls2 := Imap.add id (!ram,false) !lbls2 }

instr:
	| labeli 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 }