@@ -80,12 +80,16 @@ Definition parse_label : ParserAction string
80
80
(fun '(char, ls) => string_of_list_ascii (char :: ls))
81
81
(([a-zA-Z] || parse_any_ascii "._?$") ;;
82
82
(([a-zA-Z] || parse_any_ascii "0123456789_$#@~.?")* )).
83
+
83
84
Definition parse_non_access_size_label : ParserAction string
84
- := parse_lookahead_not parse_AccessSize ;;R parse_label.
85
+ := parse_lookahead_not parse_AccessSize ;;R parse_label.
86
+
87
+ Definition parse_rip_relative_kind : ParserAction rip_relative_kind
88
+ := parse_map (fun _ => explicitly_rip_relative) "rip".
85
89
86
- Definition parse_MEM : ParserAction MEM
90
+ Definition parse_MEM {opts : assembly_program_options} : ParserAction MEM
87
91
:= parse_option_list_map
88
- (fun '(access_size, (constant_location_label, (br (*base reg *) , sr (*scale reg, including z *) , offset, base_label)))
92
+ (fun '(access_size, (constant_location_label, (br (*base reg *) , sr (*scale reg, including z *) , offset, base_label, rip_relative )))
89
93
=> match base_label, constant_location_label with
90
94
| Some _, Some _ => (* invalid? *) None
91
95
| Some _ as lbl, None
@@ -96,14 +100,15 @@ Definition parse_MEM : ParserAction MEM
96
100
; mem_base_reg := br:option REG
97
101
; mem_base_label := lbl
98
102
; mem_scale_reg := sr:option (Z * REG)
99
- ; mem_offset := offset:option Z |}
103
+ ; mem_offset := offset:option Z
104
+ ; rip_relative := rip_relative:rip_relative_kind |}
100
105
end )
101
106
(((strip_whitespace_after parse_AccessSize)?) ;;
102
107
(parse_non_access_size_label?) ;;
103
108
(parse_option_list_map
104
109
(fun '(offset, vars)
105
110
=> (vars <-- List.map (fun '(c, (v, e), vs) => match vs, e with [], 1%Z => Some (c, v) | _, _ => None end ) vars;
106
- let regs : list (Z * REG) := Option.List.map (fun '(c, v) => match v with inl v => Some (c, v) | inr _ => None end ) vars in
111
+ let regs : list (Z * ( REG + rip_relative_kind) ) := Option.List.map (fun '(c, v) => match v with inl v => Some (c, v) | inr _ => None end ) vars in
107
112
let labels : list (Z * string) := Option.List.map (fun '(c, v) => match v with inr v => Some (c, v) | inl _ => None end ) vars in
108
113
base_label <- match labels with
109
114
| [] => Some None
@@ -114,15 +119,17 @@ Definition parse_MEM : ParserAction MEM
114
119
base_scale_reg <- match regs with
115
120
| [] => Some (None, None)
116
121
| [(1%Z, r)] => Some (Some r, None)
117
- | [(s, r)] => Some (None, Some (s, r))
118
- | [(1%Z, r1); (s, r2)]
119
- | [(s, r2); (1%Z, r1)]
122
+ | [(s, inl r)] => Some (None, Some (s, r))
123
+ | [(1%Z, r1); (s, inl r2)]
124
+ | [(s, inl r2); (1%Z, r1)]
120
125
=> Some (Some r1, Some (s, r2))
121
126
| _ => None
122
127
end ;
123
128
let '(br, sr) := base_scale_reg in
124
- Some (br (*base reg *) , sr (*scale reg, including z *) , offset, base_label))%option)
125
- ("[" ;;R parse_Z_poly_strict (sum_beq _ _ REG_beq String.eqb) (parse_or_else_gen (fun x => x) parse_REG parse_label) ;;L "]"))).
129
+ let rip_relative := match br with Some (inr k) => k | _ => if default_rel then implicitly_rip_relative else not_rip_relative end in
130
+ let br := (br <- br; match br with inl br => Some br | inr _ => None end )%option in
131
+ Some (br (*base reg *) , sr (*scale reg, including z *) , offset, base_label, rip_relative))%option)
132
+ ("[" ;;R parse_Z_poly_strict (sum_beq _ _ (sum_beq _ _ REG_beq rip_relative_kind_beq) String.eqb) (parse_or_else_gen (fun x => x) (parse_or_else_gen (fun x => x) parse_REG parse_rip_relative_kind) parse_label) ;;L "]"))).
126
133
127
134
Definition parse_CONST (const_keyword : bool) : ParserAction CONST
128
135
:= if const_keyword
@@ -138,7 +145,7 @@ Definition parse_JUMP_LABEL : ParserAction JUMP_LABEL
138
145
((strip_whitespace_after "NEAR ")? ;; parse_label).
139
146
140
147
(* we only parse something as a label if it cannot possibly be anything else, because asm is terrible and has ambiguous parses otherwise :-( *)
141
- Definition parse_ARG (const_keyword : bool) : ParserAction ARG
148
+ Definition parse_ARG {opts : assembly_program_options} (const_keyword : bool) : ParserAction ARG
142
149
:= parse_or_else
143
150
(parse_alt_list
144
151
[parse_map reg parse_REG
@@ -165,7 +172,7 @@ Definition parse_OpPrefix : ParserAction OpPrefix
165
172
:= parse_strs parse_OpPrefix_list.
166
173
167
174
(** assumes no leading nor trailing whitespace and no comment *)
168
- Definition parse_RawLine : ParserAction RawLine
175
+ Definition parse_RawLine {opts : assembly_program_options} : ParserAction RawLine
169
176
:= fun s
170
177
=> let s := String.trim s in
171
178
(* get the first space-separated opcode *)
@@ -206,7 +213,7 @@ Definition parse_RawLine : ParserAction RawLine
206
213
parsed_prefix
207
214
end .
208
215
209
- Definition parse_Line (line_num : N) : ParserAction Line
216
+ Definition parse_Line {opts : assembly_program_options} (line_num : N) : ParserAction Line
210
217
:= fun s
211
218
=> let '(indentv, rest_linev) := take_while_drop_while Ascii.is_whitespace s in
212
219
let '(precommentv, commentv)
@@ -223,22 +230,35 @@ Definition parse_Line (line_num : N) : ParserAction Line
223
230
(parse_RawLine rawlinev).
224
231
225
232
(* the error is the unparsable lines *)
226
- Fixpoint parse_Lines' (l : list string) (line_num : N) : ErrorT (list string) Lines
233
+ Fixpoint parse_Lines' {opts : assembly_program_options} (l : list string) (line_num : N) : ErrorT (list string) Lines
227
234
:= match l with
228
235
| [] => Success []
229
236
| l :: ls
230
- => match finalize (parse_Line line_num) l, parse_Lines' ls (line_num + 1) with
237
+ => let '(result, next_opts) :=
238
+ match finalize (@parse_Line opts line_num) l with
239
+ | None => (None, opts)
240
+ | Some result =>
241
+ (Some result,
242
+ match result.(rawline) with
243
+ | DEFAULT_REL => {| default_rel := true |}
244
+ | _ => opts
245
+ end )
246
+ end in
247
+ match result, @parse_Lines' next_opts ls (line_num + 1) with
231
248
| None, Error ls => Error (("Line " ++ show line_num ++ ": " ++ l) :: ls)
232
249
| None, Success _ => Error (("Line " ++ show line_num ++ ": " ++ l) :: nil)
233
250
| Some _, Error ls => Error ls
234
251
| Some l, Success ls => Success (l :: ls)
235
252
end
236
253
end .
237
254
238
- Definition parse_Lines (l : list string) : ErrorT (list string) Lines
255
+ Definition parse_Lines {opts : assembly_program_options} (l : list string) : ErrorT (list string) Lines
239
256
:= parse_Lines' (String.split_newlines l) 1.
240
257
241
- Notation parse := parse_Lines (only parsing).
258
+ #[export] Instance default_assembly_program_options : assembly_program_options
259
+ := {| default_rel := false |}.
260
+
261
+ Notation parse := (@parse_Lines default_assembly_program_options) (only parsing).
242
262
243
263
Global Instance show_lvl_MEM : ShowLevel MEM
244
264
:= fun m
@@ -248,11 +268,19 @@ Global Instance show_lvl_MEM : ShowLevel MEM
248
268
| None => show_lvl
249
269
end )
250
270
(fun 'tt
251
- => let reg_part
252
- := (match m.(mem_base_reg), m.(mem_scale_reg) with
253
- | (*"[Reg]" *) Some br, None => show_REG br
254
- | (*"[Reg + Z * Reg]" *) Some br, Some (z, sr) => show_REG br ++ " + " ++ Decimal.show_Z z ++ " * " ++ show_REG sr (*only matching '+' here, because there cannot be a negative scale. *)
255
- | (*"[ Z * Reg]" *) None, Some (z, sr) => Decimal.show_Z z ++ " * " ++ show_REG sr
271
+ => let is_explict_rip_relative := match m.(rip_relative) with explicitly_rip_relative => true | _ => false end in
272
+ let base_reg_str :=
273
+ match is_explict_rip_relative, m.(mem_base_reg) with
274
+ | false, Some br => Some (show_REG br)
275
+ | false, None => None
276
+ | true, None => Some "rip"
277
+ | true, Some br => Some ("rip + " ++ show_REG br) (* but this should not happen *)
278
+ end in
279
+ let reg_part
280
+ := (match base_reg_str, m.(mem_scale_reg) with
281
+ | (*"[Reg]" *) Some br, None => br
282
+ | (*"[Reg + Z * Reg]" *) Some br, Some (z, sr) => br ++ " + " ++ Decimal.show_Z z ++ " * " ++ show_REG sr (*only matching '+' here, because there cannot be a negative scale. *)
283
+ | (*"[ Z * Reg]" *) None, Some (z, sr) => Decimal.show_Z z ++ " * " ++ show_REG sr
256
284
| (*"[ ]" *) None, None => "" (* impossible, because only offset is invalid, but we seem to need it for coq because both are option's *)
257
285
end %Z) in
258
286
let offset_part
@@ -265,8 +293,8 @@ Global Instance show_lvl_MEM : ShowLevel MEM
265
293
then "0x08 * " ++ Decimal.show_Z (offset / 8)
266
294
else Hex.show_Z offset)
267
295
end %Z) in
268
- match m.(mem_base_label), m.(mem_base_reg) , m.(mem_offset), m.(mem_scale_reg) with
269
- | Some lbl, Some rip , None, None => lbl ++ "[" ++ reg_part ++ offset_part ++ "]"
296
+ match m.(mem_base_label), is_explict_rip_relative , m.(mem_offset), m.(mem_scale_reg) with
297
+ | Some lbl, true , None, None => lbl ++ "[" ++ reg_part ++ offset_part ++ "]"
270
298
| Some lbl, _, _, _ => let l_offset := lbl ++ offset_part in
271
299
"[" ++
272
300
(if reg_part =? ""
@@ -575,9 +603,9 @@ Definition get_labeled_data (ls : Lines) : list (string * list (AccessSize * lis
575
603
let labeled_data := List.filter (fun '(_, data) => match data with nil => false | _ => true end ) labeled_data in
576
604
labeled_data.
577
605
578
- Definition parse_assembly_options (ls : Lines) : assembly_program_options
606
+ (* Definition parse_assembly_options (ls : Lines) : assembly_program_options
579
607
:= {| default_rel := Option.is_Some (List.find (fun l => match l.(rawline) with
580
608
| DEFAULT_REL => true
581
609
| _ => false
582
610
end) ls)
583
- |}.
611
+ |}. *)
0 commit comments