[m-rev.] for review: x86-64 instructions and output files
Fransiska Nathania HANDOKO
fhandoko at students.csse.unimelb.edu.au
Mon Jan 15 14:01:59 AEDT 2007
Estimated hours taken: 50
Branches: main
Create a file to represent x86_64 instruction sets and another file to
print the instructions out for the needs to compile LLDS to x86_64.
compiler/x86_64_instrs.m:
Defines x86_64 instructions using AT&T syntax.
compiler/x86_64_out.m:
Printing out x86_64 instructions.
Index: compiler/ll_backend.m
===================================================================
RCS file:
/home/mercury/mercury1/repository/mercury/compiler/ll_backend.m,v
retrieving revision 1.17
diff -u -r1.17 ll_backend.m
--- compiler/ll_backend.m 27 Jul 2006 05:01:10 -0000 1.17
+++ compiler/ll_backend.m 8 Jan 2007 03:15:58 -0000
@@ -92,6 +92,10 @@
:- include_module layout_out.
:- include_module rtti_out.
+% The LLDS->x86_64 asm phase.
+:- include_module x86_64_instrs.
+:- include_module x86_64_out.
+
:- implementation.
:- import_module check_hlds. % needed for type_util, mode_util etc
Index: compiler/mercury_compile.m
===================================================================
RCS file:
/home/mercury/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.423
diff -u -r1.423 mercury_compile.m
--- compiler/mercury_compile.m 10 Jan 2007 02:49:21 -0000
1.423
+++ compiler/mercury_compile.m 12 Jan 2007 04:26:08 -0000
@@ -3651,7 +3651,7 @@
maybe_tuple_arguments(Verbose, Stats, !HLDS, !IO) :-
module_info_get_globals(!.HLDS, Globals),
- globals.lookup_bool_option(Globals, tuple, Tuple),
+ globals.lookup_bool_option(Globals, untuple, Tuple),
(
Tuple = yes,
maybe_write_string(Verbose, "% Tupling...\n", !IO),
Index: compiler/x86_64_instrs.m
===================================================================
RCS file: compiler/x86_64_instrs.m
diff -N compiler/x86_64_instrs.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ compiler/x86_64_instrs.m 12 Jan 2007 04:29:30 -0000
@@ -0,0 +1,1629 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2007 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: x86_64_instrs.m.
+% Main author: fhandoko.
+%
+% This module contains the representations of the x86_64 instructions.
+%
+%-----------------------------------------------------------------------------%
+
+:- module ll_backend.x86_64_instrs.
+:- interface.
+
+:- import_module list.
+:- import_module maybe.
+
+%-----------------------------------------------------------------------------%
+
+:- type x86_64_instruction
+ ---> x86_64_instr(
+ x86_64_instr_name :: x86_64_op,
+ x86_64_comment :: string
+ ).
+
+:- type label_name == string.
+
+:- type x86_64_instr
+ ---> comment(string)
+ ; label(label_name)
+ ; directives(list(pseudo_op))
+ ; instrs(list(x86_64_instruction)).
+
+%-----------------------------------------------------------------------------%
+
+ % Signed integers of various sizes.
+ %
+:- type int8 ---> int8(int). % In bottom 8 bits.
+:- type int16 ---> int16(int). % In bottom 16 bits.
+:- type int32 ---> int32(int). % in bottom 32 bits.
+
+ % Unsigned integers of various sizes.
+ %
+:- type uint8 ---> uint8(int). % In bottom 8 bits.
+:- type uint16 ---> uint16(int). % In bottom 16 bits.
+:- type uint32 ---> uint32(int). % In bottom 32 bits.
+
+
+%-----------------------------------------------------------------------------%
+%
+% x86_64 pseudo-ops.
+%
+
+ % Pseudo op for x86_64. Also called assembler directive.
+ %
+:- type pseudo_op
+ ---> abort
+ % stop the assembly immediately.
+
+ ; align(
+ align_bits :: int,
+ align_fill_value :: maybe(int),
+ align_skip_bytes :: maybe(int)
+ )
+ % Advance the location counter until it is a multiple of
+ % 'align_bits'. The second and third arguments are optional.
+ % 'align_fill_value': value to be stored in the padding bytes.
+ % 'align_skip_bytes': maximum number of bytes to be skipped.
+
+ ; ascii(
+ ascii_literals :: list(string)
+ )
+ % 'ascii_literals' contain zero or more string literals. Assembles
+ % each literal into consecutive addresses.
+
+ ; asciiz(
+ asciiz_literals :: list(string)
+ )
+ % Simiar to '.ascii', but each string is followed by a zero byte.
+
+ ; balign(
+ balign_bits :: int,
+ balign_fill_value :: maybe(int),
+ balign_skip_bytes :: maybe(int)
+ )
+ % Similar to 'align'.
+
+ ; byte(
+ byte_exprs :: list(string)
+ )
+ % 'byte_exprs' contains zero or more expressions. Each expression is
+ % assembled into the next byte.
+
+ ; comm(
+ comm_symbol :: string,
+ comm_length :: int,
+ comm_align :: maybe(int)
+ )
+ % Declare a common symbol 'comm_symbol'. Allocate 'comm_length'
+ % bytes if the symbol has not been defined.
+ % (optional) 'comm_align' is the desired alignment of the symbol.
+
+ ; data(
+ data_subsection :: maybe(int)
+ )
+ % Tells assembler to assemble the following statements onto the end
+ % of the data subsection numbered 'data_subsection'.
+
+ ; desc(
+ desc_symbol :: string,
+ desc_abs_expr :: string
+ )
+ % Set the descriptor of the symbol to the low 16 bits of
+ % 'desc_abs_expr'.
+
+ ; def(
+ def_name :: string
+ )
+ % Begin defining debugging information for a symbol 'def_name'.
+
+ ; dim
+ % Tell to include auxiliary debugging information in the symbol
+ % table.
+
+ ; double(
+ double_nums :: list(float)
+ )
+ % 'double_nums' contains zero or more floating point numbers.
+
+ ; eject
+ % Force a page break.
+
+ ; else_
+ % As in 'if-then-else' conditional expression.
+
+ ; elseif
+ % Shorthand for the beginning a new '.if' block.
+
+ ; end
+ % Mark the end of the assembly file.
+
+ ; endef
+ % End of a symbol definition begun with '.def'.
+
+ ; endfunc
+ % End of a function specified with '.func'.
+
+ ; endif
+ % End of a block of conditional code.
+
+ ; endm
+ % End of assembly macro.
+
+ ; equ(
+ equ_symbol :: string,
+ equ_expr :: string
+ )
+ % Set the value of 'equ_symbol' to 'equ_expr'.
+
+ ; equiv(
+ equiv_symbol :: string,
+ equiv_expr :: string
+ )
+ % Like '.equ' except that the assembler will signal an error
+ % if 'equiv_symbol' is already defined.
+
+ ; err
+ % Print an error message.
+
+ ; exitm
+ % Exit early from the current macro definition.
+
+ ; extern
+ % Ignored. '.extern' is accepted for compatibility only.
+
+ ; fail_(
+ fail_expr :: string
+ )
+ % Generate an error or a warning. If 'fail_expr' is 500 or more, it
+ % prints a warning message. Otherwise, it prints an error message.
+
+ ; file(
+ file_name :: string
+ )
+ % Start a new logical file.
+
+ ; fill(
+ fill_repeat :: int,
+ fill_size :: maybe(int),
+ fill_value :: maybe(int)
+ )
+ % Emits 'fill_repeat' copies of 'fill_size' byte. The contents of
+ % each 'fil_repeat' bytes is taken from an 8-byte number. The
+ % highest order 4 bytes are zero. The lowest order 4 bytes are
+ % 'fill_value'. The last 2 arguments are optional.
+
+ ; float(
+ float_nums :: list(float)
+ )
+ % 'float_nums' contains zero or more floating point numbers.
+
+ ; func_(
+ func_name :: string,
+ func_label :: string
+ )
+ % Emits debugging information to denote function 'func_name' and
+ % is ignored unless the file is assembled with debugging enabled.
+ % 'func_label' is the entry point of the function.
+
+ ; global(
+ global_symbol :: string
+ )
+ % makes the global_symbol' visible to other programs that are linked
+ % with it.
+
+ ; globl(
+ globl_symbol :: string
+ )
+ % makes the globl_symbol' visible to other programs that are linked
+
+ ; hidden(
+ hidden_name :: string
+ )
+ % Override the named symbol default visibility (which is set by
+ % their binding: local, global or weak).
+
+ ; hword(
+ hword_exprs :: list(string)
+ )
+ % 'hword_exprs' contains zero or more expressions and emit a 16-bit
+ % number for each. Synonym for '.short'.
+
+ ; ident
+ % To place tags in object files.
+
+ ; if_(
+ if_expr :: string
+ )
+ % Mark the beginning of a conditional section.
+
+ ; ifdef(
+ ifdef_symbol :: string
+ )
+ % Assemble the following section of code if 'ifdef_symbol' has been
+ % defined.
+
+ ; ifc(
+ ifc_string1 :: string,
+ ifc_string2 :: string
+ )
+ % Assemble the following section of code if the two strings are the
+ % same.
+
+ ; ifeq(
+ ifeq_expr :: string
+ )
+ % Assemble the following section of code if the argument is zero.
+
+ ; ifge(
+ ifge_expr :: string
+ )
+ % Assemble the following section of code if the argument is greater
+ % than equal to zero.
+
+ ; ifgt(
+ ifgt_expr :: string
+ )
+ % Assemble the following section of code if the argument is greater
+ % than zero.
+
+ ; ifle(
+ ifle_expr :: string
+ )
+ % Assemble the following section of code if the argument is less
+ % than equal to zero.
+
+ ; iflt(
+ iflt_expr :: string
+ )
+ % Assemble the following section of code if the argument is less
+ % than zero.
+
+ ; ifnc(
+ ifnc_string1 :: string,
+ ifnc_string2 :: string
+ )
+ % Assemble the following section of code if the two strings are not
+ % the same.
+
+ ; ifndef(
+ ifndef_symbol :: string
+ )
+ % Assemble the following section of code if 'ifndef_symbol' has not
+ % been defined.
+
+ ; ifnotdef(
+ ifnotdef_symbol :: string
+ )
+ % Synonym for ifndef.
+
+ ; ifne(
+ ifne_expr :: string
+ )
+ % Assemble the following section of code if the argument is not
+ % equal to zero.
+
+ ; ifnes(
+ ifnes_string1 :: string,
+ ifnes_string2 :: string
+ )
+ % Assemble the following section of code if the two strings are not
+ % the same.
+
+ ; include(
+ include_file :: string
+ )
+ % Include supporting 'include_file'.
+
+ ; int(
+ int_exprs :: list(string)
+ )
+ % 'int_exprs' contains zero or more expressions. For each
+ % expression, emit a number that, at run time, is the value of that
+ % expression.
+
+ ; internal(
+ internal_name :: string
+ )
+ % Like '.hidden' pseudo-op.
+
+ ; lcomm(
+ lcomm_symbol :: string,
+ lcomm_length :: int
+ )
+ % Reserve 'lcomm_length' bytes for a local common denoted by
+ % 'lcomm_symbol'.
+
+ ; line(
+ line_number :: int
+ )
+ % Change the logical line number.
+
+ ; list
+ % Control whether or not assembly listings are generated. This
+ % increments the internal counter.
+
+ ; long(
+ long_exprs :: list(string)
+ )
+ % Same as '.int'.
+
+ ; macro
+ % Define macro to generate assembly output.
+
+ ; nolist
+ % Control whether or not assembly listings are generated. It
+ % decrements an internal counter.
+
+ ; p2align(
+ p2align_pow_bit :: int,
+ p2align_fill_value :: maybe(int),
+ p2align_skip_bytes :: maybe(int)
+ )
+ % Advances the location counter until it is a multiple of
+ % 2 ^ ('p2align_pow_bit')
+ % p2align_fill_value: value to be stored in padding bytes.
+ % 'p2align_skip_bytes: maximum bytes to be skipped.
+
+ ; popsection
+ % Replace the current section (and subsection) with the top section
+ % (and subsection) on the section stack.
+
+ ; previous
+ % Swap the current section (and subsection) with most recently
+ % referenced secction (and subsection) prior to this one.
+
+ ; print(string)
+ % print string on the standard output.
+
+ ; protected(
+ protected_name :: string
+ )
+ % Like '.hidden' or '.internal'
+
+ ; psize(
+ psize_lines :: int,
+ psize_cols :: maybe(int)
+ )
+ % Declare the number of lines specified by 'psize_lines' and
+ % an optional number of columns specified by 'psize_cols'.
+
+ ; purgem(
+ purgem_name :: string
+ )
+ % Undefine the macro 'purgem_name' so that later uses of the string
+ % will not be expanded.
+
+ ; pushsection(
+ pushsection_name :: string,
+ pushsection_subsect :: int
+ )
+ % Push the current section (and subsection) onto the top of the
+ % section stack and then replace the current section and subsection
+ % with 'pushsection_name' and 'pushsection_subsect'.
+
+ ; quad(
+ quad_bignums :: list(string)
+ )
+ % 'quad_bignums' contains zero or more bignums. For each bignum, it
+ % emits an 8-byte-integer.
+
+ ; rept(
+ rept_count :: int
+ )
+ % Repeat the sequence of lines between the '.rept' directive and the
+ % next '.endr' directive 'rept_count' times.
+
+ ; sbttl(
+ sbttl_subheading :: string
+ )
+ % Use 'subttl_subheading' as the title (immediately after the title
+ % line).
+
+ ; scl(
+ scl_class :: string
+ )
+ % Set the storage-class value for a symbol.
+
+ ; section(
+ section_name :: string,
+ section_flags :: maybe(string),
+ section_type :: maybe(string),
+ section_entsize :: maybe(int)
+ )
+ % ELF section stack manipulation directive.
+
+ ; set(
+ set_symbol :: string,
+ set_expression :: string
+ )
+ % Set the value of 'set_symbol' to 'set_expression'
+
+ ; short(
+ short_exprs :: list(string)
+ )
+
+ ; single(
+ single_nums :: list(float)
+ )
+ % Has the same effect as '.float'.
+
+ ; size(
+ size_name :: string,
+ size_exprs :: string
+ )
+ % Set the size associated with symbol'size_name'. The size in bytes
+ % is computed from 'size_expr'.
+
+ ; skip(
+ skip_size :: int,
+ skip_value :: maybe(int)
+ )
+ % Emit 'skip_size' bytes, each of value 'skip_value' (optional).
+
+ ; sleb128(
+ sleb128_exprs :: list(string)
+ )
+ % Stand for "signed little endian base 128". It is a variable length
+ % representation of numbers used by the DWARF symbolic.
+
+ ; space(
+ space_size :: int,
+ space_fill :: maybe(int)
+ )
+ % Emit 'space_size' bytes, each of value 'space_fill'(optional).
+
+ ; string(
+ string_str :: list(string)
+ )
+ % Copy the characters in each string inside 'string_strs' to the
+ % object file.
+
+ ; struct(
+ struct_expr :: string
+ )
+ % Switch to the absolute section and set the section offset to
+ % 'struct_expr'.
+
+ ; subsection(
+ subsection_name :: string
+ )
+ % Replace the current subsection with 'subsection_name'.
+
+ ; symver(
+ symver_name :: string,
+ symver_alias :: string
+ )
+ % If 'symver_name' is defined within the file being assembled, it
+ % creates a symbol alias with the name 'symver_alias'
+
+ ; tag(
+ tag_struct_name :: string
+ )
+ % Include auxiliary debugging information in the symbol table.
+
+ ; text(
+ text_subsection :: maybe(int)
+ )
+ % Assemble the following statements onto the end of the text
+ % subsection numbered zero or 'text_subsection' (if present).
+
+ ; title(
+ title_heading :: string
+ )
+ % Use 'title_heading' as the title when generating assembly listing.
+
+ ; type_(
+ type_name :: string,
+ type_desc :: string
+ )
+ % Set the type of symbol'type_name' to be either a function or an
+ % object symbol.
+
+ ; uleb128(
+ uleb128_exprs :: list(string)
+ )
+ % Stands for "unsigned little endian base 128". It is a variable
+ % length representation of numbers used by the DWARF symbolic
+ % debugging format.
+
+ ; val(
+ val_addr :: string
+ )
+ % Record 'val_addr' as the value attribute of a symbol table entry.
+
+ ; version(
+ version_note :: string
+ )
+ % Create a '.note' section and places into it an ELF formatted note
+ % of type NT_VERSION>
+
+ ; weak(
+ weak_names :: list(string)
+ )
+ % Set the weak attribute on the list of symbol in 'weak_names'. If
+ % the symbol has not existed, it will be created.
+
+ ; word(
+ word_exprs :: list(string)
+ ).
+ % 'word_exprs' contains zero or more expressions.
+
+%-----------------------------------------------------------------------------%
+%
+% x86_64 registers.
+%
+
+ % 64-bit RFLAGS register holding various status flags and one control flag.
+ % Details on amd64-prog-man-vol1 manual p38.
+ %
+:- type flags_reg
+ ---> rflags(int).
+
+ % General purpose registers on the x86_64.
+ % Details on amd64-prog-man-vol1 manual p27.
+ %
+:- type gp_reg
+ ---> rax
+ ; rbx
+ ; rcx
+ ; rdx
+ ; rbp
+ ; rsi
+ ; rdi
+ ; rsp
+ ; r8
+ ; r9
+ ; r10
+ ; r11
+ ; r12
+ ; r13
+ ; r14
+ ; r15.
+
+ % 64-bit instruction pointer register on the x86_64. Instruction pointer
+ % RIP is used as a base register for relative addressing. x86_64
+ % instructions using RIP can be:
+ % rip_constant(%rip)
+ % rip_expr(%rip)
+ % Details on GNU assembler 'as' documentation in the section entitled
+ % "Machine Dependencies: i386-Dependent: i386-Memory".
+ %
+:- type instr_ptr
+ ---> rip_constant(
+ rip_byte_offset :: int32
+ )
+
+ ; rip_expr(
+ rip_expr :: string
+ ).
+
+%-----------------------------------------------------------------------------%
+%
+% Operands for x86_64 instructions.
+%
+
+ % Immediate operands for the x86_64 instruction.
+ %
+:- type imm_operand
+ ---> imm8(int8)
+ ; imm16(int16)
+ ; imm32(int32).
+
+ % Memory reference operands for the x86_64 instruction can be an absolute
+ % address (given as a displacement from the base address of a data segment)
+ % or an instruction-relative address.
+ % Details on amd64-prog-man-vol1 p19.
+ %
+:- type mem_ref
+ ---> mem_abs(
+ mem_abs_address :: base_address
+ )
+
+ ; mem_rip(
+ instr_rel_address :: instr_ptr
+ ).
+
+ % Base address can be relative to the content of a general-purpose register
+ % or relative value of an expression (such as arithmetic expression
+ % containing labels in data segment).
+ %
+:- type base_address
+ ---> base_reg(
+ base_offset :: int,
+ base_reg :: gp_reg
+ )
+
+ ; base_expr(
+ base_expr :: string
+ ).
+
+ % All operands for the x86_64 instructions.
+ %
+:- type operand
+ ---> operand_reg(gp_reg)
+ ; operand_imm(imm_operand)
+ ; operand_mem_ref(mem_ref).
+
+
+%
+% Subtypes of the operand type.
+% XXX maybe we should use inst-subtyping for these?
+%
+
+ % x86_64_instruction's operand is either the content a general-purpose
+ % register or the content of a memory reference.
+ %
+:- type reg_or_mem_ref_op
+ ---> rmro_reg(gp_reg)
+ ; rmro_mem_ref(mem_ref).
+
+ % x86_64_instruction's operand is either the contents of a general-purpose
+ % register or the value of an immediate operand.
+ %
+:- type reg_or_imm_op
+ ---> rio_reg(gp_reg)
+ ; rio_imm(imm_operand).
+
+ % x86_64_instruction's operand is either the content of CL register (the
+ % bottom 16 bits of RCX register) or an 8-bit immediate value.
+ %
+:- type cl_reg_or_imm_op
+ ---> crio_reg_cl(gp_reg)
+ ; crio_imm8(int8).
+
+ % x86_64 instruction's operand is an offset relative to the instruction
+ % pointer.
+ %
+:- type rel_offset
+ ---> ro8(int8) % Signed 8-bit offset (in bottom 8 bits).
+ ; ro16(int16) % Signed 16-bit offset (in bottom 16 bits).
+ ; ro32(int32). % Signed 32-bit offset (in bottom 32 bits).
+
+ % x86_64 instruction's operand can be a register, memory reference,
+ % signed relative offset or a label.
+ %
+:- type rmrol
+ ---> rmrol_reg(gp_reg)
+ ; rmrol_mem_ref(mem_ref)
+ ; rmrol_rel_offset(rel_offset)
+ ; rmrol_label(
+ rmrol_label_name :: string
+ ).
+
+%-----------------------------------------------------------------------------%
+%
+% x86_64 instructions.
+%
+
+ % We use At&T style instructions where the source comes before the
+ % destination.
+ %
+:- type x86_64_op
+ ---> adc(
+ adc_src :: operand,
+ adc_dst :: reg_or_mem_ref_op
+ )
+ % Add with carry. Add 'adc_src' to 'adc_dst' + carry flag (CF).
+ % Details on amd64-prog-man-vol3 manual p65.
+
+ ; add(
+ add_src :: operand,
+ add_dst :: reg_or_mem_ref_op
+ )
+ % Signed or unsigned add. Add 'adc_src' to 'adc_dst'.
+ % Details on amd64-prog-man-vol3 manual p67.
+
+ ; and(
+ and_src :: operand,
+ and_dst :: reg_or_mem_ref_op
+ )
+ % Performs a bitwise AND operation on both operands.
+ % Details on amd64-prog-man-vol3 manual p69.
+
+ ; bsf(
+ bsf_src :: reg_or_mem_ref_op,
+ bsf_dst :: gp_reg
+ )
+ % Bit scan forward. Searches the value in 'bsf_src' for the least
+ % significant set bit.
+ % Details on amd64-prog-man-vol3 manual p74.
+
+ ; bsr(
+ bsr_src :: reg_or_mem_ref_op,
+ bsr_dst :: gp_reg
+ )
+ % Bit scan reverse. Searches the value in 'bsf_src' for the most
+ % significant set bit.
+ % Details on amd64-prog-man-vol3 manual p75.
+
+ ; bswap(gp_reg)
+ % Byte swap. Reverses the byte order of the specified 'gp_reg'.
+ % Details on amd64-prog-man-vol3 manual p76.
+
+ ; bt(
+ bt_src :: reg_or_mem_ref_op,
+ bt_idx :: reg_or_imm_op
+ )
+ % Bit test. Copies a bit specified by 'bt_idx' from a bit string in
+ % 'bt_src' to the carry flag (CF) or RFLAGS register.
+ % Details on amd64-prog-man-vol3 manual p77.
+
+ ; btc(
+ btc_src :: reg_or_mem_ref_op,
+ btc_idx :: reg_or_imm_op
+ )
+ % Bit test and complement. Complements 'btc_src' after performing
+ % 'bt' operation.
+ % Details on amd64-prog-man-vol3 manual p79.
+
+ ; btr(
+ btr_src :: reg_or_mem_ref_op,
+ btr_idx :: reg_or_imm_op
+ )
+ % Bit test and reverse. Clears 'btr_src' to 0 after performing 'bt'
+ % operation.
+ % Details on amd64-prog-man-vol3 manual p81.
+
+ ; bts(
+ bts_src :: reg_or_mem_ref_op,
+ bts_idx :: reg_or_imm_op
+ )
+ % Bit test and set. Sets 'bts_src' to 1 after performing 'bt'
+ % operation.
+ % Details on amd64-prog-man-vol3 manual p83.
+
+ ; call(rmrol)
+ % Call with target specified by 'rmrol': register, memory location,
+ % relative offset or a label.
+ % Details on amd64-prog-man-vol3 manual p85.
+
+ ; cbw
+ % Sign-extend AL into AX.
+ % Details on amd64-prog-man-vol3 manual p94.
+
+ ; cwde
+ % Sign-extend AX into EAX.
+ % Details on amd64-prog-man-vol3 manual p94.
+
+ ; cdqe
+ % Sign-extend EAX into RAX.
+ % Details on amd64-prog-man-vol3 manual p94.
+
+ ; cwd
+ % Sign-extend AX into DX:AX.
+ % Details on amd64-prog-man-vol3 manual p95.
+
+ ; cdq
+ % Sign-extend EAX into EDX:EAX.
+ % Details on amd64-prog-man-vol3 manual p95.
+
+ ; cqo
+ % Sign-extend RAX into RDX:RAX.
+ % Details on amd64-prog-man-vol3 manual p95.
+
+ ; clc
+ % Clears the carry flag (CF) in the rFLAGS register to zero.
+ % Details on amd64-prog-man-vol3 manual p96.
+
+ ; cld
+ % Clears the direction flag (DF) in the rFLAGS register to zero.
+ % Details on amd64-prog-man-vol3 manual p97.
+
+ ; cmc
+ % Complements the carry flag bit (CF) bit in the rFLAGS register.
+ % Details on amd64-prog-man-vol3 manual p100.
+
+ ; cmovo(
+ cmovo_src :: reg_or_mem_ref_op,
+ cmovo_dest :: gp_reg
+ )
+ % Moves if overflow (OF = 1).
+ % Details on amd64-prog-man-vol3 manual p101.
+
+ ; cmovno(
+ cmovno_src :: reg_or_mem_ref_op,
+ cmovno_dest :: gp_reg
+ )
+ % Moves if not overflow (OF = 0).
+ % Details on amd64-prog-man-vol3 manual p101.
+
+ ; cmovb(
+ cmovb_src :: reg_or_mem_ref_op,
+ cmovb_dest :: gp_reg
+ )
+ % Moves if below (CF = 1).
+ % Details on amd64-prog-man-vol3 manual p101.
+
+ ; cmovc(
+ cmovc_src :: reg_or_mem_ref_op,
+ cmovc_dest :: gp_reg
+ )
+ % Moves if carry (CF = 1).
+ % Details on amd64-prog-man-vol3 manual p101.
+
+ ; cmovnae(
+ cmovnae_src :: reg_or_mem_ref_op,
+ cmovnae_dest :: gp_reg
+ )
+ % Moves if not above or equal (CF = 1).
+ % Details on amd64-prog-man-vol3 manual p101.
+
+ ; cmovnb(
+ cmovnb_src :: reg_or_mem_ref_op,
+ cmovnb_dest :: gp_reg
+ )
+ % Moves if not below (CF = 0).
+ % Details on amd64-prog-man-vol3 manual p101.
+
+ ; cmovnc(
+ cmovnc_src :: reg_or_mem_ref_op,
+ cmovnc_dest :: gp_reg
+ )
+ % Moves if not carry (CF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovae(
+ cmovae_src :: reg_or_mem_ref_op,
+ cmovae_dest :: gp_reg
+ )
+ % Moves if above or equal (CF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovz(
+ cmovz_src :: reg_or_mem_ref_op,
+ cmovz_dest :: gp_reg
+ )
+ % Moves if zero (ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmove(
+ cmove_src :: reg_or_mem_ref_op,
+ cmove_dest :: gp_reg
+ )
+ % Moves if equal (ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovnz(
+ cmovnz_src :: reg_or_mem_ref_op,
+ cmovnz_dest :: gp_reg
+ )
+ % Moves if not zero (ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovne(
+ cmovne_src :: reg_or_mem_ref_op,
+ cmovne_dest :: gp_reg
+ )
+ % Moves if not equal (ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovbe(
+ cmovbe_src :: reg_or_mem_ref_op,
+ cmovbe_dest :: gp_reg
+ )
+ % Moves if below or equal (CF = 1 or ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovna(
+ cmovna_src :: reg_or_mem_ref_op,
+ cmovna_dest :: gp_reg
+ )
+ % Moves if not above (CF = 1 or ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovnbe(
+ cmovnbe_src :: reg_or_mem_ref_op,
+ cmovnbe_dest :: gp_reg
+ )
+ % Moves if not below or equal (CF = 0 or ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmova(
+ cmova_src :: reg_or_mem_ref_op,
+ cmova_dest :: gp_reg
+ )
+ % Moves if above (CF = 1 or ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovs(
+ cmovs_src :: reg_or_mem_ref_op,
+ cmovs_dest :: gp_reg
+ )
+ % Moves if sign (SF = 1).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovns(
+ cmovns_src :: reg_or_mem_ref_op,
+ cmovns_dest :: gp_reg
+ )
+ % Moves if not sign (SF = 0).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovp(
+ cmovp_src :: reg_or_mem_ref_op,
+ cmovp_dest :: gp_reg
+ )
+ % Moves if parity (PF = 1).
+ % Details on amd64-prog-man-vol3 manual p102.
+
+ ; cmovpe(
+ cmovpe_src :: reg_or_mem_ref_op,
+ cmovpe_dest :: gp_reg
+ )
+ % Moves if parity even (PF = 1).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovnp(
+ cmovnp_src :: reg_or_mem_ref_op,
+ cmovnp_dest :: gp_reg
+ )
+ % Moves if not parity (PF = 0).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovpo(
+ cmovpo_src :: reg_or_mem_ref_op,
+ cmovpo_dest :: gp_reg
+ )
+ % Moves if parity odd (PF = 0).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovl(
+ cmovl_src :: reg_or_mem_ref_op,
+ cmovl_dest :: gp_reg
+ )
+ % Moves if less (SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovnge(
+ cmovnge_src :: reg_or_mem_ref_op,
+ cmovnge_dest :: gp_reg
+ )
+ % Moves if not greater or equal (SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovnl(
+ cmovnl_src :: reg_or_mem_ref_op,
+ cmovnl_dest :: gp_reg
+ )
+ % Moves if not less (SF = OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovge(
+ cmovge_src :: reg_or_mem_ref_op,
+ cmovge_dest :: gp_reg
+ )
+ % Moves if greater or equal (SF = OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovle(
+ cmovle_src :: reg_or_mem_ref_op,
+ cmovle_dest :: gp_reg
+ )
+ % Moves if less or equal (ZF = 1 or SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovng(
+ cmovng_src :: reg_or_mem_ref_op,
+ cmovng_dest :: gp_reg
+ )
+ % Moves if not greater (ZF = 1 or SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovnle(
+ cmovnle_src :: reg_or_mem_ref_op,
+ cmovnle_dest :: gp_reg
+ )
+ % Moves if not less or equal (ZF = 0 or SF = OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmovg(
+ cmovg_src :: reg_or_mem_ref_op,
+ cmovg_dest :: gp_reg
+ )
+ % Moves if greater (ZF = 0 or SF = OF).
+ % Details on amd64-prog-man-vol3 manual p103.
+
+ ; cmp(
+ cmp_src :: operand,
+ cmp_dest :: reg_or_mem_ref_op
+ )
+ % Compares 'cmp_src' with 'cmp_dest'.
+ % Details on amd64-prog-man-vol3 manual p105.
+
+ ; cmpxchg(
+ cmpxchg_cmp :: reg_or_mem_ref_op,
+ cmpxchg_xchg :: gp_reg
+ )
+ % Compares the value in RAX with the value in 'cmpxchg_cmp'.
+ % If equal, copies the value in 'cmpxchg_xchg' to 'cmpxchg_cmp'.
+ % Details on amd64-prog-man-vol3 manual p111.
+
+ ; cmpxchg8b(mem_ref)
+ % Compares the value in EDX:EAX with the value in 'mem_ref'.
+ % Details on amd64-prog-man-vol3 manual p113.
+
+ ; dec(reg_or_mem_ref_op)
+ % Decrements the contents of 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p120.
+
+ ; div(reg_or_mem_ref_op)
+ % Unsigned divide RDX:RAX by the value in 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p122.
+
+ ; enter(
+ enter_stack_size :: uint16,
+ enter_nesting_level :: uint8
+ )
+ % Creates a procedure stack frame with a stack size specified in
+ % 'enter_stack_size' and nesting level specified in
+ % 'enter_nesting_level'(0 to 31).
+ % Details on amd64-prog-man-vol3 manual p124.
+
+ ; idiv(reg_or_mem_ref_op)
+ % Signed divide RDX:RAX by the value in 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p126.
+
+ ; imul(reg_or_mem_ref_op)
+ % Signed multiply RAX by the value in 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p128.
+
+ ; imul(
+ imul1_src :: reg_or_mem_ref_op,
+ imul1_dest :: gp_reg
+ )
+ % Signed multiply 'imul1_src' by 'imul1_dest'.
+ % Details on amd64-prog-man-vol3 manual p129.
+
+ ; imul(
+ imul2_src :: reg_or_mem_ref_op,
+ imul2_multiplicand :: imm_operand,
+ imul2_dest :: gp_reg
+ )
+ % Signed multiply 'imul2_src' by 'imul2_multiplicand'.
+ % Details on amd64-prog-man-vol3 manual p129.
+
+ ; inc(reg_or_mem_ref_op)
+ % Increments the contents of 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p133.
+
+ ; jo(rel_offset)
+ % Jumps if overflow (OF = 1).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jno(rel_offset)
+ % Jumps if not overflow (OF = 0).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jb(rel_offset)
+ % Jumps if below (CF = 1).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jc(rel_offset)
+ % Jumps if carry (CF = 1).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jnae(rel_offset)
+ % Jumps if not above or equal (CF = 1).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jnb(rel_offset)
+ % Jumps if not below (CF = 0).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jnc(rel_offset)
+ % Jumps if not carry (CF = 0).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jae(rel_offset)
+ % Jumps if above or equal (CF = 0).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jz(rel_offset)
+ % Jumps if zero (ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; je(rel_offset)
+ % Jumps if equal (ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jnz(rel_offset)
+ % Jumps if not zero (ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jne(rel_offset)
+ % Jumps if not equal (ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p147.
+
+ ; jbe(rel_offset)
+ % Jumps if below or equal (CF = 1 or ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jna(rel_offset)
+ % Jumps if not above (CF = 1 or ZF = 1).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jnbe(rel_offset)
+ % Jumps if not below or equal (CF = 0 or ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; ja(rel_offset)
+ % Jumps if above (CF = 0 or ZF = 0).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; js(rel_offset)
+ % Jumps if sign (SF = 1).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jns(rel_offset)
+ % Jumps if not sign (SF = 0).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jp(rel_offset)
+ % Jumps if parity (PF = 1).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jpe(rel_offset)
+ % Jumps if parity even (PF = 1).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jnp(rel_offset)
+ % Jumps if not parity (PF = 0).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jpo(rel_offset)
+ % Jumps if parity odd (PF = 0).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jl(rel_offset)
+ % Jumps if less (SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jnge(rel_offset)
+ % Jumps if not greater or equal (SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jnl(rel_offset)
+ % Jumps if not less (SF = OF).
+ % Details on amd64-prog-man-vol3 manual p148.
+
+ ; jge(rel_offset)
+ % Jumps if greater or equal (SF = OF).
+ % Details on amd64-prog-man-vol3 manual p149.
+
+ ; jle(rel_offset)
+ % Jumps if less or equal (ZF = 1 or SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p149.
+
+ ; jng(rel_offset)
+ % Jumps if not greater (ZF = 1 or SF <> OF).
+ % Details on amd64-prog-man-vol3 manual p149.
+
+ ; jnle(rel_offset)
+ % Jumps if not less or equal (ZF = 0 and SF = OF).
+ % Details on amd64-prog-man-vol3 manual p149.
+
+ ; jg(rel_offset)
+ % Jumps if greater (ZF = 0 and SF = OF).
+ % Details on amd64-prog-man-vol3 manual p149.
+
+ ; jrcxz(rel_offset)
+ % Jumps to the target instruction located at the specified 8-bit
+ % relative offset if RCX is zero.
+ % Details on amd64-prog-man-vol3 manual p150.
+
+ ; jmp(rmrol)
+ % Jumps with target specified in 'rmrol': register, memory location,
+ % relative offset or label.
+ % Details on amd64-prog-man-vol3 manual p152.
+
+ ; lea(
+ lea_src :: mem_ref,
+ lea_dest :: gp_reg
+ )
+ % Stores effective address 'lea_src' into 'lea_dest'.
+ % Details on amd64-prog-man-vol3 manual p163.
+
+ ; leave
+ % Sets RSP to the value in RBP and pop RBP.
+ % Details on amd64-prog-man-vol3 manual p164.
+
+ ; loop(
+ loop_rel_8bit :: rel_offset
+ )
+ % Decrements RCX then jump if RCX is not zero
+ % Details on amd64-prog-man-vol3 manual p169.
+
+ ; loope(
+ loope_rel_8bit :: rel_offset
+ )
+ % Decrements RCX then jump if RCX is not zero and ZF = 1.
+ % Details on amd64-prog-man-vol3 manual p169.
+
+ ; loopne(
+ loopne_rel_8bit :: rel_offset
+ )
+ % Decrements RCX then jump if RCX is not zero and ZF = 0.
+ % Details on amd64-prog-man-vol3 manual p169.
+
+ ; loopnz(
+ loopnz_rel_8bit :: rel_offset
+ )
+ % Decrements RCX then jump if RCX is not zero and ZF = 0.
+ % Details on amd64-prog-man-vol3 manual p170.
+
+ ; loopz(
+ loopz_rel_8bit :: rel_offset
+ )
+ % Decrements RCX then jump if RCX is not zero and ZF = 1.
+ % Details on amd64-prog-man-vol3 manual p170.
+
+ ; mov(
+ mov_src :: operand,
+ mov_dest :: reg_or_mem_ref_op
+ )
+ % Copies 'mov_src' to 'mov_dest'.
+ % Details on amd64-prog-man-vol3 manual p173.
+
+ ; mul(reg_or_mem_ref_op)
+ % Unsigned multiply 'reg_or_mem_ref_op' by RAX.
+ % Details on amd64-prog-man-vol3 manual p190.
+
+ ; neg(reg_or_mem_ref_op)
+ % Performs a two's complement negation of 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p192.
+
+ ; nop
+ % Increments RIP to point to next instruction.
+ % Details on amd64-prog-man-vol3 manual p194.
+
+ ; not_(reg_or_mem_ref_op)
+ % Performs one's complement negation (NOT) of 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p195.
+
+ ; or(
+ or_src :: operand,
+ or_dest :: reg_or_mem_ref_op
+ )
+ % Performs a logical OR on the bits in 'or_src' and 'or_dest'.
+ % Details on amd64-prog-man-vol3 manual p196.
+
+ ; pop(reg_or_mem_ref_op)
+ % Pops the stack into 'reg_or_mem_ref_op'.
+ % Details on amd64-prog-man-vol3 manual p204.
+
+ ; popfq
+ % Pops a quadword from the stack to the RFLAGS register.
+ % Details on amd64-prog-man-vol3 manual p208.
+
+ ; push(operand)
+ % Pushes the content of operand onto the stack.
+ % Details on amd64-prog-man-vol3 manual p215.
+
+ ; pushfq
+ % Pushes the RFLAGS quadword onto the stack.
+ % Details on amd64-prog-man-vol3 manual p218.
+
+ ; ret
+ % Near return to the calling procedure.
+ % Details on amd64-prog-man-vol3 manual p224.
+
+ ; rcl(
+ rcl_amount :: cl_reg_or_imm_op,
+ rcl_dest :: reg_or_mem_ref_op
+ )
+ % Rotate bits in 'rcl_dest' to the left and through the carry flag
+ % by the number of bit positions as specified in 'rcl_amount'.
+ % Details on amd64-prog-man-vol3 manual p220.
+
+ ; rcr(
+ rcr_amount :: cl_reg_or_imm_op,
+ rcr_dest :: reg_or_mem_ref_op
+ )
+ % Rotate bits in 'rcr_dest' to the right and through the carry flag
+ % by the number of bit positions as specified in 'rcr_amount'.
+ % Details on amd64-prog-man-vol3 manual p222.
+
+ ; ret(uint16)
+ % Near return to the calling procedure, then pop the specified
+ % number of bytes from stack.
+ % Details on amd64-prog-man-vol3 manual p224.
+
+ ; rol(
+ rol_amount :: cl_reg_or_imm_op,
+ rol_dest :: reg_or_mem_ref_op
+ )
+ % Rotates the bits of 'rol_dest' left by 'rol_amount' bits.
+ % Details on amd64-prog-man-vol3 manual p230.
+
+ ; ror(
+ ror_amount :: cl_reg_or_imm_op,
+ ror_dest :: reg_or_mem_ref_op
+ )
+ % Rotates the bits of 'ror_dest' right by 'ror_amount bits'.
+ % Details on amd64-prog-man-vol3 manual p232.
+
+ ; sal(
+ sal_amount :: cl_reg_or_imm_op,
+ sal_dest :: reg_or_mem_ref_op
+ )
+ % Shift 'sal_dest' left by 'sal_amount'.
+ % Details on amd64-prog-man-vol3 manual p235.
+
+ ; shl(
+ shl_amount :: cl_reg_or_imm_op,
+ shl_dest :: reg_or_mem_ref_op
+ )
+ % Shift 'shl_dest' left by 'shl_amount'.
+ % Details on amd64-prog-man-vol3 manual p235.
+
+ ; sar(
+ sar_amount :: cl_reg_or_imm_op,
+ sar_dest :: reg_or_mem_ref_op
+ )
+ % Shift 'sar_dest' right by 'sar_amount'.
+ % Details on amd64-prog-man-vol3 manual p238.
+
+ ; sbb(
+ sbb_src :: operand,
+ sbb_dest :: reg_or_mem_ref_op
+ )
+ % Subtracts 'sbb_src' from 'sbb_dest' with borrow.
+ % Details on amd64-prog-man-vol3 manual p241.
+
+ ; seto(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If overflow
+ % (OF = 1), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setno(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not overflow
+ % (OF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setb(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is below
+ % (CF = 1), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setc(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is carry
+ % (CF = 1), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setnae(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is not above
+ % or equal (CF = 1), set the value in the specified register or an
+ % 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setnb(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is not below
+ % (CF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setnc(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is not carry
+ % (CF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setae(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is above or
+ % equal (CF = 0), set the value in the specified register or an
+ % 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setz(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If zero (ZF = 1),
+ % set the value in the specified register or an 8-bit memory
+ % reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; sete(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If equal (ZF = 1),
+ % set the value in the specified register or an 8-bit memory
+ % reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setnz(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not zero
+ % (ZF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setne(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not equal
+ % (ZF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p246.
+
+ ; setbe(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If below or equal
+ % (CF = 1 or ZF = 1), set the value in the specified register or
+ % an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setna(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not above
+ % (CF = 1 or ZF = 1), set the value in the specified register or
+ % an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setnbe(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not below or
+ % equal (CF = 0 and ZF = 0), set the value in the specified
+ % register or an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; seta(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If above
+ % (CF = 0 and ZF = 0), set the value in the specified
+ % register or an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; sets(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is sign,
+ % (SF = 1), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setns(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is not sign,
+ % (SF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setp(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If flag is parity
+ % (PF = 1), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setpe(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If parity even,
+ % (PF = 1), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setnp(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not parity,
+ % (PF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setpo(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If parity odd,
+ % (PF = 0), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setl(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If less (SF <> OF),
+ % set the value in the specified register or an 8-bit memory
+ % reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setnge(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not greater or
+ % equal (SF <> OF), set the value in the specified register or an
+ % 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setnl(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not less
+ % (SF = OF), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setge(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If greater or equal
+ % (SF = OF), set the value in the specified register or an 8-bit
+ % memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setle(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If less or equal
+ % (ZF = 1 or SF <> OF), set the value in the specified register or
+ % an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setng(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not greater
+ % (ZF = 1 or SF <> OF), set the value in the specified register or
+ % an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setnle(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If not less or equal
+ % (ZF = 0 and SF = OF), set the value in the specified register or
+ % an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; setg(reg_or_mem_ref_op)
+ % Check the status flag in the RFLAGS register. If greater
+ % (ZF = 0 and SF = OF), set the value in the specified register or
+ % an 8-bit memory reference to 1.
+ % Details on amd64-prog-man-vol3 manual p247.
+
+ ; shld(
+ shld_amount :: cl_reg_or_imm_op,
+ shld_dest1 :: reg_or_mem_ref_op,
+ shld_dest2 :: gp_reg
+ )
+ % Shift 'shld_dest1' to the left by 'shld_amount' and shift in a bit
+ % pattern in 'shld_dest2' from the right.
+ % Details on amd64-prog-man-vol3 manual p251.
+
+ ; shr(
+ shr_amount :: cl_reg_or_imm_op,
+ shr_dest :: reg_or_mem_ref_op
+ )
+ % Shift 'shr_dest' right by 'shr_amount'.
+ % Details on amd64-prog-man-vol3 manual p253.
+
+ ; shrd(
+ shrd_amount :: cl_reg_or_imm_op,
+ shrd_dest1 :: reg_or_mem_ref_op,
+ shrd_dest2 :: gp_reg
+ )
+ % Shift 'shrd_dest1' to the right by 'shrd_amount' and shift in
+ % a bit pattern in 'shrd_dest2' from the left.
+ % Details on amd64-prog-man-vol3 manual p255.
+
+ ; stc
+ % Sets the carry flag (CF) in the RFLAGS register to 1.
+ % Details on amd64-prog-man-vol3 manual p257.
+
+ ; std
+ % Sets the direction flag (DF) in the rflags register to 1.
+ % Details on amd64-prog-man-vol3 manual p258.
+
+ ; sub(
+ sub_src :: operand,
+ sub_dest :: reg_or_mem_ref_op
+ )
+ % Subtracts 'sub_src' from 'sub_dest'.
+ % Details on amd64-prog-man-vol3 manual p261.
+
+ ; test(
+ test_src1 :: reg_or_mem_ref_op,
+ test_src2 :: reg_or_imm_op
+ )
+ % Performs a bitwise AND on 'test_src1' and 'test_src2'.
+ % Details on amd64-prog-man-vol3 manual p264.
+
+ ; xadd(
+ xadd_src :: gp_reg,
+ xadd_dest :: reg_or_mem_ref_op
+ )
+ % Exchanges the contents of 'xadd_src' with 'xadd_dest', load
+ % their sum into 'xadd_dest'.
+ % Details on amd64-prog-man-vol3 manual p266.
+
+ ; xchg(
+ xchg_src1 :: reg_or_mem_ref_op,
+ xchg_src2 :: reg_or_mem_ref_op
+ )
+ % Exchanges the contents of 'xchg_src1' and 'xchg_src2'.
+ % Details on amd64-prog-man-vol3 manual p268.
+
+ ; xor(
+ xor_src :: operand,
+ xor_dest :: reg_or_mem_ref_op
+ ).
+ % Performs a bitwise XOR on 'xor_src' with 'xor_dest' and stores
+ % the result in xor_dest.
+ % Details on amd64-prog-man-vol3 manual p272.
+
+%-----------------------------------------------------------------------------%
Index: compiler/x86_64_out.m
===================================================================
RCS file: compiler/x86_64_out.m
diff -N compiler/x86_64_out.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ compiler/x86_64_out.m 12 Jan 2007 04:29:28 -0000
@@ -0,0 +1,1311 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2007 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: x86_64_out.m.
+% Main author: fhandoko.
+%
+% This module defines the routines for printing out x86_64 instructions.
+%
+%-----------------------------------------------------------------------------%
+
+:- module ll_backend.x86_64_out.
+:- interface.
+
+:- import_module ll_backend.x86_64_instrs.
+
+:- import_module io.
+
+%-----------------------------------------------------------------------------%
+
+:- pred output_x86_64_instrs(x86_64_instr::in, io::di, io::uo) is det.
+
+ % XXX This is just for testing purposes.
+ %
+% :- pred pretend_main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.compiler_util.
+
+:- import_module bool.
+:- import_module char.
+:- import_module int.
+:- import_module list.
+:- import_module maybe.
+:- import_module string.
+:- import_module type_desc.
+
+%-----------------------------------------------------------------------------%
+
+% pretend_main(!IO) :-
+% Comment1 = comment("This is a comment"),
+% Label1 = label(".L1"),
+% PseudoOps1 = [
+% abort,
+% align(6, no, yes(2)),
+% align(7, yes(12), no),
+% align(8, no, no),
+% ascii([".LI", ".L2"]),
+% comm(".L3", 8, no),
+% section(".data", no, no, no)
+% ],
+% Instrs1 = [
+% x86_64_instr(adc(operand_reg(rax),
+% rmro_reg(rbx)
+% ), ""),
+% x86_64_instr(add(operand_imm(imm8(int8(0x178))),
+% rmro_mem_ref(mem_abs(base_reg(0, r8)))
+% ), ""),
+% x86_64_instr(and(operand_reg(rdx),
+% rmro_mem_ref(mem_abs(base_reg(2, rdx)))
+% ), ""),
+% x86_64_instr(bsf(rmro_reg(r8), r15), ""),
+% x86_64_instr(bsr(rmro_reg(rcx), rax), ""),
+% x86_64_instr(bswap(r10), ""),
+% x86_64_instr(bt(rmro_mem_ref(mem_rip(rip_expr(".L1"))),
+% rio_reg(rsi)), ""),
+% x86_64_instr(btc(rmro_reg(rdi), rio_imm(imm16(int16(0x1822)))),""),
+% x86_64_instr(btr(rmro_reg(rbp),
+% rio_imm(imm32(int32(0x182199)))), ""),
+% x86_64_instr(call(rmrol_rel_offset(ro8(int8(127)))), "comment"),
+% x86_64_instr(cmovo(rmro_mem_ref(mem_rip(rip_constant(int32(2)))),
+% r11), ""),
+% x86_64_instr(mov(operand_imm(imm32(int32(10))), rmro_reg(rbx)),""),
+% x86_64_instr(or(operand_mem_ref(mem_rip(rip_constant(int32(2)))),
+% rmro_reg(rcx)), ""),
+% x86_64_instr(push(operand_mem_ref(mem_abs(base_expr(".L2")))),""),
+% x86_64_instr(rol(crio_reg_cl(rcx), rmro_reg(rax)), ""),
+% x86_64_instr(ror(crio_imm8(int8(20)), rmro_mem_ref(mem_rip(
+% rip_expr(".L2")) )), ""),
+% x86_64_instr(sbb(operand_mem_ref(mem_rip(rip_expr(".L1"))),
+% rmro_reg(r11)), "")
+% ],
+%
+% Label2 = label(".L2"),
+% PseudoOps2 = [
+% section(".rodata", yes("aMS"), yes("@progbits"), yes(1)),
+% p2align(1,no,yes(7)),
+% type_("Type", "@function")
+% ],
+% Instrs2 = [
+% x86_64_instr(loop(ro8(int8(19))), "another comment"),
+% x86_64_instr(xor(operand_imm(imm32(int32(19))),
+% rmro_mem_ref(mem_rip(rip_expr(".L4")))
+% ), "comment"),
+% x86_64_instr(jo(ro8(int8(22))), "comment again"),
+% x86_64_instr(div(rmro_reg(rdx)), "comment div"),
+% x86_64_instr(jmp(rmrol_label(".L2")), "comment jmp"),
+% x86_64_instr(mov(operand_mem_ref(mem_abs(base_expr(".L3"))),
+% rmro_reg(rbx)), "")
+% ],
+%
+% Instructions = [
+% comment(""), label(""), directives([file("x86_64_out.m")]),
+% instrs([]),
+% Comment1, Label1, directives(PseudoOps1), instrs(Instrs1),
+% comment("Comment"), Label2, directives(PseudoOps2),
+% instrs(Instrs2)
+% ],
+% list.foldl(output_x86_64_instrs, Instructions, !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % Output x86_64 instructions including comments, labels and pseudo-ops.
+ %
+output_x86_64_instrs(comment(Comment), !IO) :-
+ ( string.length(Comment) > 0 ->
+ io.write_string("# " ++ Comment ++ "\n", !IO)
+ ;
+ true
+ ).
+output_x86_64_instrs(label(LabelName), !IO) :-
+ ( string.length(LabelName) > 0 ->
+ io.write_string(LabelName ++ ":\n", !IO)
+ ;
+ true
+ ).
+output_x86_64_instrs(directives(PseudoOps), !IO) :-
+ list.foldl(output_x86_64_pseudo_op, PseudoOps, !IO).
+output_x86_64_instrs(instrs(Instrs), !IO) :-
+ ( list.length(Instrs) > 0 ->
+ output_x86_64_instr_and_comment(Instrs, !IO)
+ ;
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
+%
+% Output x86_64 pseudo-op.
+%
+
+:- pred output_x86_64_pseudo_op(pseudo_op::in, io::di, io::uo) is det.
+
+output_x86_64_pseudo_op(abort, !IO) :-
+ io.write_string("\t.abort\n", !IO).
+output_x86_64_pseudo_op(align(Bytes, FillVal, SkipBytes), !IO) :-
+ output_pseudo_op_with_int_args(".align", Bytes, FillVal, SkipBytes, !IO).
+output_x86_64_pseudo_op(ascii(Literals), !IO) :-
+ output_pseudo_op_str_args(".ascii", Literals, !IO).
+output_x86_64_pseudo_op(asciiz(Literals), !IO) :-
+ output_pseudo_op_str_args(".asciiz", Literals, !IO).
+output_x86_64_pseudo_op(balign(Bytes, FillVal, SkipBytes), !IO) :-
+ output_pseudo_op_with_int_args(".balign", Bytes, FillVal, SkipBytes,!IO).
+output_x86_64_pseudo_op(byte(ExprList), !IO) :-
+ output_pseudo_op_str_args(".byte", ExprList, !IO).
+output_x86_64_pseudo_op(comm(Symbol, Length, Align0), !IO) :-
+ io.write_string("\t.comm\t" ++ Symbol ++ ",", !IO),
+ io.write_int(Length, !IO),
+ ( Align0 = yes(Align1) ->
+ io.write_string(",", !IO),
+ io.write_int(Align1, !IO)
+ ;
+ true
+ ),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(data(Subsection0), !IO) :-
+ io.write_string("\t.data\t", !IO),
+ ( Subsection0 = yes(Subsection1) ->
+ io.write_int(Subsection1, !IO)
+ ;
+ true
+ ),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(desc(Symbol, AbsExpr), !IO) :-
+ io.write_string("\t.desc\t" ++ Symbol ++ "," ++ AbsExpr ++ "\n",
!IO).
+output_x86_64_pseudo_op(def(Name), !IO) :-
+ io.write_string("\t.def\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(dim, !IO) :-
+ io.write_string("\t.dim\n", !IO).
+output_x86_64_pseudo_op(double(NumList), !IO) :-
+ output_pseudo_op_float_args(".double", NumList, !IO).
+output_x86_64_pseudo_op(eject, !IO) :-
+ io.write_string("\t.eject\n", !IO).
+output_x86_64_pseudo_op(else_, !IO) :-
+ io.write_string("\t.else\n", !IO).
+output_x86_64_pseudo_op(elseif, !IO) :-
+ io.write_string("\t.elseif\n", !IO).
+output_x86_64_pseudo_op(end, !IO) :-
+ io.write_string("\t.end\n", !IO).
+output_x86_64_pseudo_op(endef, !IO) :-
+ io.write_string("\t.endef\n", !IO).
+output_x86_64_pseudo_op(endfunc, !IO) :-
+ io.write_string("\t.endfunc\n", !IO).
+output_x86_64_pseudo_op(endif, !IO) :-
+ io.write_string("\t.endif\n", !IO).
+output_x86_64_pseudo_op(endm, !IO) :-
+ io.write_string("\t.endm\n", !IO).
+output_x86_64_pseudo_op(equ(Symbol, Expr), !IO) :-
+ io.write_string("\t.equ\t" ++ Symbol ++ "," ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(equiv(Symbol, Expr), !IO) :-
+ io.write_string("\t.equiv\t" ++ Symbol ++ "," ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(err, !IO) :-
+ io.write_string("\t.err\n", !IO).
+output_x86_64_pseudo_op(exitm, !IO) :-
+ io.write_string("\t.exitm\n", !IO).
+output_x86_64_pseudo_op(extern, !IO) :-
+ io.write_string("\t.extern\n", !IO).
+output_x86_64_pseudo_op(fail_(Expr), !IO) :-
+ io.write_string("\t.fail\t" ++ Expr++ "\n", !IO).
+output_x86_64_pseudo_op(file(Name), !IO) :-
+ io.write_string("\t.file\t\"" ++ Name ++ "\"\n", !IO).
+output_x86_64_pseudo_op(fill(Repeat, Size, Val), !IO) :-
+ output_pseudo_op_with_int_args(".repeat", Repeat, Size, Val, !IO).
+output_x86_64_pseudo_op(float(NumList), !IO) :-
+ output_pseudo_op_float_args(".float", NumList, !IO).
+output_x86_64_pseudo_op(func_(Name, Label), !IO) :-
+ io.write_string("\t.func\t" ++ Name ++ "," ++ Label ++ "\n", !IO).
+output_x86_64_pseudo_op(global(Symbol), !IO) :-
+ io.write_string("\t.global\t" ++ Symbol ++ "\n", !IO).
+output_x86_64_pseudo_op(globl(Symbol), !IO) :-
+ io.write_string("\t.globl\t" ++ Symbol ++ "\n", !IO).
+output_x86_64_pseudo_op(hidden(Name), !IO) :-
+ io.write_string("\t.hidden\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(hword(ExprList), !IO) :-
+ output_pseudo_op_str_args(".hword", ExprList, !IO).
+output_x86_64_pseudo_op(ident, !IO) :-
+ io.write_string("\t.ident\n", !IO).
+output_x86_64_pseudo_op(if_(Expr), !IO) :-
+ io.write_string("\t.if\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(ifdef(Symbol), !IO) :-
+ io.write_string("\t.ifdef\t" ++ Symbol ++ "\n", !IO).
+output_x86_64_pseudo_op(ifc(Str1, Str2), !IO) :-
+ io.write_string("\t.ifc\t" ++ Str1 ++ "," ++ Str2 ++ "\n", !IO).
+output_x86_64_pseudo_op(ifeq(Expr), !IO) :-
+ io.write_string("\t.ifeq\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(ifge(Expr), !IO) :-
+ io.write_string("\t.ifge\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(ifgt(Expr), !IO) :-
+ io.write_string("\t.ifgt\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(ifle(Expr), !IO) :-
+ io.write_string("\t.ifle\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(iflt(Expr), !IO) :-
+ io.write_string("\t.iflt\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(ifnc(Str1, Str2), !IO) :-
+ io.write_string("\t.ifnc\t" ++ Str1 ++ "," ++ Str2 ++ "\n", !IO).
+output_x86_64_pseudo_op(ifndef(Symbol), !IO) :-
+ io.write_string("\t.ifndef\t" ++ Symbol ++ "\n", !IO).
+output_x86_64_pseudo_op(ifnotdef(Symbol), !IO) :-
+ io.write_string("\t.ifnotdef\t" ++ Symbol ++ "\n", !IO).
+output_x86_64_pseudo_op(ifne(Expr), !IO) :-
+ io.write_string("\t.ifne\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(ifnes(Str1, Str2), !IO) :-
+ io.write_string("\t.ifnes\t" ++ Str1 ++ "," ++ Str2 ++ "\n", !IO).
+output_x86_64_pseudo_op(include(File), !IO) :-
+ io.write_string("\t.include\t" ++ "\"" ++ File ++ "\"\n", !IO).
+output_x86_64_pseudo_op(int(ExprList), !IO) :-
+ output_pseudo_op_str_args(".int", ExprList, !IO).
+output_x86_64_pseudo_op(internal(Name), !IO) :-
+ io.write_string("\t.internal\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(lcomm(Symbol, Length), !IO) :-
+ io.write_string("\tlcomm\t" ++ Symbol, !IO),
+ io.write_int(Length, !IO),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(line(LineNum), !IO) :-
+ io.write_string("\t.line\t", !IO),
+ io.write_int(LineNum, !IO),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(list, !IO) :-
+ io.write_string("\t.list\n", !IO).
+output_x86_64_pseudo_op(long(ExprList), !IO) :-
+ output_pseudo_op_str_args(".long", ExprList, !IO).
+output_x86_64_pseudo_op(macro, !IO) :-
+ io.write_string("\t.macro\n", !IO).
+output_x86_64_pseudo_op(nolist, !IO) :-
+ io.write_string("\t.nolist\n", !IO).
+output_x86_64_pseudo_op(p2align(PowBit, FillVal, SkipBytes), !IO) :-
+ output_pseudo_op_with_int_args(".p2align", PowBit, FillVal,
SkipBytes, !IO).
+output_x86_64_pseudo_op(popsection, !IO) :-
+ io.write_string("\t.popsection\n", !IO).
+output_x86_64_pseudo_op(previous, !IO) :-
+ io.write_string("\t.previous\n", !IO).
+output_x86_64_pseudo_op(print(Str), !IO) :-
+ io.write_string("\t.print\t" ++ Str ++ "\n", !IO).
+output_x86_64_pseudo_op(protected(Name), !IO) :-
+ io.write_string("\t.protected\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(psize(Lines, Cols), !IO) :-
+ output_pseudo_op_with_int_args(".psize", Lines, Cols, no, !IO).
+output_x86_64_pseudo_op(purgem(Name), !IO) :-
+ io.write_string("\t.purgem\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(pushsection(Name, Subsection), !IO) :-
+ io.write_string("\t.pushsection\t" ++ Name, !IO),
+ io.write_int(Subsection, !IO),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(quad(BigNumList), !IO) :-
+ output_pseudo_op_str_args("\t.quad\t", BigNumList, !IO).
+output_x86_64_pseudo_op(rept(Count), !IO) :-
+ io.write_string("\t.rept\t", !IO),
+ io.write_int(Count, !IO),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(sbttl(SubHeading), !IO) :-
+ io.write_string("\t.sbttl\t" ++ "\"" ++ SubHeading ++ "\"\n", !IO).
+output_x86_64_pseudo_op(scl(Class), !IO) :-
+ io.write_string("\t.scl\t" ++ Class ++ "\n", !IO).
+output_x86_64_pseudo_op(section(Name, Flags0, Type0, EntSize0), !IO) :-
+ io.write_string("\t.section\t" ++ Name, !IO),
+ ( Flags0 = yes(Flags1) ->
+ check_section_flags_and_type(Flags1, Type0, Result0),
+ (
+ Result0 = yes,
+ Type0 = yes(Type1)
+ ->
+ io.write_string(",\"" ++ Flags1 ++ "\"", !IO),
+ ( check_pseudo_section_type(Type1) ->
+ io.write_string("," ++ Type1, !IO)
+ ;
+ unexpected(this_file, "output_x86_64_pseudo_op: section:
+ check_section_type unexpected")
+ )
+ ;
+ unexpected(this_file, "output_x86_64_pseudo_op: section:
+ check_section_flags_and_type unexpected")
+ )
+ ;
+ true
+ ),
+ ( EntSize0 = yes(EntSize1)->
+ io.write_string(",", !IO),
+ io.write_int(EntSize1, !IO)
+ ;
+ true
+ ),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(set(Symbol, Expr), !IO) :-
+ io.write_string("\t.set\t" ++ Symbol ++ "," ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(short(ExprList), !IO) :-
+ output_pseudo_op_str_args(".short", ExprList, !IO).
+output_x86_64_pseudo_op(single(FloatList), !IO) :-
+ output_pseudo_op_float_args(".single", FloatList, !IO).
+output_x86_64_pseudo_op(size(Name, Expr), !IO) :-
+ io.write_string("\t.size\t" ++ Name ++ "," ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(skip(Size, Val), !IO) :-
+ output_pseudo_op_with_int_args(".skip", Size, Val, no, !IO).
+output_x86_64_pseudo_op(sleb128(ExprList), !IO) :-
+ output_pseudo_op_str_args(".sleb128\t", ExprList, !IO).
+output_x86_64_pseudo_op(space(Size, Fill), !IO) :-
+ output_pseudo_op_with_int_args(".space", Size, Fill, no, !IO).
+output_x86_64_pseudo_op(string(StrList), !IO) :-
+ output_pseudo_op_str_args(".string", StrList, !IO).
+output_x86_64_pseudo_op(struct(Expr), !IO) :-
+ io.write_string("\t.struct\t" ++ Expr ++ "\n", !IO).
+output_x86_64_pseudo_op(subsection(Name), !IO) :-
+ io.write_string("\t.subsection\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(symver(Name, Alias), !IO) :-
+ io.write_string("\t.symver\t" ++ Name ++ "," ++ Alias ++ "\n", !IO).
+output_x86_64_pseudo_op(tag(Name), !IO) :-
+ io.write_string("\t.tag\t" ++ Name ++ "\n", !IO).
+output_x86_64_pseudo_op(text(Subsection0), !IO) :-
+ io.write_string("\ttext\t", !IO),
+ ( Subsection0 = yes(Subsection1) ->
+ io.write_int(Subsection1, !IO)
+ ;
+ true
+ ),
+ io.write_string("\n", !IO).
+output_x86_64_pseudo_op(title(Heading), !IO) :-
+ io.write_string("\t.title\t" ++ Heading ++ "\n", !IO).
+output_x86_64_pseudo_op(type_(Name, Desc), !IO) :-
+ ( check_pseudo_type_desc(Desc) ->
+ io.write_string("\t.type\t" ++ Name ++ "," ++ Desc ++ "\n", !IO)
+ ;
+ unexpected(this_file, "output_x86_64_pseudo_op: type_ unexpected")
+ ).
+output_x86_64_pseudo_op(uleb128(ExprList), !IO) :-
+ output_pseudo_op_str_args(".uleb128", ExprList, !IO).
+output_x86_64_pseudo_op(val(Addr), !IO) :-
+ io.write_string("\t.val\t" ++ Addr ++ "\n", !IO).
+output_x86_64_pseudo_op(version(Note), !IO) :-
+ io.write_string("\t.version\t" ++ Note ++ "\n", !IO).
+output_x86_64_pseudo_op(weak(NameList), !IO) :-
+ output_pseudo_op_str_args(".weak", NameList, !IO).
+output_x86_64_pseudo_op(word(ExprList), !IO) :-
+ output_pseudo_op_str_args(".word", ExprList, !IO).
+
+ % Output pseudo-op name with 1, 2 or 3 integer arguments.
+ %
+:- pred output_pseudo_op_with_int_args(string::in, int::in, maybe(int)::in,
+ maybe(int)::in, io::di, io::uo) is det.
+
+output_pseudo_op_with_int_args(OpName, Arg1, Arg2, Arg3, !IO) :-
+ io.write_string("\t" ++ OpName ++ "\t", !IO),
+ io.write_int(Arg1, !IO),
+ ( Arg2 = yes(Arg2Out) ->
+ io.write_string(",", !IO),
+ io.write_int(Arg2Out, !IO)
+ ;
+ true
+ ),
+ ( Arg3 = yes(Arg3Out) ->
+ ( Arg2 = no ->
+ io.write_string(",,", !IO),
+ io.write_int(Arg3Out, !IO)
+ ;
+ io.write_string(",", !IO),
+ io.write_int(Arg3Out, !IO)
+ )
+ ;
+ true
+ ),
+ io.write_string("\n", !IO).
+
+ % Output pseudo-op having list of float as its argument.
+ %
+:- pred output_pseudo_op_float_args(string::in, list(float)::in,
+ io::di, io::uo) is det.
+
+output_pseudo_op_float_args(OpName, FloatArgs, !IO) :-
+ io.write_string("\t" ++ OpName ++ "\t", !IO),
+ pseudo_op_float_args_while(FloatArgs, !IO),
+ io.write_string("\n", !IO).
+
+:- pred pseudo_op_float_args_while(list(float)::in, io::di, io::uo) is det.
+
+pseudo_op_float_args_while([], !IO).
+pseudo_op_float_args_while([Arg | Args], !IO) :-
+ io.write_float(Arg, !IO),
+ ( Args = [] ->
+ pseudo_op_float_args_while(Args, !IO)
+ ;
+ io.write_string(",", !IO),
+ pseudo_op_float_args_while(Args, !IO)
+ ).
+
+ % Output pseudo-op having list of string as its argument.
+ %
+:- pred output_pseudo_op_str_args(string::in, list(string)::in,
+ io::di, io::uo) is det.
+
+output_pseudo_op_str_args(OpName, StrArgs, !IO) :-
+ io.write_string("\t" ++ OpName ++ "\t", !IO),
+ pseudo_op_str_args_while(StrArgs, !IO),
+ io.write_string("\n", !IO).
+
+:- pred pseudo_op_str_args_while(list(string)::in, io::di, io::uo) is
det.
+
+pseudo_op_str_args_while([], !IO).
+pseudo_op_str_args_while([Arg | Args], !IO) :-
+ io.write_string(Arg, !IO),
+ ( Args = [] ->
+ pseudo_op_str_args_while(Args, !IO)
+ ;
+ io.write_string(",", !IO),
+ pseudo_op_str_args_while(Args, !IO)
+ ).
+
+ % Check if FLAGS and TYPE argument of '.section' pseudo-op is valid
+ %
+:- pred check_section_flags_and_type(string::in, maybe(string)::in,
+ bool::out) is det.
+
+check_section_flags_and_type(Flags, Type0, Result) :-
+ ( string.contains_char(Flags, 'M') ->
+ (
+ Type0 = yes(Type1),
+ string.length(Type1) > 0
+ ->
+ true
+ ;
+ unexpected(this_file, "check_section_flags_and_type:
+ flag unexpected")
+ )
+ ;
+ true
+ ),
+ string.to_char_list(Flags, CharList),
+ check_pseudo_section_flags(CharList, Result0),
+ ( Result0 = yes ->
+ Result = yes
+ ;
+ Result = no
+ ).
+
+ % Check FLAGS argument of '.section' pseudo-op
+ %
+:- pred check_pseudo_section_flags(list(char)::in, bool::out) is det.
+
+check_pseudo_section_flags([], yes).
+check_pseudo_section_flags([Char | Chars], Result) :-
+ ( string.contains_char(section_pseudo_op_flags, Char) ->
+ check_pseudo_section_flags(Chars, Result)
+ ;
+ Result = no
+ ).
+
+ % The optional FLAGS argument of '.section' pseudo-op contains any
+ % combination of:
+ % 'a' - section is allocatable
+ % 'w' - section is writable
+ % 'x' - section is executable
+ % 'M' - section is mergeable
+ % 'S' - section contains zero terminated string
+ %
+:- func section_pseudo_op_flags = string.
+
+section_pseudo_op_flags = "awxMS".
+
+ % The optional type of '.section' pseudo-op may contain:
+ % @progbits - section contains data
+ % @nobits - section does not contain data
+ %
+:- pred check_pseudo_section_type(string::in) is semidet.
+
+check_pseudo_section_type("@progbits").
+check_pseudo_section_type("@nobits").
+
+ % Two valid values of 'type_desc' field in pseudo-op '.type':
+ % @function
+ % @object
+ %
+:- pred check_pseudo_type_desc(string::in) is semidet.
+
+check_pseudo_type_desc("@function").
+check_pseudo_type_desc("@function").
+
+%-----------------------------------------------------------------------------%
+%
+% Output x86_64 instructions.
+%
+
+:- pred output_x86_64_instr_and_comment(list(x86_64_instruction)::in, io::di,
+ io::uo) is det.
+
+output_x86_64_instr_and_comment([], !IO).
+output_x86_64_instr_and_comment([Instr | Instrs], !IO) :-
+ Instr = x86_64_instr(InstrName, Comment),
+ output_x86_64_instr(InstrName, !IO),
+ output_comment(Comment, !IO),
+ output_x86_64_instr_and_comment(Instrs, !IO).
+
+ % Output x86_64 instruction and its operands (if any).
+ %
+:- pred output_x86_64_instr(x86_64_op::in, io::di, io::uo) is det.
+
+output_x86_64_instr(adc(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("adc", Src, Dest, !IO).
+output_x86_64_instr(add(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("add", Src, Dest, !IO).
+output_x86_64_instr(and(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("and", Src, Dest, !IO).
+output_x86_64_instr(bsf(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("bsf", Src, Dest, !IO).
+output_x86_64_instr(bsr(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("bsr", Src, Dest, !IO).
+output_x86_64_instr(bswap(Reg), !IO) :-
+ io.write_string("\tbswap\t", !IO),
+ reg_type(Reg, RegType),
+ io.write_string(RegType ++ "\t", !IO).
+output_x86_64_instr(bt(Src, Idx), !IO) :-
+ instr_with_rmro_and_rio("bt", Src, Idx, !IO).
+output_x86_64_instr(btc(Src, Idx), !IO) :-
+ instr_with_rmro_and_rio("btc", Src, Idx, !IO).
+output_x86_64_instr(btr(Src, Idx), !IO) :-
+ instr_with_rmro_and_rio("btr", Src, Idx, !IO).
+output_x86_64_instr(bts(Src, Idx), !IO) :-
+ instr_with_rmro_and_rio("bts", Src, Idx, !IO).
+output_x86_64_instr(call(TargetLocation), !IO) :-
+ instr_with_rmrol("call", TargetLocation, !IO).
+output_x86_64_instr(cbw, !IO) :-
+ io.write_string("\tcbw\t", !IO).
+output_x86_64_instr(cwde, !IO) :-
+ io.write_string("\tcwde\t", !IO).
+output_x86_64_instr(cdqe, !IO) :-
+ io.write_string("\tcdqe\t", !IO).
+output_x86_64_instr(cwd, !IO) :-
+ io.write_string("\tcwd\t", !IO).
+output_x86_64_instr(cdq, !IO) :-
+ io.write_string("\tcdq\t", !IO).
+output_x86_64_instr(cqo, !IO) :-
+ io.write_string("\tcqo\t", !IO).
+output_x86_64_instr(clc, !IO) :-
+ io.write_string("\tclc\t", !IO).
+output_x86_64_instr(cld, !IO) :-
+ io.write_string("\tcld\t", !IO).
+output_x86_64_instr(cmc, !IO) :-
+ io.write_string("\tcmc\t", !IO).
+output_x86_64_instr(cmovo(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovo", Src, Dest, !IO).
+output_x86_64_instr(cmovno(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovno", Src, Dest, !IO).
+output_x86_64_instr(cmovb(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovb", Src, Dest, !IO).
+output_x86_64_instr(cmovc(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovc", Src, Dest, !IO).
+output_x86_64_instr(cmovnae(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnae", Src, Dest, !IO).
+output_x86_64_instr(cmovnb(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnb", Src, Dest, !IO).
+output_x86_64_instr(cmovnc(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnc", Src, Dest, !IO).
+output_x86_64_instr(cmovae(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovae", Src, Dest, !IO).
+output_x86_64_instr(cmovz(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovz", Src, Dest, !IO).
+output_x86_64_instr(cmove(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmove", Src, Dest, !IO).
+output_x86_64_instr(cmovnz(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnz", Src, Dest, !IO).
+output_x86_64_instr(cmovne(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovne", Src, Dest, !IO).
+output_x86_64_instr(cmovbe(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovbe", Src, Dest, !IO).
+output_x86_64_instr(cmovna(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovna", Src, Dest, !IO).
+output_x86_64_instr(cmovnbe(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnbe", Src, Dest, !IO).
+output_x86_64_instr(cmova(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmova", Src, Dest, !IO).
+output_x86_64_instr(cmovs(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovs", Src, Dest, !IO).
+output_x86_64_instr(cmovns(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovns", Src, Dest, !IO).
+output_x86_64_instr(cmovp(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovp", Src, Dest, !IO).
+output_x86_64_instr(cmovpe(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovpe", Src, Dest, !IO).
+output_x86_64_instr(cmovnp(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnp", Src, Dest, !IO).
+output_x86_64_instr(cmovpo(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovpo", Src, Dest, !IO).
+output_x86_64_instr(cmovl(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovl", Src, Dest, !IO).
+output_x86_64_instr(cmovnge(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnge", Src, Dest, !IO).
+output_x86_64_instr(cmovnl(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnl", Src, Dest, !IO).
+output_x86_64_instr(cmovge(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovge", Src, Dest, !IO).
+output_x86_64_instr(cmovle(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovle", Src, Dest, !IO).
+output_x86_64_instr(cmovng(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovng", Src, Dest, !IO).
+output_x86_64_instr(cmovnle(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovnle", Src, Dest, !IO).
+output_x86_64_instr(cmovg(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("cmovg", Src, Dest, !IO).
+output_x86_64_instr(cmp(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("cmp", Src, Dest, !IO).
+output_x86_64_instr(cmpxchg(Cmp, Xchg), !IO) :-
+ instr_with_rmro_and_reg("cmpxchg", Cmp, Xchg, !IO).
+output_x86_64_instr(cmpxchg8b(MemRef), !IO) :-
+ mem_ref_type(MemRef, MemRefType),
+ io.write_string("\tcmpxchg8b" ++ MemRefType, !IO).
+output_x86_64_instr(dec(RegOrMemRef), !IO) :-
+ instr_with_rmro("dec", RegOrMemRef, !IO).
+output_x86_64_instr(div(RegOrMemRef), !IO) :-
+ instr_with_rmro("div", RegOrMemRef, !IO).
+output_x86_64_instr(enter(StackSize, NestingLevel), !IO) :-
+ StackSize = uint16(Size),
+ NestingLevel = uint8(Level),
+ check_unsigned_int_size(16, Size, Result0),
+ check_unsigned_int_size(8, Level, Result1),
+ (
+ Result0 = yes,
+ Result1 = yes
+ ->
+ io.write_string("\tenter\t", !IO),
+ io.write_int(Size, !IO),
+ io.write_string(",", !IO),
+ io.write_int(Level, !IO),
+ io.write_string("\t", !IO)
+ ;
+ unexpected(this_file, "output_x86_64_instr: enter unexpected")
+ ).
+output_x86_64_instr(idiv(RegOrMemRef), !IO) :-
+ instr_with_rmro("idiv", RegOrMemRef, !IO).
+output_x86_64_instr(imul(RegOrMemRef), !IO) :-
+ instr_with_rmro("idiv", RegOrMemRef, !IO).
+output_x86_64_instr(imul(Src, Dest), !IO) :-
+ instr_with_rmro_and_reg("imul", Src, Dest, !IO).
+output_x86_64_instr(imul(RegOrMemRefOp, Imm, Reg), !IO) :-
+ io.write_string("\timul\t", !IO),
+ rmro_type(RegOrMemRefOp, Type),
+ io.write_string(Type ++ ", ", !IO),
+ imm_op_type(Imm, ImmVal),
+ io.write_string(ImmVal ++ ", ", !IO),
+ reg_type(Reg, RegType),
+ io.write_string(RegType ++ "\t", !IO).
+output_x86_64_instr(inc(RegOrMemRef), !IO) :-
+ instr_with_rmro("inc", RegOrMemRef, !IO).
+output_x86_64_instr(jo(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jo", RelOffset, !IO).
+output_x86_64_instr(jno(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jno", RelOffset, !IO).
+output_x86_64_instr(jb(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jb", RelOffset, !IO).
+output_x86_64_instr(jc(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jc", RelOffset, !IO).
+output_x86_64_instr(jnae(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnae", RelOffset, !IO).
+output_x86_64_instr(jnb(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnb", RelOffset, !IO).
+output_x86_64_instr(jnc(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnc", RelOffset, !IO).
+output_x86_64_instr(jae(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jae", RelOffset, !IO).
+output_x86_64_instr(jz(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jz", RelOffset, !IO).
+output_x86_64_instr(je(RelOffset), !IO) :-
+ instr_with_rel_offset_op("je", RelOffset, !IO).
+output_x86_64_instr(jnz(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnz", RelOffset, !IO).
+output_x86_64_instr(jne(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jne", RelOffset, !IO).
+output_x86_64_instr(jbe(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jbe", RelOffset, !IO).
+output_x86_64_instr(jna(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jna", RelOffset, !IO).
+output_x86_64_instr(jnbe(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnbe", RelOffset, !IO).
+output_x86_64_instr(ja(RelOffset), !IO) :-
+ instr_with_rel_offset_op("ja", RelOffset, !IO).
+output_x86_64_instr(js(RelOffset), !IO) :-
+ instr_with_rel_offset_op("js", RelOffset, !IO).
+output_x86_64_instr(jns(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jns", RelOffset, !IO).
+output_x86_64_instr(jp(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jp", RelOffset, !IO).
+output_x86_64_instr(jpe(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jpe", RelOffset, !IO).
+output_x86_64_instr(jnp(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnp", RelOffset, !IO).
+output_x86_64_instr(jpo(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jpo", RelOffset, !IO).
+output_x86_64_instr(jl(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jl", RelOffset, !IO).
+output_x86_64_instr(jnge(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnge", RelOffset, !IO).
+output_x86_64_instr(jnl(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnl", RelOffset, !IO).
+output_x86_64_instr(jge(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jge", RelOffset, !IO).
+output_x86_64_instr(jle(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jle", RelOffset, !IO).
+output_x86_64_instr(jng(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jng", RelOffset, !IO).
+output_x86_64_instr(jnle(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jnle", RelOffset, !IO).
+output_x86_64_instr(jg(RelOffset), !IO) :-
+ instr_with_rel_offset_op("jg", RelOffset, !IO).
+output_x86_64_instr(jrcxz(RelOffset), !IO) :-
+ instr_with_8bit_rel_offset_op("jrcxz", RelOffset, !IO).
+output_x86_64_instr(jmp(Target), !IO) :-
+ instr_with_rmrol("jmp", Target, !IO).
+output_x86_64_instr(lea(Src, Dest), !IO) :-
+ instr_with_mem_ref_and_reg_op("lea", Src, Dest, !IO).
+output_x86_64_instr(leave, !IO) :-
+ io.write_string("\tleave\t", !IO).
+output_x86_64_instr(loop(RelOffset), !IO) :-
+ instr_with_8bit_rel_offset_op("loop", RelOffset, !IO).
+output_x86_64_instr(loope(RelOffset), !IO) :-
+ instr_with_8bit_rel_offset_op("loope", RelOffset, !IO).
+output_x86_64_instr(loopne(RelOffset), !IO) :-
+ instr_with_8bit_rel_offset_op("loopne", RelOffset, !IO).
+output_x86_64_instr(loopnz(RelOffset), !IO) :-
+ instr_with_8bit_rel_offset_op("loopnz", RelOffset, !IO).
+output_x86_64_instr(loopz(RelOffset), !IO) :-
+ instr_with_8bit_rel_offset_op("loopz", RelOffset, !IO).
+output_x86_64_instr(mov(Source, Dest), !IO) :-
+ instr_with_op_and_rmro("mov", Source, Dest, !IO).
+output_x86_64_instr(mul(RegOrMemRef), !IO) :-
+ instr_with_rmro("mul", RegOrMemRef, !IO).
+output_x86_64_instr(neg(RegOrMemRef), !IO) :-
+ instr_with_rmro("neg", RegOrMemRef, !IO).
+output_x86_64_instr(nop, !IO) :-
+ io.write_string("nop", !IO).
+output_x86_64_instr(not_(RegOrMemRef), !IO) :-
+ instr_with_rmro("not", RegOrMemRef, !IO).
+output_x86_64_instr(or(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("or", Src, Dest, !IO).
+output_x86_64_instr(pop(RegOrMemRefOp), !IO) :-
+ instr_with_rmro("pop", RegOrMemRefOp, !IO).
+output_x86_64_instr(popfq, !IO) :-
+ io.write_string("\tpopfq\t", !IO).
+output_x86_64_instr(push(Operand), !IO) :-
+ io.write_string("\tpush\t", !IO),
+ operand_type(Operand, OperandType),
+ io.write_string(OperandType ++ "\t", !IO).
+output_x86_64_instr(pushfq, !IO) :-
+ io.write_string("\tpushfq\t", !IO).
+output_x86_64_instr(rcl(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("rcl", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(rcr(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("rcr", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(ret, !IO) :-
+ io.write_string("\tret\t", !IO).
+output_x86_64_instr(ret(uint16(NumBytes)), !IO) :-
+ check_unsigned_int_size(16, NumBytes, Result),
+ ( Result = yes ->
+ io.write_string("\tret\t", !IO),
+ io.write_int(NumBytes, !IO),
+ io.write_string("\t", !IO)
+ ;
+ unexpected(this_file, "output_x86_64_instr: ret unexpected")
+ ).
+output_x86_64_instr(rol(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("rol", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(ror(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("ror", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(sal(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("sal", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(shl(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("shl", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(sar(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("sar", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(sbb(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("sbb", Src, Dest, !IO).
+output_x86_64_instr(seto(RegOrMemRef), !IO) :-
+ instr_with_rmro("seto", RegOrMemRef, !IO).
+output_x86_64_instr(setno(RegOrMemRef), !IO) :-
+ instr_with_rmro("setno", RegOrMemRef, !IO).
+output_x86_64_instr(setb(RegOrMemRef), !IO) :-
+ instr_with_rmro("setb", RegOrMemRef, !IO).
+output_x86_64_instr(setc(RegOrMemRef), !IO) :-
+ instr_with_rmro("setc", RegOrMemRef, !IO).
+output_x86_64_instr(setnae(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnae", RegOrMemRef, !IO).
+output_x86_64_instr(setnb(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnb", RegOrMemRef, !IO).
+output_x86_64_instr(setnc(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnc", RegOrMemRef, !IO).
+output_x86_64_instr(setae(RegOrMemRef), !IO) :-
+ instr_with_rmro("setae", RegOrMemRef, !IO).
+output_x86_64_instr(setz(RegOrMemRef), !IO) :-
+ instr_with_rmro("setz", RegOrMemRef, !IO).
+output_x86_64_instr(sete(RegOrMemRef), !IO) :-
+ instr_with_rmro("sete", RegOrMemRef, !IO).
+output_x86_64_instr(setnz(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnz", RegOrMemRef, !IO).
+output_x86_64_instr(setne(RegOrMemRef), !IO) :-
+ instr_with_rmro("setne", RegOrMemRef, !IO).
+output_x86_64_instr(setbe(RegOrMemRef), !IO) :-
+ instr_with_rmro("setbe", RegOrMemRef, !IO).
+output_x86_64_instr(setna(RegOrMemRef), !IO) :-
+ instr_with_rmro("setna", RegOrMemRef, !IO).
+output_x86_64_instr(setnbe(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnbe", RegOrMemRef, !IO).
+output_x86_64_instr(seta(RegOrMemRef), !IO) :-
+ instr_with_rmro("seta", RegOrMemRef, !IO).
+output_x86_64_instr(sets(RegOrMemRef), !IO) :-
+ instr_with_rmro("sets", RegOrMemRef, !IO).
+output_x86_64_instr(setns(RegOrMemRef), !IO) :-
+ instr_with_rmro("setns", RegOrMemRef, !IO).
+output_x86_64_instr(setp(RegOrMemRef), !IO) :-
+ instr_with_rmro("setp", RegOrMemRef, !IO).
+output_x86_64_instr(setpe(RegOrMemRef), !IO) :-
+ instr_with_rmro("setpe", RegOrMemRef, !IO).
+output_x86_64_instr(setnp(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnp", RegOrMemRef, !IO).
+output_x86_64_instr(setpo(RegOrMemRef), !IO) :-
+ instr_with_rmro("setpo", RegOrMemRef, !IO).
+output_x86_64_instr(setl(RegOrMemRef), !IO) :-
+ instr_with_rmro("sel", RegOrMemRef, !IO).
+output_x86_64_instr(setnge(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnge", RegOrMemRef, !IO).
+output_x86_64_instr(setnl(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnl", RegOrMemRef, !IO).
+output_x86_64_instr(setge(RegOrMemRef), !IO) :-
+ instr_with_rmro("setge", RegOrMemRef, !IO).
+output_x86_64_instr(setle(RegOrMemRef), !IO) :-
+ instr_with_rmro("setle", RegOrMemRef, !IO).
+output_x86_64_instr(setng(RegOrMemRef), !IO) :-
+ instr_with_rmro("setng", RegOrMemRef, !IO).
+output_x86_64_instr(setnle(RegOrMemRef), !IO) :-
+ instr_with_rmro("setnle", RegOrMemRef, !IO).
+output_x86_64_instr(setg(RegOrMemRef), !IO) :-
+ instr_with_rmro("setg", RegOrMemRef, !IO).
+output_x86_64_instr(shld(ClRegOrImm, RegOrMemRef, Reg), !IO) :-
+ instr_with_crio_rmro_and_reg("shld", ClRegOrImm, RegOrMemRef, Reg, !IO).
+output_x86_64_instr(shr(ClRegOrImm, RegOrMemRef), !IO) :-
+ instr_with_crio_and_rmro("shr", ClRegOrImm, RegOrMemRef, !IO).
+output_x86_64_instr(shrd(ClRegOrImm, RegOrMemRef, Reg), !IO) :-
+ instr_with_crio_rmro_and_reg("shrd", ClRegOrImm, RegOrMemRef, Reg, !IO).
+output_x86_64_instr(stc, !IO) :-
+ io.write_string("\tstc\t", !IO).
+output_x86_64_instr(std, !IO) :-
+ io.write_string("\tstd\t", !IO).
+output_x86_64_instr(sub(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("sub", Src, Dest, !IO).
+output_x86_64_instr(test(Src1, Src2), !IO) :-
+ instr_with_rmro_and_rio("test", Src1, Src2, !IO).
+output_x86_64_instr(xadd(Src, Dest), !IO) :-
+ instr_with_reg_and_rmro("xadd", Src, Dest, !IO).
+output_x86_64_instr(xchg(Src1, Src2), !IO) :-
+ instr_with_rmro_and_rmro("xchg", Src1, Src2, !IO).
+output_x86_64_instr(xor(Src, Dest), !IO) :-
+ instr_with_op_and_rmro("xor", Src, Dest, !IO).
+
+
+:- pred output_comment(string::in, io::di, io::uo) is det.
+
+output_comment(Comment, !IO) :-
+ ( string.length(Comment) > 0 ->
+ io.write_string("\t# ", !IO),
+ io.write_string(Comment, !IO)
+ ;
+ true
+ ),
+ io.write_string("\n", !IO).
+
+%-----------------------------------------------------------------------------%
+%
+% Output of x86_64 operands.
+%
+
+ % Output a string representation of an immediate value.
+ %
+:- pred imm_op_type(imm_operand::in, string::out) is det.
+
+imm_op_type(imm8(int8(Val)), ImmVal) :-
+ ImmVal = "$" ++ string.int_to_string(Val).
+imm_op_type(imm16(int16(Val)), ImmVal) :-
+ ImmVal = "$" ++ string.int_to_string(Val).
+imm_op_type(imm32(int32(Val)), ImmVal) :-
+ ImmVal = "$" ++ string.int_to_string(Val).
+
+ % Output a string representation of a general-purpose register.
+ %
+:- pred reg_type(gp_reg::in, string::out) is det.
+
+reg_type(rax, "%rax").
+reg_type(rbx, "%rbx").
+reg_type(rcx, "%rcx").
+reg_type(rdx, "%rdx").
+reg_type(rbp, "%rbp").
+reg_type(rsi, "%rsi").
+reg_type(rdi, "%rdi").
+reg_type(rsp, "%rsp").
+reg_type(r8, "%r8").
+reg_type(r9, "%r9").
+reg_type(r10, "%r10").
+reg_type(r11, "%r11").
+reg_type(r12, "%r12").
+reg_type(r13, "%r13").
+reg_type(r14, "%r14").
+reg_type(r15, "%r15").
+
+ % Output a string representation of a memory reference.
+ %
+:- pred mem_ref_type(mem_ref::in, string::out) is det.
+
+mem_ref_type(mem_abs(DirectMemRef), MemRefVal) :-
+ base_address_type(DirectMemRef, MemRefVal).
+mem_ref_type(mem_rip(InstrPtr), MemRefVal) :-
+ instr_ptr_type(InstrPtr, MemRefVal).
+
+ % Output a string representation of a base address in a memory reference.
+ %
+:- pred base_address_type(base_address::in, string::out) is det.
+
+base_address_type(base_reg(Offset, Reg), BaseAddress) :-
+ reg_type(Reg, RegType),
+ ( Offset = 0 ->
+ BaseAddress = "(" ++ RegType ++ ")"
+ ;
+ BaseAddress = string.int_to_string(Offset) ++ "(" ++ RegType ++
")"
+ ).
+base_address_type(base_expr(Expr), DispType) :-
+ DispType = "$" ++ Expr.
+
+ % Output a string representation of RIP relative addressing.
+ %
+:- pred instr_ptr_type(instr_ptr::in, string::out) is det.
+
+instr_ptr_type(rip_constant(int32(Constant)), InstrPtrType) :-
+ check_signed_int_size(32, Constant, Result),
+ (
+ Result = yes,
+ InstrPtrType = string.int_to_string(Constant) ++ "(%rip)"
+ ;
+ Result = no,
+ unexpected(this_file, "instr_ptr_type: int32 unexpected")
+ ).
+instr_ptr_type(rip_expr(Symbol), InstrPtrType) :-
+ InstrPtrType = Symbol ++ "(%rip)".
+
+ % Output a string representation of a relative offset.
+ %
+:- pred rel_offset_type(rel_offset::in, string::out) is det.
+
+rel_offset_type(ro8(int8(Val)), RelOffsetVal) :-
+ check_signed_int_size(8, Val, Result),
+ ( Result = yes ->
+ ( Val = 0 ->
+ RelOffsetVal = ""
+ ;
+ RelOffsetVal = string.int_to_string(Val)
+ )
+ ;
+ unexpected(this_file, "rel_offset_type: ro8 unexpected")
+ ).
+rel_offset_type(ro16(int16(Val)), RelOffsetVal) :-
+ check_signed_int_size(16, Val, Result),
+ ( Result = yes ->
+ ( Val = 0 ->
+ RelOffsetVal = ""
+ ;
+ RelOffsetVal = string.int_to_string(Val)
+ )
+ ;
+ unexpected(this_file, "rel_offset_type: ro16 unexpected")
+ ).
+rel_offset_type(ro32(int32(Val)), RelOffsetVal) :-
+ check_signed_int_size(32, Val, Result),
+ ( Result = yes ->
+ ( Val = 0 ->
+ RelOffsetVal = ""
+ ;
+ RelOffsetVal = string.int_to_string(Val)
+ )
+ ;
+ unexpected(this_file, "rel_offset_type: ro32 unexpected")
+ ).
+
+ % Output a string representation of a general operand type.
+ %
+:- pred operand_type(operand::in, string::out) is det.
+
+operand_type(operand_reg(Reg), RegType) :-
+ reg_type(Reg, RegType).
+operand_type(operand_imm(Imm), ImmVal) :-
+ imm_op_type(Imm, ImmVal).
+operand_type(operand_mem_ref(MemRef), MemRefVal) :-
+ mem_ref_type(MemRef, MemRefVal).
+
+ % Output a string representation of an operand whose type is a register/
+ % memory reference.
+ %
+:- pred rmro_type(reg_or_mem_ref_op::in, string::out) is det.
+
+rmro_type(rmro_reg(Reg), RegType) :-
+ reg_type(Reg, RegType).
+rmro_type(rmro_mem_ref(MemRef), MemRefVal) :-
+ mem_ref_type(MemRef, MemRefVal).
+
+ % Output a string representation of an operand whose type is a register
+ % or an immediate value.
+ %
+:- pred rio_type(reg_or_imm_op::in, string::out) is det.
+
+rio_type(rio_reg(Reg), RegType) :-
+ reg_type(Reg, RegType).
+rio_type(rio_imm(Imm), ImmVal) :-
+ imm_op_type(Imm, ImmVal).
+
+ % Output a string representation of an operand whose type is a cl register
+ % or an unsigned immediate value.
+ %
+:- pred crio_type(cl_reg_or_imm_op::in, string::out) is det.
+
+crio_type(crio_reg_cl(Reg), RegType) :-
+ ( Reg = rcx ->
+ RegType = "%cl"
+ ;
+ unexpected(this_file, "crio_type: crio_reg_cl unexpected")
+ ).
+crio_type(crio_imm8(int8(Val)), ImmVal) :-
+ check_unsigned_int_size(8, Val, Result),
+ ( Result = yes ->
+ ImmVal = "$" ++ string.int_to_string(Val)
+ ;
+ unexpected(this_file, "crio_type: crio_imm8 unexpected")
+ ).
+
+ % Output a string representation of an operand whose type is either
+ % a register, memory reference, signed relative offset or a label.
+ %
+:- pred rmrol_type(rmrol::in, string::out) is det.
+
+rmrol_type(rmrol_reg(Reg), RegType) :-
+ reg_type(Reg, RegType).
+rmrol_type(rmrol_mem_ref(MemRef), MemRefVal) :-
+ mem_ref_type(MemRef, MemRefVal).
+rmrol_type(rmrol_rel_offset(RelOffset), RelOffsetVal) :-
+ rel_offset_type(RelOffset, RelOffsetVal).
+rmrol_type(rmrol_label(LabelName), LabelOut) :-
+ LabelOut = LabelName.
+
+%-----------------------------------------------------------------------------%
+%
+% Subsection of "Output of x86_64 instructions".
+%
+
+ % Output an instruction with a register/memory reference as an operand.
+ %
+:- pred instr_with_rmro(string::in, reg_or_mem_ref_op::in,
+ io::di, io::uo) is det.
+
+instr_with_rmro(InstrName, RegOrMemRef, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ rmro_type(RegOrMemRef, RegOrMemRefType),
+ io.write_string(RegOrMemRefType ++ "\t\t", !IO).
+
+ % Output an instruction with a signed offset relative to the instruction
+ % pointer as an operand.
+ %
+:- pred instr_with_rel_offset_op(string::in, rel_offset::in,
+ io::di, io::uo) is det.
+
+instr_with_rel_offset_op(InstrName, RelOffset, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ rel_offset_type(RelOffset, RelOffsetType),
+ io.write_string(RelOffsetType ++ "\t\t", !IO).
+
+ % Output an instruction with a signed 8-bit offset relative to the
+ % instruction pointer as an operand.
+ %
+:- pred instr_with_8bit_rel_offset_op(string::in, rel_offset::in,
+ io::di, io::uo) is det.
+
+instr_with_8bit_rel_offset_op(InstrName, RelOffset, !IO) :-
+ (
+ RelOffset = ro8(int8(Val)),
+ check_signed_int_size(8, Val, Result),
+ Result = yes
+ ->
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ io.write_int(Val, !IO),
+ io.write_string("\t\t", !IO)
+ ;
+ unexpected(this_file, "instr_with_8bit_rel_offset_op: unexpected")
+ ).
+
+ % Output an instruction with either a register, memory reference,
+ % relative offset or a label as its operand.
+ %
+:- pred instr_with_rmrol(string::in, rmrol::in, io::di, io::uo) is det.
+
+instr_with_rmrol(InstrName, Target, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ rmrol_type(Target, TargetType),
+ io.write_string(TargetType ++ "\t\t", !IO).
+
+ % Output an instruction with a general operand and a register/memory
+ % reference as the first and second operand respectively.
+ %
+:- pred instr_with_op_and_rmro(string::in, operand::in, reg_or_mem_ref_op::in,
+ io::di, io::uo) is det.
+
+instr_with_op_and_rmro(InstrName, SrcOperand, DestRegOrMemRefOp, !IO) :-
+ (
+ SrcOperand = operand_mem_ref(_),
+ DestRegOrMemRefOp = rmro_mem_ref(_)
+ ->
+ % Both operands cannot be of type memory reference.
+ unexpected(this_file, "instr_with_op_and_rmro: unexpected")
+ ;
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ operand_type(SrcOperand, OperandType),
+ io.write_string(OperandType ++ ", ", !IO),
+ rmro_type(DestRegOrMemRefOp, DestType),
+ io.write_string(DestType ++ "\t", !IO)
+ ).
+
+ % Output an instruction with a register/memory reference and a register as
+ % the first and second operand respectively.
+ %
+:- pred instr_with_rmro_and_reg(string::in, reg_or_mem_ref_op::in, gp_reg::in,
+ io::di, io::uo) is det.
+
+instr_with_rmro_and_reg(InstrName, SrcRegOrMemRefOp, DestReg, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ rmro_type(SrcRegOrMemRefOp, SrcType),
+ io.write_string(SrcType ++ ", ", !IO),
+ reg_type(DestReg, RegType),
+ io.write_string(RegType ++ "\t", !IO).
+
+ % Output an instruction with a register/memory reference and a register/
+ % immediate value as the first and second operand respectively.
+ %
+:- pred instr_with_rmro_and_rio(string::in, reg_or_mem_ref_op::in,
+ reg_or_imm_op::in, io::di, io::uo) is det.
+
+instr_with_rmro_and_rio(InstrName, SrcRegOrMemRefOp, DestRegOrImmOp, !IO)
:-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ rmro_type(SrcRegOrMemRefOp, SrcType),
+ io.write_string(SrcType ++ ",", !IO),
+ rio_type(DestRegOrImmOp, DestType),
+ io.write_string(DestType ++ "\t", !IO).
+
+ % Output an instruction with a register/memory reference as the first and
+ % second operand respectively.
+ %
+:- pred instr_with_rmro_and_rmro(string::in, reg_or_mem_ref_op::in,
+ reg_or_mem_ref_op::in, io::di, io::uo) is det.
+
+instr_with_rmro_and_rmro(InstrName, RegOrMemRefOp0, RegOrMemRefOp1, !IO)
:-
+ (
+ RegOrMemRefOp0 = rmro_mem_ref(_),
+ RegOrMemRefOp1 = rmro_mem_ref(_)
+ ->
+ unexpected(this_file, "instr_with_rmro_and_rmro: unexpected")
+ ;
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ rmro_type(RegOrMemRefOp0, Type0),
+ io.write_string(Type0 ++ ", ", !IO),
+ rmro_type(RegOrMemRefOp1, Type1),
+ io.write_string(Type1 ++ "\t", !IO)
+ ).
+
+ % Output an instruction with a register and a register/memory reference as
+ % the first and second operand respectively.
+ %
+:- pred instr_with_reg_and_rmro(string::in, gp_reg::in, reg_or_mem_ref_op::in,
+ io::di, io::uo) is det.
+
+instr_with_reg_and_rmro(InstrName, SrcReg, DestRegOrMemRefOp, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ reg_type(SrcReg, RegType),
+ io.write_string(RegType ++ ", ", !IO),
+ rmro_type(DestRegOrMemRefOp, DestType),
+ io.write_string(DestType ++ "\t", !IO).
+
+ % Output an instruction with a cl register/immediate value and a register/
+ % memory reference as the first and second operand respectively.
+ %
+:- pred instr_with_crio_and_rmro(string::in, cl_reg_or_imm_op::in,
+ reg_or_mem_ref_op::in, io::di, io::uo) is det.
+
+instr_with_crio_and_rmro(InstrName, ClRegOrImm, RegOrMemRef, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ crio_type(ClRegOrImm, ClRegOrImmType),
+ io.write_string(ClRegOrImmType ++ ", ", !IO),
+ rmro_type(RegOrMemRef, RegOrMemRefType),
+ io.write_string(RegOrMemRefType ++ "\t", !IO).
+
+ % Output an instruction with a cl register/immediate value, a register/
+ % memory reference and a register as the first, second and third operand
+ % respectively.
+ %
+:- pred instr_with_crio_rmro_and_reg(string::in, cl_reg_or_imm_op::in,
+ reg_or_mem_ref_op::in, gp_reg::in, io::di, io::uo) is det.
+
+instr_with_crio_rmro_and_reg(InstrName, ClRegOrImm, RegOrMemRef, Reg, !IO) :-
+ io.write_string("\t" ++ InstrName ++ "\t", !IO),
+ crio_type(ClRegOrImm, ClRegOrImmType),
+ io.write_string(ClRegOrImmType ++ "\t", !IO),
+ rmro_type(RegOrMemRef, RegOrMemRefType),
+ io.write_string(RegOrMemRefType ++ ", ", !IO),
+ reg_type(Reg, RegType),
+ io.write_string(RegType ++ "\t", !IO).
+
+ % Output an instruction with a memory reference and a register as the first
+ % and second operand respectively.
+ %
+:- pred instr_with_mem_ref_and_reg_op(string::in, mem_ref::in,
+ gp_reg::in, io::di, io::uo) is det.
+
+instr_with_mem_ref_and_reg_op(InstrName, SrcMemRef, DestReg, !IO) :-
+ mem_ref_type(SrcMemRef, MemRefType),
+ io.write_string("\t" ++ InstrName ++ "\t" ++ MemRefType, !IO),
+ reg_type(DestReg, DestRegType),
+ io.write_string(", " ++ DestRegType ++ "\t", !IO).
+
+%-----------------------------------------------------------------------------%
+
+ % Check whether an unsigned int (Val) with n bits (BitSize) is within the
+ % range of 0 and (2^n)-1.
+ %
+:- pred check_unsigned_int_size(int::in, int::in, bool::out) is det.
+
+check_unsigned_int_size(BitSize, Val, Result) :-
+ MaxInt = (1 << BitSize) - 1,
+ (
+ Val >= 0,
+ Val =< MaxInt
+ ->
+ Result = yes
+ ;
+ Result = no
+ ).
+
+ % Check whether a signed int (Val) with n bits (BitSize) is within the
+ % range of -2^(n-1) and 2^(n-1)-1.
+ %
+:- pred check_signed_int_size(int::in, int::in, bool::out) is det.
+
+check_signed_int_size(BitSize, Val, Result) :-
+ MinInt = - (1 << (BitSize - 1)),
+ MaxInt = (1 << (BitSize - 1)) - 1,
+ (
+ Val >= MinInt,
+ Val =< MaxInt
+ ->
+ Result = yes
+ ;
+ Result = no
+ ).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "x86_64_out.m".
+
+:- end_module x86_64_out.
+%-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list