1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
|
%{
(****************************************************************************)
(* the diy toolsuite *)
(* *)
(* Jade Alglave, University College London, UK. *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France. *)
(* *)
(* Copyright 2010-present Institut National de Recherche en Informatique et *)
(* en Automatique and the authors. All rights reserved. *)
(* *)
(* This software is governed by the CeCILL-B license under French law and *)
(* abiding by the rules of distribution of free software. You can use, *)
(* modify and/ or redistribute the software under the terms of the CeCILL-B *)
(* license as circulated by CEA, CNRS and INRIA at the following URL *)
(* "http://www.cecill.info". We also give a copy in LICENSE.txt. *)
(****************************************************************************)
module A = ARMBase
%}
%token EOF
%token <ARMBase.reg> ARCH_REG
%token <string> SYMB_REG
%token <int> NUM
%token <string> NAME
%token <string> META
%token <string> CODEVAR
%token <int> PROC
%token SEMI COMMA PIPE COLON LBRK RBRK LPAREN RPAREN
/* Instruction tokens */
%token I_ADD I_ADDS I_BX I_SUB I_SUBS I_AND I_ORR I_ANDS I_ANDEQ I_B I_BEQ I_BNE I_CMP I_MOV I_MOVW I_MOVT I_MOVNE I_MOVEQ I_XOR I_XORS I_DMB I_DSB I_ISB I_CBZ I_CBNZ
%token I_LDR I_LDREX I_LDRNE I_LDREQ I_LDRD I_LDM I_LDMIB I_STR I_STRNE I_STREQ I_STREX I_LDA I_STL I_LDAEX I_STLEX I_PUSH I_POP I_MOVWEQ I_MOVTEQ
%token I_SY I_ST I_ISH I_ISHST I_NSH I_NSHST I_OSH I_OSHST
%token S_LSL
%type <MiscParser.proc list * (ARMBase.parsedPseudo) list list> main
%start main
%type <ARMBase.parsedPseudo list> instr_option_seq
%start instr_option_seq
%%
main:
| semi_opt proc_list iol_list EOF { $2,$3 }
semi_opt:
| { () }
| SEMI { () }
proc_list:
| ps=separated_nonempty_list(PIPE,PROC) SEMI
{ List.map (fun p -> p,None,MiscParser.Main) ps }
iol_list :
| instr_option_list SEMI
{[$1]}
| instr_option_list SEMI iol_list {$1::$3}
instr_option_list :
| instr_option
{[$1]}
| instr_option PIPE instr_option_list
{$1::$3}
instr_option_seq:
| separated_nonempty_list(SEMI,instr_option) EOF { $1 }
instr_option :
| { A.Nop }
| NAME COLON instr_option { A.Label ($1,$3) }
| CODEVAR { A.Symbolic $1 }
| instr { A.Instruction $1}
reg:
| SYMB_REG { A.Symbolic_reg $1 }
| ARCH_REG { $1 }
k:
| NUM { MetaConst.Int $1 }
| META { MetaConst.Meta $1 }
shift:
| COMMA S_LSL k { A.S_LSL $3 }
instr:
| I_ADD reg COMMA reg COMMA k
{ A.I_ADD (A.DontSetFlags,$2,$4,$6) }
| I_ADDS reg COMMA reg COMMA k
{ A.I_ADD (A.SetFlags,$2,$4,$6) }
| I_ADD reg COMMA reg COMMA reg
{ A.I_ADD3 (A.DontSetFlags,$2, $4, $6) }
| I_ADDS reg COMMA reg COMMA reg
{ A.I_ADD3 (A.SetFlags,$2, $4, $6) }
| I_BX reg
{ A.I_BX $2 }
| I_SUB reg COMMA reg COMMA k
{ A.I_SUB (A.DontSetFlags,$2,$4,$6) }
| I_SUBS reg COMMA reg COMMA k
{ A.I_SUB (A.SetFlags,$2,$4,$6) }
| I_SUB reg COMMA reg COMMA reg
{ A.I_SUB3 (A.DontSetFlags,$2, $4, $6) }
| I_SUBS reg COMMA reg COMMA reg
{ A.I_SUB3 (A.SetFlags,$2, $4, $6) }
| I_AND reg COMMA reg COMMA k
{ A.I_AND (A.DontSetFlags,$2,$4,$6) }
| I_ORR reg COMMA reg COMMA k
{ A.I_ORR (A.DontSetFlags,$2,$4,$6) }
| I_ANDS reg COMMA reg COMMA k
{ A.I_AND (A.SetFlags,$2,$4,$6) }
| I_ANDEQ reg COMMA reg COMMA reg
{ (* This is historically used as a NOP when regs are the same*)
if $2 = $4 && $4 = $6 then A.I_NOP else A.I_ANDC (A.EQ,$2,$4,$6) }
| I_B NAME
{ A.I_B $2 }
| I_BNE NAME
{ A.I_BNE $2 }
| I_BEQ NAME
{ A.I_BEQ $2 }
| I_CBZ reg COMMA NAME
{ A.I_CB (false,$2,$4) }
| I_CBNZ reg COMMA NAME
{ A.I_CB (true,$2,$4) }
| I_CMP reg COMMA k
{ A.I_CMPI ($2,$4) }
| I_CMP reg COMMA reg
{ A.I_CMP ($2,$4) }
/* Load */
| I_LDR reg COMMA reg
{ A.I_LDR ($2,$4, A.AL) }
| I_LDR reg COMMA LBRK reg RBRK
{ A.I_LDR ($2,$5,A.AL) }
| I_LDR reg COMMA LBRK reg COMMA reg RBRK
{ A.I_LDR3 ($2,$5,$7,A.AL) }
| I_LDR reg COMMA LBRK reg COMMA reg shift RBRK
{ A.I_LDR3_S ($2,$5,$7,$8,A.AL) }
| I_LDR reg COMMA LBRK reg COMMA k RBRK
{ A.I_LDRO ($2,$5,$7,A.AL) }
| I_LDRNE reg COMMA reg
{ A.I_LDR ($2,$4,A.NE) }
| I_LDRNE reg COMMA LBRK reg RBRK
{ A.I_LDR ($2,$5,A.NE) }
| I_LDRNE reg COMMA LBRK reg COMMA reg RBRK
{ A.I_LDR3 ($2,$5,$7,A.NE) }
| I_LDREQ reg COMMA reg
{ A.I_LDR ($2,$4,A.EQ) }
| I_LDREQ reg COMMA LBRK reg RBRK
{ A.I_LDR ($2,$5,A.EQ) }
| I_LDREQ reg COMMA LBRK reg COMMA reg RBRK
{ A.I_LDR3 ($2,$5,$7,A.EQ) }
| I_LDREX reg COMMA reg
{ A.I_LDREX ($2,$4) }
| I_LDREX reg COMMA LBRK reg RBRK
{ A.I_LDREX ($2,$5) }
| I_LDAEX reg COMMA LBRK reg RBRK
{ A.I_LDAEX ($2,$5) }
| I_LDA reg COMMA LBRK reg RBRK
{ A.I_LDA ($2, $5)}
(* 2-reg and 3-reg variants of LDM for now *)
| I_LDM reg COMMA LPAREN reg COMMA reg RPAREN
{ A.I_LDM2 ($2, $5, $7, A.NO) }
| I_LDMIB reg COMMA LPAREN reg COMMA reg RPAREN
{ A.I_LDM2 ($2, $5, $7, A.IB) }
| I_LDM reg COMMA LPAREN reg COMMA reg COMMA reg RPAREN
{ A.I_LDM3 ($2, $5, $7, $9, A.NO) }
| I_PUSH LPAREN reg RPAREN
{ A.I_NOP }
| I_PUSH LPAREN reg COMMA reg RPAREN
{ A.I_NOP }
| I_POP LPAREN reg COMMA reg RPAREN
{ A.I_NOP }
| I_POP LPAREN reg RPAREN
{ A.I_NOP }
(* LDRD syntax comes in two forms - LDRD Rd1, Rd2, [Ra] and *)
(* LDRD Rd1, [Ra] - in both cases LDRD requires Rd2 is Rd(1+1) *)
(* so the second register can be and is omitted e.g by GCC-10*)
| I_LDRD reg COMMA reg COMMA LBRK reg RBRK
{ A.I_LDRD ($2,$4,$7,None) }
| I_LDRD reg COMMA LBRK reg RBRK
{ A.I_LDRD ($2,A.next_reg $2,$5,None) }
| I_LDRD reg COMMA reg COMMA LBRK reg COMMA k RBRK
{ A.I_LDRD ($2,$4,$7,Some $9) }
| I_LDRD reg COMMA LBRK reg COMMA k RBRK
{ A.I_LDRD ($2,A.next_reg $2,$5,Some $7) }
/* Store */
| I_STR reg COMMA reg
{ A.I_STR ($2,$4,A.AL) }
| I_STR reg COMMA LBRK reg RBRK
{ A.I_STR ($2,$5,A.AL) }
| I_STR reg COMMA LBRK reg COMMA reg RBRK
{ A.I_STR3 ($2,$5,$7,A.AL) }
| I_STR reg COMMA LBRK reg COMMA reg shift RBRK
{ A.I_STR3_S ($2,$5,$7,$8,A.AL) }
| I_STRNE reg COMMA reg
{ A.I_STR ($2,$4,A.NE) }
| I_STRNE reg COMMA LBRK reg RBRK
{ A.I_STR ($2,$5,A.NE) }
| I_STRNE reg COMMA LBRK reg COMMA reg RBRK
{ A.I_STR3 ($2,$5,$7,A.NE) }
| I_STREQ reg COMMA reg
{ A.I_STR ($2,$4,A.EQ) }
| I_STREQ reg COMMA LBRK reg RBRK
{ A.I_STR ($2,$5,A.EQ) }
| I_STREQ reg COMMA LBRK reg COMMA reg RBRK
{ A.I_STR3 ($2,$5,$7,A.EQ) }
| I_STREX reg COMMA reg COMMA LBRK reg RBRK
{ A.I_STREX ($2,$4,$7,A.AL) }
| I_STL reg COMMA LBRK reg RBRK
{ A.I_STL ($2, $5,A.AL) }
| I_STLEX reg COMMA reg COMMA LBRK reg RBRK
{ A.I_STLEX ($2,$4,$7) }
/* MOVE */
| I_MOV reg COMMA k
{ A.I_MOVI ($2,$4,A.AL) }
| I_MOVNE reg COMMA k
{ A.I_MOVI ($2,$4,A.NE) }
| I_MOVEQ reg COMMA k
{ A.I_MOVI ($2,$4,A.EQ) }
| I_MOV reg COMMA reg
{ A.I_MOV ($2,$4,A.AL) }
| I_MOVNE reg COMMA reg
{ A.I_MOV ($2,$4,A.NE) }
| I_MOVEQ reg COMMA reg
{ A.I_MOV ($2,$4,A.EQ) }
| I_MOVW reg COMMA k
{ A.I_MOVW ($2,$4,A.AL)}
| I_MOVWEQ reg COMMA k
{ A.I_MOVW ($2,$4,A.EQ) }
| I_MOVT reg COMMA k
{ A.I_MOVT ($2,$4,A.AL)}
| I_MOVTEQ reg COMMA k
{ A.I_MOVT ($2,$4,A.EQ)}
| I_XOR reg COMMA reg COMMA reg
{ A.I_XOR (A.DontSetFlags,$2,$4,$6) }
| I_XORS reg COMMA reg COMMA reg
{ A.I_XOR (A.SetFlags,$2,$4,$6) }
/* FENCES */
| I_DMB { A.I_DMB A.SY }
| I_DSB opt { A.I_DSB $2 }
| I_DMB opt { A.I_DMB $2 }
| I_DSB { A.I_DSB A.SY }
| I_ISB { A.I_ISB }
opt:
| I_SY { A.SY }
| I_ST { A.ST }
| I_ISH { A.ISH }
| I_ISHST { A.ISHST }
| I_NSH { A.NSH }
| I_NSHST { A.NSHST }
| I_OSH { A.OSH }
| I_OSHST { A.OSHST }
|