@@ -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
@@ -170,7 +177,7 @@ Definition parse_OpPrefix : ParserAction OpPrefix
170
177
:= parse_strs parse_OpPrefix_list.
171
178
172
179
(** assumes no leading nor trailing whitespace and no comment *)
173
- Definition parse_RawLine : ParserAction RawLine
180
+ Definition parse_RawLine {opts : assembly_program_options} : ParserAction RawLine
174
181
:= fun s => (
175
182
let s := String.trim s in
176
183
(* get the first space-separated opcode *)
@@ -225,7 +232,7 @@ Definition parse_RawLine : ParserAction RawLine
225
232
parsed_prefix
226
233
end )%bool.
227
234
228
- Definition parse_Line (line_num : N) : ParserAction Line
235
+ Definition parse_Line {opts : assembly_program_options} (line_num : N) : ParserAction Line
229
236
:= fun s
230
237
=> let '(indentv, rest_linev) := take_while_drop_while Ascii.is_whitespace s in
231
238
let '(precommentv, commentv)
@@ -242,22 +249,35 @@ Definition parse_Line (line_num : N) : ParserAction Line
242
249
(parse_RawLine rawlinev).
243
250
244
251
(* the error is the unparsable lines *)
245
- Fixpoint parse_Lines' (l : list string) (line_num : N) : ErrorT (list string) Lines
252
+ Fixpoint parse_Lines' {opts : assembly_program_options} (l : list string) (line_num : N) : ErrorT (list string) Lines
246
253
:= match l with
247
254
| [] => Success []
248
255
| l :: ls
249
- => match finalize (parse_Line line_num) l, parse_Lines' ls (line_num + 1) with
256
+ => let '(result, next_opts) :=
257
+ match finalize (@parse_Line opts line_num) l with
258
+ | None => (None, opts)
259
+ | Some result =>
260
+ (Some result,
261
+ match result.(rawline) with
262
+ | DEFAULT_REL => {| default_rel := true |}
263
+ | _ => opts
264
+ end )
265
+ end in
266
+ match result, @parse_Lines' next_opts ls (line_num + 1) with
250
267
| None, Error ls => Error (("Line " ++ show line_num ++ ": " ++ l) :: ls)
251
268
| None, Success _ => Error (("Line " ++ show line_num ++ ": " ++ l) :: nil)
252
269
| Some _, Error ls => Error ls
253
270
| Some l, Success ls => Success (l :: ls)
254
271
end
255
272
end .
256
273
257
- Definition parse_Lines (l : list string) : ErrorT (list string) Lines
274
+ Definition parse_Lines {opts : assembly_program_options} (l : list string) : ErrorT (list string) Lines
258
275
:= parse_Lines' (String.split_newlines l) 1.
259
276
260
- Notation parse := parse_Lines (only parsing).
277
+ #[export] Instance default_assembly_program_options : assembly_program_options
278
+ := {| default_rel := false |}.
279
+
280
+ Notation parse := (@parse_Lines default_assembly_program_options) (only parsing).
261
281
262
282
Global Instance show_lvl_MEM : ShowLevel MEM
263
283
:= fun m
@@ -274,11 +294,19 @@ Global Instance show_lvl_MEM : ShowLevel MEM
274
294
| None => show_lvl
275
295
end )
276
296
(fun 'tt
277
- => let reg_part
278
- := (match m.(mem_base_reg), m.(mem_scale_reg) with
279
- | (*"[Reg]" *) Some br, None => show_REG br
280
- | (*"[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. *)
281
- | (*"[ Z * Reg]" *) None, Some (z, sr) => Decimal.show_Z z ++ " * " ++ show_REG sr
297
+ => let is_explict_rip_relative := match m.(rip_relative) with explicitly_rip_relative => true | _ => false end in
298
+ let base_reg_str :=
299
+ match is_explict_rip_relative, m.(mem_base_reg) with
300
+ | false, Some br => Some (show_REG br)
301
+ | false, None => None
302
+ | true, None => Some "rip"
303
+ | true, Some br => Some ("rip + " ++ show_REG br) (* but this should not happen *)
304
+ end in
305
+ let reg_part
306
+ := (match base_reg_str, m.(mem_scale_reg) with
307
+ | (*"[Reg]" *) Some br, None => br
308
+ | (*"[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. *)
309
+ | (*"[ Z * Reg]" *) None, Some (z, sr) => Decimal.show_Z z ++ " * " ++ show_REG sr
282
310
| (*"[ ]" *) None, None => "" (* impossible, because only offset is invalid, but we seem to need it for coq because both are option's *)
283
311
end %Z) in
284
312
let offset_part
@@ -291,8 +319,8 @@ Global Instance show_lvl_MEM : ShowLevel MEM
291
319
then "0x08 * " ++ Decimal.show_Z (offset / 8)
292
320
else Hex.show_Z offset)
293
321
end %Z) in
294
- match m.(mem_base_label), m.(mem_base_reg) , m.(mem_offset), m.(mem_scale_reg) with
295
- | Some lbl, Some rip , None, None => lbl ++ "[" ++ reg_part ++ offset_part ++ "]"
322
+ match m.(mem_base_label), is_explict_rip_relative , m.(mem_offset), m.(mem_scale_reg) with
323
+ | Some lbl, true , None, None => lbl ++ "[" ++ reg_part ++ offset_part ++ "]"
296
324
| Some lbl, _, _, _ => let l_offset := lbl ++ offset_part in
297
325
"[" ++
298
326
(if reg_part =? ""
@@ -603,9 +631,9 @@ Definition get_labeled_data (ls : Lines) : list (string * list (AccessSize * lis
603
631
let labeled_data := List.filter (fun '(_, data) => match data with nil => false | _ => true end ) labeled_data in
604
632
labeled_data.
605
633
606
- Definition parse_assembly_options (ls : Lines) : assembly_program_options
634
+ (* Definition parse_assembly_options (ls : Lines) : assembly_program_options
607
635
:= {| default_rel := Option.is_Some (List.find (fun l => match l.(rawline) with
608
636
| DEFAULT_REL => true
609
637
| _ => false
610
638
end) ls)
611
- |}.
639
+ |}. *)
0 commit comments