summaryrefslogtreecommitdiff
path: root/asm/asmpars.mly
diff options
context:
space:
mode:
Diffstat (limited to 'asm/asmpars.mly')
-rw-r--r--asm/asmpars.mly163
1 files changed, 163 insertions, 0 deletions
diff --git a/asm/asmpars.mly b/asm/asmpars.mly
new file mode 100644
index 0000000..ebc4ae7
--- /dev/null
+++ b/asm/asmpars.mly
@@ -0,0 +1,163 @@
+%{
+ 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<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:
+ | 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 }