Logo Search packages:      
Sourcecode: pcc version File versions  Download package

table.c

/*    $Id: table.c,v 1.14 2010/09/19 13:54:41 ragge Exp $   */
/*
 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * MIPS port by Jan Enoksson (janeno-1@student.ltu.se) and
 * Simon Olsson (simols-1@student.ltu.se) 2005.
 *
 * It appears that the target machine was big endian.  The original
 * code contained many endian aspects which are now handled in
 * machine-independent code.
 * 
 * On MIPS, the assembler does an amazing amount of work for us.
 * We don't have to worry about PIC, nor about finding the address
 * of SNAMES.  Whenever possible, we defer the work to the assembler.
 */

#include "pass2.h"

#define TUWORD TUNSIGNED|TULONG
#define TSWORD TINT|TLONG
#define TWORD TUWORD|TSWORD

struct optab table[] = {
/* First entry must be an empty entry */
{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },

/* PCONVs are usually not necessary */
{ PCONV,    INAREG,
      SAREG,      TWORD|TPOINT,
      SAREG,      TWORD|TPOINT,
            0,    RLEFT,
            "     # convert between word and pointer", },

/*
 * Conversions of integral<->integral types
 */

{ SCONV,    INAREG,
      SOREG,  TCHAR,
      SAREG,      TSWORD|TSHORT,
            NAREG,      RESC1,
            "     lb A1,AL    # convert oreg char to short/int\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TCHAR,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
            NAREG,      RESC1,
            "     lbu A1,AL   # convert oreg char to uchar/ushort/uint\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,  TUCHAR,
      SAREG,      TWORD|TSHORT|TUSHORT,
            NAREG,      RESC1,
            "     lbu A1,AL   # convert oreg uchar to (u)short/(u)int\n"
            "     nop\n", },

{ SCONV,    INBREG,
      SOREG,      TCHAR,
      SBREG,      TLONGLONG,
            NBREG,      RESC1,
                  "     lb A1,AL    # convert oreg char to longlong\n"
                  "     nop\n"
                  "     sra U1,A1,31\n", },

/* chor -> ulonglong handled later */

{ SCONV,    INBREG,
      SOREG,      TUCHAR,
      SBREG,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     lbu A1,AL   # convert oreg uchar to (u)longlong\n"
                  "     move U1,$zero\n", },

{ SCONV,    INAREG,
      SOREG,      TSHORT|TUSHORT,
      SAREG,      TCHAR,
            NAREG,      RESC1,
            "     lb A1,AL    # convert oreg (u)short to char (endianness problem?)\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TSHORT|TUSHORT,
      SAREG,  TUCHAR,
            NAREG,      RESC1,
            "     lbu A1,AL   # convert oreg (u)short to uchar (endianness problem?)\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TSHORT,
      SAREG,      TSWORD,
            NAREG,      RESC1,
            "     lh A1,AL    # convert oreg short to int\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TSHORT,
      SAREG,      TUWORD,
            NAREG,      RESC1,
            "     lhu A1,AL   # convert oreg short to uint\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TUSHORT,
      SAREG,      TWORD,
            NAREG,      RESC1,
            "     lhu A1,AL   # convert oreg ushort to (u)int\n"
            "     nop\n", },

{ SCONV,    INBREG,
      SOREG,      TSHORT,
      SBREG,      TLONGLONG,
            NBREG,      RESC1,
                  "     lh A1,AL    # convert oreg short to longlong\n"
                  "     nop\n"
                  "     sra U1,A1,31\n", },

{ SCONV,    INBREG,
      SOREG,      TSHORT,
      SBREG,      TULONGLONG,
            NBREG,      RESC1,
                  "     lhu A1,AL   # convert oreg short to ulonglong\n"
                  "     nop\n"
            "     move U1,$zero\n", },

{ SCONV,    INBREG,
      SOREG,      TUSHORT,
      SBREG,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     lhu A1,AL   # convert oreg ushort to (u)longlong\n"
                  "     move U1,$zero\n", },

{ SCONV,    INAREG,
      SOREG,      TWORD,
      SAREG,      TCHAR,
            NAREG,      RESC1,
            "     lb A1,AL    # convert oreg word to char (endianness problem here?)\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TWORD,
      SAREG,      TUCHAR,
            NAREG,      RESC1,
            "     lbu A1,AL   # convert oreg word to uchar (endianness problem here?)\n"
            "     nop\n", },
    
{ SCONV,    INAREG,
      SOREG,      TWORD,
      SAREG,      TSHORT,
            NAREG,      RESC1,
            "     lh A1,AL    # convert oreg word to short (endianness problem here?)\n"
            "     nop\n", },

/* convert (u)long to ushort */
{ SCONV,    INAREG,
      SOREG,      TWORD,
      SAREG,      TUSHORT,
            NAREG,      RESC1,
            "     lhu A1,AL   # convert oreg word to ushort (endianness problem here?)\n"
            "     nop\n", },

{ SCONV,    INBREG,
      SOREG,      TSWORD,
      SBREG,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
                  "     lw A1,AL    # convert oreg int/long to (u)llong (endianness problem here?)\n"
                  "     nop\n"
                  "     sra U1,A1,31\n" },

{ SCONV,    INBREG,
      SOREG,      TUWORD,
      SBREG,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     lw A1,AL    # convert oreg (u)int to (u)llong (endianness problem here?)\n"
                  "     move U1,$zero\n", },

{ SCONV,    INAREG,
      SOREG,      TLONGLONG|TULONGLONG,
      SAREG,      TCHAR,
            NAREG,      RESC1,
            "     lb A1,AL    # convert oreg (u)llong to char     (endianness problem here?)\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TLONGLONG|TULONGLONG,
      SAREG,      TUCHAR,
            NAREG,      RESC1,
            "     lbu A1,AL   # convert oreg (u)llong to uchar (endianness problem?)\n"
            "     nop\n", },
    
{ SCONV,    INAREG,
      SOREG,      TLONGLONG|TULONGLONG,
      SAREG,      TSHORT,
            NAREG,      RESC1,
            "     lh A1,AL    # convert oreg (u)llong to short (endianness problem?)\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TLONGLONG|TULONGLONG,
      SAREG,      TUSHORT,
            NAREG,      RESC1,
            "     lhu A1,AL   # convert oreg (u)llong to ushort (endianness problem here?)\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SOREG,      TLONGLONG|TULONGLONG,
      SAREG,      TWORD,
            NAREG,      RESC1,
                  "     lw A1,AL    # convert oreg (u)llong to (u)int (endianness problem here?)\n"
            "     nop\n", },

/*
 * Conversions of integral types (register-register)
 *
 * For each deunsigned type, they look something like this:
 *
 * signed -> bigger signed      - nothing to do
 * signed -> bigger unsigned    - clear the top bits (of source type)
 *
 * signed -> smaller signed     - sign-extend the bits (to dest type)
 * signed -> smaller unsigned   - clear the top bits (of dest type)
 * unsigned -> smaller signed   - sign-extend top bits (to dest type)
 * unsigned -> smaller unsigned - clear the top bits (of dest type)
 *
 * unsigned -> bigger           - nothing to do
 */

{ SCONV,    INAREG,
      SAREG,      TPOINT|TWORD,
      SAREG,      TPOINT|TWORD,
            0,    RLEFT,
            "     # convert int to int\n", },

{ SCONV,    INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SBREG,      TLONGLONG|TULONGLONG,
            0,    RLEFT,
            "     # convert (u)longlong to (u)longlong", },

{ SCONV,    INAREG,
      SAREG,      TCHAR,
      SAREG,      TSWORD|TSHORT,
            0,    RLEFT,
            "     # convert char to short/int\n", },

{ SCONV,    INAREG,
      SAREG,      TCHAR,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
            NAREG|NASL, RESC1,
            "     andi A1,AL,255    # convert char to uchar/ushort/uint\n", },

{ SCONV,    INAREG,
      SAREG,      TUCHAR,
      SAREG,      TCHAR,
            NAREG|NASL, RESC1,
            "     sll A1,AL,24      # convert uchar to char\n"
            "     sra A1,A1,24\n", },

{ SCONV,    INAREG,
      SAREG,      TUCHAR,
      SAREG,      TWORD|TSHORT|TUSHORT,
            0,    RLEFT,
            "     # convert uchar to (u)short/(u)int\n", },

{ SCONV,    INAREG,
      SAREG,      TSHORT,
      SAREG,      TCHAR,
            NAREG|NASL, RESC1,
            "     sll A1,AL,24      # convert short to char\n"
            "     sra A1,A1,24\n", },

{ SCONV,    INAREG,
      SAREG,      TSHORT,
      SAREG,      TUCHAR,
            NAREG|NASL, RESC1,
            "     andi A1,AL,255    # convert short to uchar\n", },

{ SCONV,    INAREG,
      SAREG,      TSHORT,
      SAREG,      TUWORD|TUSHORT,
            NAREG|NASL, RESC1,
            "     andi A1,AL,65535  # convert short to ushort\n", },

{ SCONV,    INAREG,
      SAREG,      TSHORT,
      SAREG,      TSWORD,
            NAREG|NASL, RESC1,
            "     sll A1,AL,16      # convert short to ushort\n"
            "     sra A1,A1,16\n", },

{ SCONV,    INAREG,
      SAREG,      TUSHORT,
      SAREG,      TCHAR,
            NAREG|NASL, RESC1,
            "     sll A1,AL,24      # convert short to char\n"
            "     sra A1,A1,24\n", },

{ SCONV,    INAREG,
      SAREG,      TUSHORT,
      SAREG,      TUCHAR,
            NAREG|NASL, RESC1,
            "     andi A1,AL,255    # convert ushort to char\n", },

{ SCONV,    INAREG,
      SAREG,      TUSHORT,
      SAREG,      TSHORT,
            NAREG|NASL, RESC1,
            "     sll A1,AL,16      # convert short to ushort\n"
            "     sra A1,A1,16\n", },

{ SCONV,    INAREG,
      SAREG,      TUSHORT,
      SAREG,      TWORD,
            0,    RDEST,
            "     # convert ushort to (u)int\n", },

{ SCONV,    INAREG,
      SAREG,      TSWORD,
      SAREG,      TCHAR,
            NAREG|NASL, RESC1,
            "     sll A1,AL,8 # convert int to char\n"
            "     sra A1,A1,8\n", },

{ SCONV,    INAREG,
      SAREG,      TSWORD,
      SAREG,      TUCHAR,
            NAREG|NASL, RESC1,
            "     andi A1,AL,255    # convert int to uchar\n", },

{ SCONV,    INAREG,
      SAREG,      TSWORD,
      SAREG,      TSHORT,
            NAREG|NASL, RESC1,
            "     sll A1,AL,16      # convert int to short\n"
            "     sra A1,A1,16\n", },

{ SCONV,    INAREG,
      SAREG,      TSWORD,
      SAREG,      TUSHORT,
            NAREG|NASL, RESC1,
            "     andi A1,AL,65535  # convert int to ushort\n", },

{ SCONV,    INAREG,
      SAREG,      TUWORD,
      SAREG,      TCHAR,
            NAREG|NASL, RESC1,
            "     sll A1,AL,24      # convert int to char\n"
            "     sra A1,A1,24\n", },

{ SCONV,    INAREG,
      SAREG,      TUWORD,
      SAREG,      TUCHAR,
            NAREG|NASL, RESC1,
            "     andi A1,AL,255    # convert int to uchar\n", },

{ SCONV,    INAREG,
      SAREG,      TUWORD,
      SAREG,      TSHORT,
            NAREG|NASL, RESC1,
            "     sll A1,AL,16      # convert int to short\n"
            "     sra A1,A1,16\n", },

{ SCONV,    INAREG,
      SAREG,      TUWORD,
      SAREG,      TUSHORT,
            NAREG|NASL, RESC1,
            "     andi A1,AL,65535  # convert int to ushort\n", },

{ SCONV,    INBREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SBREG,      TLONGLONG,
            NBREG,      RESC1,
            "     move A1,AL  # convert int/short/char to longlong\n"
            "     sra U1,AL,31\n", },

{ SCONV,    INBREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SBREG,      TULONGLONG,
            NBREG,      RESC1,
            "     move A1,AL  # convert int/short/char to ulonglong\n"
            "     move U1,$zero\n", },

{ SCONV,    INBREG,
      SAREG,      TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
      SBREG,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     move A1,AL  # convert (u)int/(u)short/(u)char to ulonglong\n"
            "     move U1,$zero\n", },

{ SCONV,    INAREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TWORD,
            NAREG,      RESC1,
            "     move A1,AL  # convert (u)longlong to int\n", },

{ SCONV,    INAREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TSHORT,
            NAREG,      RESC1,
            "     sll A1,AL,16      # convert (u)longlong to short\n"
            "     sra A1,A1,16\n", },

{ SCONV,    INAREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TCHAR,
            NAREG,      RESC1,
            "     sll A1,AL,24      # convert (u)longlong to char\n"
            "     sra A1,A1,24\n", },

{ SCONV,    INAREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TUSHORT,
            NAREG,      RESC1,
            "     andi A1,AL,65535  # convert (u)longlong to ushort\n", },

{ SCONV,    INAREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TUCHAR,
            NAREG,      RESC1,
            "     andi A1,AL,255    # convert (u)longlong to uchar\n", },

{ SCONV,    INCREG,
      SCREG,      TFLOAT,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1,
            "     cvt.d.s A1,AL     # convert float to (l)double\n", },

{ SCONV,    INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TFLOAT,
            NCREG,      RESC1,
            "     cvt.s.d A1,AL     # convert (l)double to float\n", },

{ SCONV,    INCREG,
      SAREG,      TWORD,
      SCREG,      TFLOAT,
            NCREG,      RESC1,
            "     mtc1 AL,A1  # convert (u)int to float\n"
            "     nop\n"
            "     cvt.s.w A1,A1\n", },

{ SCONV,    INCREG,
      SOREG,      TWORD,
      SCREG,      TFLOAT,
            NCREG,      RESC1,
            "     l.s A1,AL   # convert (u)int to float\n"
            "     nop\n"
            "     cvt.s.w A1,A1\n", },

{ SCONV,    INCREG,
      SAREG,      TWORD,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1,
            "     mtc1 AL,A1  # convert (u)int to (l)double\n"
            "     nop\n"
            "     cvt.d.w A1,A1\n", },

{ SCONV,    INCREG,
      SOREG,      TWORD,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1,
            "     l.d A1,AL   # convert (u)int to (l)double\n"
            "     nop\n"
            "     cvt.d.w A1,A1\n", },

{ SCONV,    INAREG,
      SCREG,      TFLOAT,
      SAREG,      TWORD,
            NCREG|NAREG,      RESC1,
            "     cvt.w.s A2,AL     # convert float to (u)int\n"
            "     mfc1 A1,A2\n"
            "     nop\n", },

{ SCONV,    FOREFF,
      SCREG,      TFLOAT,
      SOREG,      TWORD,
            NCREG,      RDEST,
            "     cvt.w.s A1,AL     # convert float to (u)int\n"
            "     s.s A1,AR\n"
            "     nop\n", },

{ SCONV,    INAREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SAREG,      TWORD,
            NCREG|NAREG,      RESC1,
            "     cvt.w.d A2,AL     # convert (l)double to (u)int\n"
            "     mfc1 A1,A2\n"
            "     nop\n", },

{ SCONV,    INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            0,    RLEFT,
            "     # convert between double and ldouble\n", },

{ SCONV,    INCREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SCREG,      TFLOAT,
            NSPECIAL|NCREG,   RESC1,
            "ZF", },

{ SCONV,    INCREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SCREG,      TDOUBLE|TLDOUBLE,
            NSPECIAL|NCREG,   RESC1,
            "ZF", },

{ SCONV,    INBREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SBREG,      TLONGLONG|TULONGLONG,
            NSPECIAL|NBREG,         RESC1,
            "ZF", },

{ SCONV,    INBREG,
      SCREG,      TFLOAT,
      SBREG,      TLONGLONG|TULONGLONG,
            NSPECIAL|NBREG,         RESC1,
            "ZF", },

/*
 * Multiplication and division
 */

{ MUL,      INAREG,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
            NAREG|NASR|NASL,  RESC1,
            "     multu AL,AR # unsigned multiply\n"
            "     mflo A1\n"
            "     nop\n"
            "     nop\n", },

/* this previous will match on unsigned/unsigned multiplication first */
{ MUL,      INAREG,
      SAREG,      TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
      SAREG,      TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
            NAREG|NASR|NASL,  RESC1,
            "     mult AL,AR  # signed multiply\n"
            "     mflo A1\n"
            "     nop\n"
            "     nop\n", },

{ MUL,      INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SBREG,      TLONGLONG|TULONGLONG,
            2*NBREG,    RESC1,
            "     multu AL,AR\n"
            "     mfhi U1\n"
            "     mflo A1\n"
            "     mult AL,UR\n"
            "     mflo A2\n"
            "     nop\n"
            "     nop\n"
            "     addu A2,U1,A2\n"
            "     mult UL,AR\n"
            "     mflo U2\n"
            "     nop\n"
            "     nop\n"
            "     addu U1,A2,U2\n", },

{ MUL,      INCREG,
      SCREG,      TFLOAT,
      SCREG,      TFLOAT,
            NCREG,      RESC1,
            "     mul.s A1,AL,AR          # floating-point multiply\n", },

{ MUL,      INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1, 
            "     mul.d A1,AL,AR    # double-floating-point multiply\n", },

{ DIV,      INAREG,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
            NAREG|NASR|NASL,  RESC1,
            "     divu AL,AR  # unsigned division\n"
            "     mflo A1\n"
            "     nop\n"
            "     nop\n", },

/* the previous rule will match unsigned/unsigned first */
{ DIV,      INAREG,
      SAREG,      TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
      SAREG,      TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
            NAREG|NASR|NASL,  RESC1,
            "     div AL,AR   # signed division\n"
            "     mflo A1\n"
            "     nop\n"
            "     nop\n", },

{ DIV, INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SBREG,      TLONGLONG|TULONGLONG,
            NSPECIAL|NBREG,   RESC1,
            "ZE", },

{ DIV,      INCREG,
      SCREG,      TFLOAT,
      SCREG,      TFLOAT,
            NCREG,      RESC1,
            "     div.s A1,AL,AR          # floating-point division\n", },

{ DIV,      INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1, 
            "     div.d A1,AL,AR    # double-floating-point division\n", },

{ MOD,  INAREG,
        SAREG,  TUWORD|TUSHORT|TUCHAR,
        SAREG,  TUWORD|TUSHORT|TUCHAR,
                NAREG,  RESC1,
                "       divu AL,AR  # signed modulo\n"
            "     mfhi A1\n"
            "     nop\n"
            "     nop\n", },

/* the previous rule will match unsigned%unsigned first */
{ MOD,  INAREG,
        SAREG,  TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
        SAREG,  TWORD|TUSHORT|TSHORT|TUCHAR|TCHAR,
                NAREG,  RESC1,
                " div AL,AR   # signed modulo\n"
            "     mfhi A1\n"
            "     nop\n"
            "     nop\n", },

{ MOD,  INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SBREG,      TLONGLONG|TULONGLONG,
                NSPECIAL|NBREG,  RESC1,
                "ZE", },
    
/*
 * Templates for unsigned values needs to come before OPSIMP 
 */

{ PLUS,     INBREG,
      SBREG,      TULONGLONG|TLONGLONG,
      SBREG,      TULONGLONG|TLONGLONG,
            2*NBREG,    RESC1,
                  "     addu A1,AL,AR     # 64-bit addition\n"
                  "     sltu A2,A1,AR\n"
                  "     addu U1,UL,UR\n"
                  "     addu U1,U1,A2\n", },

{ PLUS,     INAREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SSCON,      TANY,
            NAREG|NASL, RESC1,
            "     addi A1,AL,AR\n", },

{ PLUS,     INAREG,
      SAREG,      TUWORD|TPOINT|TUSHORT|TUCHAR,
      SSCON,      TANY,
            NAREG|NASL, RESC1,
            "     addiu A1,AL,AR\n", },

{ PLUS,     INAREG,
      SAREG,      TUWORD|TPOINT|TUSHORT|TUCHAR,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
            NAREG|NASL, RESC1,
                  "     addu A1,AL,AR\n", },

{ PLUS,     INAREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SAREG,      TSWORD|TSHORT|TCHAR,
            NAREG|NASL, RESC1,
                  "     add A1,AL,AR\n", },

{ PLUS,     INCREG,
      SCREG,      TFLOAT,
      SCREG,      TFLOAT,
            NCREG|NCSL, RESC1,
            "     add.s A1,AL,AR\n", },

{ PLUS,     INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG|NCSL, RESC1,
            "     add.d A1,AL,AR\n", },

{ MINUS,    INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SBREG,      TLONGLONG|TULONGLONG,
            2*NBREG,    RESC1,
                  "     sltu A2,AL,AR     # 64-bit subtraction\n"
                  "     subu A1,AL,AR\n"
                  "     subu U1,UL,UR\n"
                  "     subu U1,U1,A2\n", },

{ MINUS,    INAREG,
      SAREG,      TUWORD|TPOINT|TUSHORT|TUCHAR,
      SSCON,      TANY,
            NAREG|NASL, RESC1,
            "     subu A1,AL,AR\n", },

{ MINUS,    INAREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SSCON,      TANY,
            NAREG|NASL, RESC1,
            "     sub A1,AL,AR\n", },

{ MINUS,    INAREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SAREG,      TSWORD|TSHORT|TCHAR,
            NAREG|NASL, RESC1,
                  "     sub A1,AL,AR\n", },

{ MINUS,    INCREG,
      SCREG,      TFLOAT,
      SCREG,      TFLOAT,
            NCREG|NCSL, RESC1,
            "     sub.s A1,AL,AR\n", },

{ MINUS,    INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG|NCSL, RESC1,
            "     sub.d A1,AL,AR\n", },

{ UMINUS,   INAREG,
      SAREG,      TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
      SANY, TANY,
            NAREG|NASL, RESC1,
            "     neg A1,AL\n", },

{ UMINUS,   INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SANY, TANY,
            NBREG|NAREG|NBSL, RESC2,
            "     subu A1,$zero,AL\n"
            "     subu U1,$zero,UL\n"
            "     sltu A2,$zero,A1\n"
            "     subu U1,U1,A2\n", },

{ UMINUS,   INCREG,
      SCREG,      TFLOAT,
      SCREG,      TFLOAT,
            NCREG|NCSL, RESC1,
            "     neg.s A1,AL\n", },

{ UMINUS,   INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            NCREG|NCSL, RESC1,
            "     neg.d A1,AL\n", },

/* Simple 'op rd, rs, rt' or 'op rt, rs, imm' operations */

{ OPSIMP,   INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SBREG,      TLONGLONG|TULONGLONG,
            NBREG|NBSR|NBSL,  RESC1,
                  "     O A1,AL,AR\n"
                  "     O U1,UL,UR\n", },
    
{ OPSIMP,   INAREG,
      SAREG,      TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
      SAREG,      TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
            NAREG|NASR|NASL,  RESC1,
            "     O A1,AL,AR\n", },

{ OPSIMP,   INAREG,
      SAREG,      TWORD|TPOINT|TSHORT|TUSHORT|TUCHAR|TCHAR,
      SPCON,      TANY,
            NAREG|NASL, RESC1,
            "     Oi A1,AL,AR\n", },

/*
 * Shift instructions
 */

{ RS, INAREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NAREG|NASL, RESC1,
            "     sra A1,AL,AR      # shift right by constant\n", },

{ RS, INAREG,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
      SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NAREG|NASL, RESC1,
            "     srl A1,AL,AR      # shift right by constant\n", },

{ LS, INAREG,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
      SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NAREG|NASL, RESC1,
            "     sll A1,AL,AR      # shift left by constant\n", },
    
{ RS, INAREG,
      SAREG,      TSWORD|TSHORT|TCHAR,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NAREG|NASL, RESC1,
            "     srav A1,AL,AR     # shift right by register\n", },

{ RS, INAREG,
      SAREG,      TUWORD|TUSHORT|TUCHAR,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NAREG|NASL, RESC1,
            "     srlv A1,AL,AR     # shift right by register\n", },

{ LS, INAREG,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NAREG|NASL, RESC1,
            "     sllv A1,AL,AR     # shift left by register\n", },     

{ RS, INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NBREG,      RESC1,
            "ZO", },

{ LS, INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NBREG,      RESC1,
            "ZO", },

{ RS, INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NSPECIAL|NBREG,   RESC1,
            "ZE", },

{ LS, INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
      SAREG,      TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
            NSPECIAL|NBREG,   RESC1,
            "ZE", },

/*
 * Rule for unary one's complement
 */

{ COMPL,        INAREG,
        SAREG,  TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
        SANY,   TANY,
                NAREG|NASL,   RESC1,
                " nor A1,$zero,AL   # complement\n", },
    
{ COMPL,        INBREG,
      SBREG,      TLONGLONG|TULONGLONG,
        SANY,   TANY,
                NBREG|NBSL,   RESC1,
                " nor A1,$zero,AL   # complement\n"
                " nor U1,$zero,UL\n", },
    
/*
 * The next rules takes care of assignments. "=".
 */

{ ASSIGN,   FOREFF|INAREG,
      SOREG|SNAME,      TWORD|TPOINT,
      SAREG,            TWORD|TPOINT,
            0,    RDEST,
            "     sw AR,AL          # store (u)int/(u)long\n"
            "     nop\n", },

{ ASSIGN,   FOREFF|INAREG,
      SOREG|SNAME,      TSHORT|TUSHORT,
      SAREG,            TSHORT|TUSHORT,
            0,    RDEST,
            "     sh AR,AL          # store (u)short\n"
            "     nop\n", },  

{ ASSIGN,   FOREFF|INAREG,
      SOREG|SNAME,      TCHAR|TUCHAR,
      SAREG,            TCHAR|TUCHAR,
            0,    RDEST,
            "     sb AR,AL          # store (u)char\n"
            "     nop\n", },  

{ ASSIGN,   FOREFF|INBREG,
      SOREG|SNAME,      TLONGLONG|TULONGLONG,
      SBREG,            TLONGLONG|TULONGLONG,
            0,    RDEST,
                  "     sw UR,UL          # store (u)longlong\n"
            "     nop\n"
                  "     sw AR,AL\n"
            "     nop\n", },

{ ASSIGN,   FOREFF|INBREG,
      SBREG,            TLONGLONG|TULONGLONG,
      SBREG,            TLONGLONG|TULONGLONG,
            0,    RDEST,
                  "     move UL,UR        # register move\n"
                  "     move AL,AR\n", },
    
{ ASSIGN,   FOREFF|INAREG,
      SAREG,      TANY,
      SAREG,      TANY,
            0,    RDEST,
            "     move AL,AR        # register move\n", },

{ ASSIGN,   FOREFF|INCREG,
      SCREG,      TFLOAT,
      SCREG,      TFLOAT,
            0,    RDEST,
            "     mov.s AL,AR       # register move\n", },

{ ASSIGN,   FOREFF|INCREG,
      SCREG,      TDOUBLE|TLDOUBLE,
      SCREG,      TDOUBLE|TLDOUBLE,
            0,    RDEST,
            "     mov.d AL,AR       # register move\n", },

{ ASSIGN,   FOREFF|INCREG,
      SNAME|SOREG,      TFLOAT,
      SCREG,            TFLOAT,
            0,    RDEST,
            "     s.s AR,AL         # store floating-point reg to oreg/sname\n"
            "     nop\n", },

{ ASSIGN,   FOREFF|INCREG,
      SNAME|SOREG,      TDOUBLE|TLDOUBLE,
      SCREG,            TDOUBLE|TLDOUBLE,
            0,    RDEST,
            "     s.d AR,AL         # store double floating-point reg to oreg/sname\n"
            "     nop\n", },

{ ASSIGN,   FOREFF|INAREG,
      SFLD,       TANY,
      SOREG|SNAME,      TANY,
            3*NAREG,    RDEST,
            "     lw A1,AR          # bit-field assignment\n"
            "     li A3,M\n"
            "     lw A2,AL\n"
            "     sll A1,A1,H\n"
            "     and A1,A1,A3\n"
            "     nor A3,$zero,A3\n"
            "     and A2,A2,A3\n"
            "     or A2,A2,A1\n"
            "     sw A2,AL\n"
            "F    lw AD,AR\n"
            "F    nop\n"
            "F    sll AD,AD,32-S\n"
            "F    sra AD,AD,32-S\n", },

/* XXX we can optimise this away */
{ ASSIGN,   FOREFF|INAREG,
      SFLD,       TANY,
      SCON,       TANY,
            3*NAREG,    RDEST,
            "     li A1,AR          # bit-field assignment\n"
            "     lw A2,AL\n"
            "     li A3,M\n"
            "     sll A1,A1,H\n"
            "     and A1,A1,A3\n"
            "     nor A3,$zero,A3\n"
            "     and A2,A2,A3\n"
            "     or A2,A2,A1\n"
            "     sw A2,AL\n"
            "F    li AD,AR\n"
            "F    sll AD,AD,32-S\n"
            "F    sra AD,AD,32-S\n", },

{ ASSIGN,   FOREFF|INAREG,
      SFLD,       TANY,
      SAREG,            TANY,
            3*NAREG,    RDEST,
            "     move A1,AR        # bit-field assignment\n"
            "     lw A2,AL\n"
            "     li A3,M\n"
            "     sll A1,A1,H\n"
            "     and A1,A1,A3\n"
            "     nor A3,$zero,A3\n"
            "     and A2,A2,A3\n"
            "     or A2,A2,A1\n"
            "     sw A2,AL\n"
            "F    move AR,AD\n"
            "F    sll AD,AD,32-S\n"
            "F    sra AD,AD,32-S\n", },

{ STASG,        INAREG|FOREFF,
        SOREG|SNAME,    TANY,
        SAREG,    TPTRTO|TANY,
                NSPECIAL,       RDEST,
                "ZQ", },

/*
 * Compare instructions
 */

{ EQ, FORCC,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
                0,      RESCC,
                " beq AL,AR,LC\n"
            "     nop\n", },

{ NE, FORCC,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
                0,      RESCC,
                " bne AL,AR,LC\n"
            "     nop\n", },

{ OPLOG,    FORCC,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
        SZERO,          TANY,
                0,      RESCC,
                " O AL,LC\n"
            "     nop\n", },

{ OPLOG,    FORCC,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
                NAREG|NASL,     RESCC,
            "     sub A1,AL,AR\n"
                " O A1,LC\n"
            "     nop\n", },

{ OPLOG,    FORCC,
        SAREG,          TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR,
        SSCON,          TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
                NAREG|NASL,     RESCC,
            "     sub A1,AL,AR\n"
                " O A1,LC\n"
            "     nop\n", },

{ OPLOG,    FORCC,
      SBREG,            TLONGLONG|TULONGLONG,
      SBREG,            TLONGLONG|TULONGLONG,
            NAREG,      RESCC,
            "ZD", },

{ OPLOG,    FORCC,
      SCREG,      TFLOAT|TDOUBLE|TLDOUBLE,
      SCREG,      TFLOAT|TDOUBLE|TLDOUBLE,
            0,    RESCC,
            "ZG", },

/*
 * Convert LTYPE to reg.
 */

{ OPLTYPE,  INAREG,
      SANY,       TANY,
      SOREG|SNAME,      TCHAR,
            NAREG,      RESC1,
            "     lb A1,AL    # load char to reg\n"
            "     nop\n", },
      
{ OPLTYPE,  INAREG,
      SANY,       TANY,
      SOREG|SNAME,      TUCHAR,
            NAREG,      RESC1,
            "     lbu A1,AL   # load uchar to reg\n"
            "     nop\n", },

{ OPLTYPE,  INAREG,
      SANY,       TANY,
      SOREG|SNAME,      TSHORT,
            NAREG,      RESC1,
            "     lh A1,AL    # load short to reg\n"
            "     nop\n", },

{ OPLTYPE,  INAREG,
      SANY,       TANY,
      SOREG|SNAME,      TUSHORT,
            NAREG,      RESC1,
            "     lhu A1,AL   # load ushort to reg\n"
            "     nop\n", },

{ OPLTYPE,  INAREG,
      SANY,       TANY,
      SOREG|SNAME,      TWORD|TPOINT,
            NAREG,      RESC1,
            "     lw A1,AL    # load (u)int/(u)long to reg\n"
            "     nop\n", },

{ OPLTYPE,  INBREG,
      SANY,       TANY,
      SOREG|SNAME,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     lw U1,UL    # load (u)longlong to reg\n"
            "     nop\n"
            "     lw A1,AL\n"
                  "     nop\n", },

{ OPLTYPE,  INAREG,
      SANY, TANY,
      SCON, TPOINT,
            NAREG,      RESC1,
            "     la A1,AL    # load constant address to reg\n", },

{ OPLTYPE,  INAREG,
      SANY, TANY,
      SZERO,      TANY,
            NAREG,      RESC1,
            "     move A1,$zero     # load 0 to reg\n", },

{ OPLTYPE,  INAREG,
      SANY, TANY,
      SCON, TANY,
            NAREG,      RESC1,
            "     li A1,AL    # load constant to reg\n", },

{ OPLTYPE,  INBREG,
      SANY, TANY,
      SZERO,      TANY,
            NBREG,      RESC1,
            "     move A1,$zero     # load 0 to reg\n"
            "     move U1,$zero\n", },

{ OPLTYPE,  INBREG,
      SANY, TANY,
      SCON, TANY,
            NBREG,      RESC1,
            "     li A1,AL    # load constant to reg\n"
            "     li U1,UL\n", },

{ OPLTYPE,  INAREG,
      SANY, TANY,
      SANY, TANY,
            NAREG,      RESC1,
            "     move A1,AL\n", },

{ OPLTYPE,  INCREG,
      SANY, TANY,
      SZERO,      TFLOAT,
            NCREG,      RESC1,
            "     mtc1 $zero,A1     # load 0 to float reg\n"
            "     nop\n", },

{ OPLTYPE,  INCREG,
      SANY, TANY,
      SZERO,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1,
            "     mtc1 $zero,A1     # load 0 to (l)double reg\n"
            "     mtc1 $zero,U1\n"
            "     nop\n", },

{ OPLTYPE,  INCREG,
      SANY, TANY,
      SOREG|SNAME,      TFLOAT,
            NCREG,      RESC1,
            "     l.s A1,AL   # load into floating-point reg\n"
            "     nop\n", },

{ OPLTYPE,  INCREG,
      SANY, TANY,
      OREG|SNAME, TDOUBLE|TLDOUBLE,
            NCREG,      RESC1,
            "     l.d A1,AL   # load into double floating-point reg\n"
            "     nop\n", },
    
/*
 * Jumps.
 */
{ GOTO,     FOREFF,
      SCON, TANY,
      SANY, TANY,
            0,    RNOP,
            "     j LL        # goto label\n"
            "     nop\n"
            "     nop\n", },

/*
 * Subroutine calls.
 */

{ CALL,         FOREFF,
        SCON,           TANY,
        SANY,           TANY,
                0,      0,
                " subu $sp,$sp,16   # call (args, no result) to scon/sname\n"
                " jal CL\n"
            "     nop\n"
            "ZC", },

{ UCALL,        FOREFF,
        SCON,           TANY,
        SANY,           TANY,
                0,      0,
                " jal CL                  # call (no args, no result) to scon/sname\n"
            "     nop\n", },

{ CALL,         INAREG,
        SCON,           TANY,
        SAREG,          TANY,
                NAREG,     RESC1,  /* should be 0 */
                " subu $sp,$sp,16   # call (args, result in v0) to scon/sname\n"
            "     jal CL\n"
            "     nop\n"
            "ZC", },

{ UCALL,        INAREG,
        SCON,           TANY,
        SAREG,          TANY,
                NAREG,     RESC1,  /* should be 0 */
                " jal CL   # call (no args, result in v0) to scon/sname\n"
            "     nop\n",
 },

{ CALL,         INBREG,
        SCON,           TANY,
        SBREG,          TANY,
                NBREG,     RESC1,  /* should be 0 */
                " subu $sp,$sp,16   # call (args, result in v0:v1) to scon/sname\n"
            "     jal CL\n"
            "     nop\n"
            "ZC", },

{ UCALL,        INBREG,
        SCON,           TANY,
        SBREG,          TANY,
                NBREG,     RESC1,  /* should be 0 */
                " jal CL   # call (no args, result in v0:v1) to scon/sname\n"
            "     nop\n",
 },

{ CALL,         INCREG,
        SCON,           TANY,
        SCREG,          TANY,
                NCREG,     RESC1,  /* should be 0 */
                " subu $sp,$sp,16   # call (args, result in f0:f1) to scon/sname\n"
            "     jal CL\n"
            "     nop\n"
            "ZC", },

{ UCALL,        INCREG,
        SCON,           TANY,
        SCREG,          TANY,
                NCREG,     RESC1,  /* should be 0 */
                " jal CL   # call (no args, result in v0:v1) to scon/sname\n"
            "     nop\n",
 },

{ CALL,         FOREFF,
        SAREG,          TANY,
        SANY,           TANY,
                0,      0,
                " subu $sp,$sp,16   # call (args, no result) to reg\n"
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n"
            "ZC", },

{ UCALL,        FOREFF,
        SAREG,          TANY,
        SANY,           TANY,
                0,      0,
            "     move $25,AL\n"
                " jal $25                 # call (no args, no result) to reg\n"
            "     nop\n", },

{ CALL,         INAREG,
        SAREG,          TANY,
        SAREG,          TANY,
                NAREG,     RESC1,  /* should be 0 */
                " subu $sp,$sp,16   # call (args, result) to reg\n"
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n"
            "ZC", },

{ UCALL,        INAREG,
        SAREG,          TANY,
        SAREG,          TANY,
                NAREG,     RESC1,  /* should be 0 */
            "     move $25,AL\n"
                " jal $25           # call (no args, result) to reg\n"
            "     nop\n", },

{ CALL,         INBREG,
        SAREG,          TANY,
        SBREG,          TANY,
                NBREG,     RESC1,  /* should be 0 */
                " subu $sp,$sp,16   # call (args, result) to reg\n"
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n"
            "ZC", },

{ UCALL,        INBREG,
        SAREG,          TANY,
        SBREG,          TANY,
                NBREG,     RESC1,  /* should be 0 */
            "     move $25,AL\n"
                " jal $25                 # call (no args, result) to reg\n"
            "     nop\n", },

{ CALL,         INCREG,
        SAREG,          TANY,
        SCREG,          TANY,
                NCREG,     RESC1,  /* should be 0 */
                " subu $sp,$sp,16   # call (args, result) to reg\n"
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n"
            "ZC", },

{ UCALL,        INCREG,
        SCREG,          TANY,
        SCREG,          TANY,
                NCREG,     RESC1,  /* should be 0 */
            "     move $25,AL\n"
                " jal $25                 # call (no args, result) to reg\n"
            "     nop\n", },


/* struct return */
{ USTCALL,      FOREFF,
      SCON|SNAME, TANY,
      SANY,       TANY,
            0,    0,
            "     jal CL\n"
            "     nop\n", },

{ USTCALL,      FOREFF,
      SAREG,            TANY,
      SANY,       TANY,
            0,    0,
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n", },

{ USTCALL,      INAREG,
      SCON|SNAME, TANY,
      SANY,       TANY,
            NAREG|NASL, RESC1,
            "     jal CL\n"
            "     nop\n", },

{ USTCALL,      INAREG,
      SAREG,            TANY,
      SANY,       TANY,
            NAREG|NASL, RESC1,
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n", },

{ STCALL,      FOREFF,
      SCON|SNAME, TANY,
      SANY,       TANY,
            0,    0,
                " subu $sp,$sp,16\n"
            "     jal CL\n"
            "     nop\n"
            "ZC", },

{ STCALL,      FOREFF,
      SAREG,      TANY,
      SANY,       TANY,
            0,    0,
                " subu $sp,$sp,16\n"
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n"
            "ZC", },

{ STCALL,      INAREG,
      SCON|SNAME, TANY,
      SANY,       TANY,
            NAREG|NASL, RESC1,
                " subu $sp,$sp,16\n"
            "     jal CL\n"
            "     nop\n"
            "ZC", },

{ STCALL,      INAREG,
      SAREG,      TANY,
      SANY,       TANY,
            0,    0,
                " subu $sp,$sp,16\n"
            "     move $25,AL\n"
                " jal $25\n"
            "     nop\n"
            "ZC", },


/*
 *  Function arguments
 */

#if 0

/* intentionally write out the register for (u)short/(u)char */
{ FUNARG,       FOREFF,
        SAREG,  TWORD|TPOINT|TUSHORT|TSHORT|TUCHAR|TCHAR,
        SANY,   TWORD|TPOINT|TUSHORT|TSHORT|TUCHAR|TCHAR,
                0,      0,
                " subu $sp,$sp,4          # save function arg to stack\n"
            "     sw AL,($sp)\n"
            "     #nop\n", },

{ FUNARG,   FOREFF,
      SBREG,      TLONGLONG|TULONGLONG,
      SANY, TLONGLONG|TULONGLONG,
            0,    0,
            "     addi $sp,$sp,-8         # save function arg to stack (endian problem here?\n"
            "     sw UL,4($sp)\n"
            "     sw AL,($sp)\n"
            "     #nop\n", },

{ FUNARG,   FOREFF,
      SCREG,      TFLOAT,
      SANY, TFLOAT,
            0,    0,
            "     addi $sp,$sp,-4         # save function arg to stack\n"
            "     s.s AL,($sp)\n"
            "     #nop\n", },

{ FUNARG,   FOREFF,
      SCREG,      TDOUBLE|TLDOUBLE,
      SANY, TDOUBLE|TLDOUBLE,
            0,    0,
            "     addi $sp,$sp,-8         # save function arg to stack\n"
            "     s.d AL,($sp)\n"
            "     #nop\n", },

#endif

{ STARG,    FOREFF,
      SAREG,            TANY,
      SANY,       TSTRUCT,
            NSPECIAL,   0,
            "ZH", },

/*
 * Indirection operators.
 */
{ UMUL, INAREG,
      SANY, TPOINT|TWORD,
      SOREG,      TPOINT|TWORD,
            NAREG,     RESC1,
            "     lw A1,AL          # word load\n"
            "     nop\n", },

{ UMUL, INAREG,
      SANY, TSHORT|TUSHORT,
      SOREG,      TSHORT|TUSHORT,
            NAREG,     RESC1,
            "     lh A1,AL          # (u)short load\n"
            "     nop\n", },

{ UMUL, INAREG,
      SANY, TCHAR|TUCHAR,
      SOREG,      TCHAR|TUCHAR,
            NAREG,     RESC1,
            "     lb A1,AL          # (u)char load\n"
            "     nop\n", },

{ UMUL,     INBREG,
      SANY, TLONGLONG|TULONGLONG,
      SOREG,      TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     lw A1,AL          # (u)longlong load - endian problem here?\n"
            "     nop\n"
            "     lw U1,UL\n"
            "     nop\n", },

{ UMUL,     INCREG,
      SANY, TFLOAT,
      SOREG,      TFLOAT,
            NCREG,      RESC1,
            "     l.s A1,AL         # float load\n"
            "     nop\n", },

{ UMUL,     INCREG,
      SANY, TDOUBLE|TLDOUBLE,
      SOREG,      TDOUBLE|TLDOUBLE,
            NCREG,      RESC1,
            "     l.d A1,AL         # float load\n"
            "     nop\n", },

#if 0
{ UMUL,     INCREG,
      SANY, TDOUBLE|TLDOUBLE,
      SAREG,      TPOINT,
            NCREG,      RESC1,
            "     l.d A1,(AL)\n"
            "     nop\n", },
    
{ UMUL, INAREG,
      SANY, TPOINT|TWORD,
      SNAME,      TPOINT|TWORD,
            NAREG,     RESC1,
            "     la A1,AL          # sname word load\n"
            "     lw A1,(A1)\n"
            "     nop\n", },

{ UMUL, INAREG,
      SANY, TSHORT|TUSHORT,
      SNAME,      TSHORT|TUSHORT,
            NAREG,     RESC1,
            "     la A1,AL          # sname (u)short load\n"
            "     lh A1,(A1)\n"
            "     nop\n", },

{ UMUL, INAREG,
      SANY, TCHAR|TUCHAR,
      SNAME,      TCHAR|TUCHAR,
            NAREG,     RESC1,
            "     la A1,AL          # sname (u)char load\n"
            "     lb A1,(A1)\n"
            "     nop\n", },

{ UMUL, INBREG,
      SANY, TLONGLONG|TULONGLONG,
      SNAME,      TLONGLONG|TULONGLONG,
            NBREG|NAREG,      RESC1,
            "     la A2,AL          # sname (u)long long load - endian problems here?\n"
            "     lw A1,(A1)\n"
            "     nop\n"
            "     lw U1,4(A1)\n"
            "     nop\n", },
#endif

{ UMUL, INAREG,
      SANY, TPOINT|TWORD,
      SAREG,      TPOINT|TWORD,
            NAREG,     RESC1,
            "     lw A1,(AL)        # word load\n"
            "     nop\n", },

#if 0
{ UMUL, INAREG,
      SANY, TSHORT|TUSHORT,
      SAREG,      TPTRTO|TSHORT|TUSHORT,
            NAREG,     RESC1,
            "     lh A1,(AL)        # (u)short load\n"
            "     nop\n", },

{ UMUL, INAREG,
      SANY, TCHAR|TUCHAR,
      SAREG,      TPTRTO|TCHAR|TUCHAR,
            NAREG|NASL,     RESC1,
            "     lb A1,(AL)        # (u)char load\n"
            "     nop\n", },

{ UMUL, INBREG,
      SANY, TLONGLONG|TULONGLONG,
      SAREG,      TPTRTO|TLONGLONG|TULONGLONG,
            NBREG,      RESC1,
            "     lw A1,(AL)        # (u)long long load - endianness problems?\n"
            "     nop\n"
            "     lw U1,4(AL)"
            "     nop\n", },
#endif

#define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""

{ FLD, DF(FLD), },

{ FREE,     FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
};

int tablesize = sizeof(table)/sizeof(table[0]);

Generated by  Doxygen 1.6.0   Back to index