[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