[Midnightbsd-cvs] src: pcc/cpp: add i386 directory which contains files in arch/x86
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu May 15 01:43:58 EDT 2008
Log Message:
-----------
add i386 directory which contains files in arch/x86 (similar to openbsd setup).
Remove arch
Disable the man page for cpp since gcc installs one.
Modified Files:
--------------
src/usr.bin/pcc/cpp:
Makefile (r1.3 -> r1.4)
Added Files:
-----------
src/usr.bin/pcc/i386:
code.c (r1.1)
local.c (r1.1)
local2.c (r1.1)
macdefs.h (r1.1)
order.c (r1.1)
table.c (r1.1)
Removed Files:
-------------
src/usr.bin/pcc/arch/x86:
code.c
local.c
local2.c
macdefs.h
order.c
table.c
-------------- next part --------------
--- usr.bin/pcc/arch/x86/order.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/* $Id: order.c,v 1.49 2007/08/01 04:53:58 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-# include "pass2.h"
-
-#include <string.h>
-
-int canaddr(NODE *);
-
-/* is it legal to make an OREG or NAME entry which has an
- * offset of off, (from a register of r), if the
- * resulting thing had type t */
-int
-notoff(TWORD t, int r, CONSZ off, char *cp)
-{
- return(0); /* YES */
-}
-
-/*
- * Turn a UMUL-referenced node into OREG.
- * Be careful about register classes, this is a place where classes change.
- */
-void
-offstar(NODE *p, int shape)
-{
- NODE *r;
-
- if (x2debug)
- printf("offstar(%p)\n", p);
-
- if (isreg(p))
- return; /* Is already OREG */
-
- r = p->n_right;
- if( p->n_op == PLUS || p->n_op == MINUS ){
- if( r->n_op == ICON ){
- if (isreg(p->n_left) == 0)
- (void)geninsn(p->n_left, INAREG);
- /* Converted in ormake() */
- return;
- }
- if (r->n_op == LS && r->n_right->n_op == ICON &&
- r->n_right->n_lval == 2 && p->n_op == PLUS) {
- if (isreg(p->n_left) == 0)
- (void)geninsn(p->n_left, INAREG);
- if (isreg(r->n_left) == 0)
- (void)geninsn(r->n_left, INAREG);
- return;
- }
- }
- (void)geninsn(p, INAREG);
-}
-
-/*
- * Do the actual conversion of offstar-found OREGs into real OREGs.
- */
-void
-myormake(NODE *q)
-{
- NODE *p, *r;
-
- if (x2debug)
- printf("myormake(%p)\n", q);
-
- p = q->n_left;
- if (p->n_op == PLUS && (r = p->n_right)->n_op == LS &&
- r->n_right->n_op == ICON && r->n_right->n_lval == 2 &&
- p->n_left->n_op == REG && r->n_left->n_op == REG) {
- q->n_op = OREG;
- q->n_lval = 0;
- q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0);
- tfree(p);
- }
-}
-
-/*
- * Shape matches for UMUL. Cooperates with offstar().
- */
-int
-shumul(NODE *p)
-{
-
- if (x2debug)
- printf("shumul(%p)\n", p);
-
- /* Turns currently anything into OREG on x86 */
- return SOREG;
-}
-
-/*
- * Rewrite increment/decrement operation.
- */
-int
-setincr(NODE *p)
-{
- if (x2debug)
- printf("setincr(%p)\n", p);
-
- return(0);
-}
-
-/*
- * Rewrite operations on binary operators (like +, -, etc...).
- * Called as a result of table lookup.
- */
-int
-setbin(NODE *p)
-{
-
- if (x2debug)
- printf("setbin(%p)\n", p);
- return 0;
-
-}
-
-/* setup for assignment operator */
-int
-setasg(NODE *p, int cookie)
-{
- if (x2debug)
- printf("setasg(%p)\n", p);
- return(0);
-}
-
-/* setup for unary operator */
-int
-setuni(NODE *p, int cookie)
-{
- return 0;
-}
-
-/*
- * Special handling of some instruction register allocation.
- */
-struct rspecial *
-nspecial(struct optab *q)
-{
- switch (q->op) {
- case OPLOG:
- {
- static struct rspecial s[] = { { NEVER, EAX }, { 0 } };
- return s;
- }
-
- case STASG:
- case STARG:
- {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NEVER, ECX }, { 0 } };
- return s;
- }
-
- case SCONV:
- if ((q->ltype & (TINT|TUNSIGNED|TSHORT|TUSHORT)) &&
- q->rtype == (TCHAR|TUCHAR)) {
- static struct rspecial s[] = {
- { NOLEFT, ESI }, { NOLEFT, EDI }, { 0 } };
- return s;
- } else if ((q->ltype & (TINT|TUNSIGNED)) &&
- q->rtype == TLONGLONG) {
- static struct rspecial s[] = {
- { NLEFT, EAX }, { NRES, EAXEDX },
- { NEVER, EAX }, { NEVER, EDX }, { 0 } };
- return s;
- } else if (q->ltype == TSHORT &&
- q->rtype == (TLONGLONG|TULONGLONG)) {
- static struct rspecial s[] = {
- { NRES, EAXEDX },
- { NEVER, EAX }, { NEVER, EDX }, { 0 } };
- return s;
- } else if (q->ltype == TCHAR &&
- q->rtype == (TLONGLONG|TULONGLONG)) {
- static struct rspecial s[] = {
- { NRES, EAXEDX },
- { NEVER, EAX }, { NEVER, EDX }, { 0 } };
- return s;
- }
- break;
- case DIV:
- if (q->lshape == SBREG) {
- static struct rspecial s[] = {
- { NEVER, AL }, { NEVER, AH },
- { NLEFT, AL }, { NRES, AL },
- { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
- return s;
- } else if (q->lshape == SAREG) {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NLEFT, EAX }, { NRES, EAX },
- { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
- return s;
- } else if (q->lshape & SCREG) {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
- return s;
- }
- break;
- case MOD:
- if (q->lshape == SBREG) {
- static struct rspecial s[] = {
- { NEVER, AL }, { NEVER, AH },
- { NLEFT, AL }, { NRES, AH },
- { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
- return s;
- } else if (q->lshape == SAREG) {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NLEFT, EAX }, { NRES, EDX },
- { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
- return s;
- } else if (q->lshape & SCREG) {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
- return s;
- }
- break;
- case MUL:
- if (q->lshape == SBREG) {
- static struct rspecial s[] = {
- { NEVER, AL }, { NEVER, AH },
- { NLEFT, AL }, { NRES, AL }, { 0 } };
- return s;
- } else if (q->lshape & SCREG) {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
- return s;
- }
- break;
- case LS:
- case RS:
- if (q->visit & (INAREG|INBREG)) {
- static struct rspecial s[] = {
- { NRIGHT, CL }, { NOLEFT, ECX }, { 0 } };
- return s;
- } else if (q->visit & INCREG) {
- static struct rspecial s[] = {
- { NEVER, EAX }, { NEVER, EDX },
- { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
- return s;
- }
- break;
-
- default:
- break;
- }
- comperr("nspecial entry %d", q - table);
- return 0; /* XXX gcc */
-}
-
-/*
- * Set evaluation order of a binary node if it differs from default.
- */
-int
-setorder(NODE *p)
-{
- return 0; /* nothing differs on x86 */
-}
--- usr.bin/pcc/arch/x86/macdefs.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/* $Id: macdefs.h,v 1.46 2007/08/19 19:25:22 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-/*
- * Machine-dependent defines for both passes.
- */
-
-/*
- * Convert (multi-)character constant to integer.
- */
-#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
-
-#define ARGINIT 64 /* # bits above fp where arguments start */
-#define AUTOINIT 0 /* # bits below fp where automatics start */
-
-/*
- * Storage space requirements
- */
-#define SZCHAR 8
-#define SZBOOL 8
-#define SZINT 32
-#define SZFLOAT 32
-#define SZDOUBLE 64
-#define SZLDOUBLE 96
-#define SZLONG 32
-#define SZSHORT 16
-#define SZLONGLONG 64
-#define SZPOINT(t) 32
-
-/*
- * Alignment constraints
- */
-#define ALCHAR 8
-#define ALBOOL 8
-#define ALINT 32
-#define ALFLOAT 32
-#define ALDOUBLE 32
-#define ALLDOUBLE 32
-#define ALLONG 32
-#define ALLONGLONG 32
-#define ALSHORT 16
-#define ALPOINT 32
-#define ALSTRUCT 32
-#define ALSTACK 32
-
-/*
- * Min/max values.
- */
-#define MIN_CHAR -128
-#define MAX_CHAR 127
-#define MAX_UCHAR 255
-#define MIN_SHORT -32768
-#define MAX_SHORT 32767
-#define MAX_USHORT 65535
-#define MIN_INT -1
-#define MAX_INT 0x7fffffff
-#define MAX_UNSIGNED 0xffffffff
-#define MIN_LONG MIN_INT
-#define MAX_LONG MAX_INT
-#define MAX_ULONG MAX_UNSIGNED
-#define MIN_LONGLONG 0x8000000000000000LL
-#define MAX_LONGLONG 0x7fffffffffffffffLL
-#define MAX_ULONGLONG 0xffffffffffffffffULL
-
-/* Default char is signed */
-#undef CHAR_UNSIGNED
-#define BOOL_TYPE CHAR /* what used to store _Bool */
-#define WCHAR_TYPE INT /* what used to store wchar_t */
-
-/*
- * Use large-enough types.
- */
-typedef long long CONSZ;
-typedef unsigned long long U_CONSZ;
-typedef long long OFFSZ;
-
-#define CONFMT "%lld" /* format for printing constants */
-#define LABFMT ".L%d" /* format for printing labels */
-#define STABLBL ".LL%d" /* format for stab (debugging) labels */
-#ifdef FORTRAN
-#define XL 8
-#define FLABELFMT "%s:\n"
-#define USETEXT ".text"
-#define USECONST ".data\t0" /* XXX - fix */
-#define USEBSS ".data\t1" /* XXX - fix */
-#define USEINIT ".data\t2" /* XXX - fix */
-#define MAXREGVAR 3 /* XXX - fix */
-#define BLANKCOMMON "_BLNK_"
-#define MSKIREG (M(TYSHORT)|M(TYLONG))
-#define TYIREG TYLONG
-#define FSZLENG FSZLONG
-#define FUDGEOFFSET 1
-#define AUTOREG EBP
-#define ARGREG EBP
-#define ARGOFFSET 4
-#endif
-
-#define BACKAUTO /* stack grows negatively for automatics */
-#define BACKTEMP /* stack grows negatively for temporaries */
-
-#define MYP2TREE(p) myp2tree(p);
-
-#undef FIELDOPS /* no bit-field instructions */
-#define RTOLBYTES /* bytes are numbered right to left */
-
-#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
-
-/* Definitions mostly used in pass2 */
-
-#define BYTEOFF(x) ((x)&03)
-#define wdal(k) (BYTEOFF(k)==0)
-#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */
-
-#define STOARG(p)
-#define STOFARG(p)
-#define STOSTARG(p)
-#define genfcall(a,b) gencall(a,b)
-
-#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
- (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 3 : 1)
-
-/*
- * The x86 has a bunch of register classes, most of them interfering
- * with each other. All registers are given a sequential number to
- * identify it which must match rnames[] in local2.c.
- * Class membership and overlaps are defined in the macros RSTATUS
- * and ROVERLAP below.
- *
- * The classes used on x86 are:
- * A - short and int regs
- * B - char regs
- * C - long long regs
- * D - floating point
- */
-#define EAX 000 /* Scratch and return register */
-#define EDX 001 /* Scratch and secondary return register */
-#define ECX 002 /* Scratch (and shift count) register */
-#define EBX 003 /* GDT pointer or callee-saved temporary register */
-#define ESI 004 /* Callee-saved temporary register */
-#define EDI 005 /* Callee-saved temporary register */
-#define EBP 006 /* Frame pointer */
-#define ESP 007 /* Stack pointer */
-
-#define AL 010
-#define AH 011
-#define DL 012
-#define DH 013
-#define CL 014
-#define CH 015
-#define BL 016
-#define BH 017
-
-#define EAXEDX 020
-#define EAXECX 021
-#define EAXEBX 022
-#define EAXESI 023
-#define EAXEDI 024
-#define EDXECX 025
-#define EDXEBX 026
-#define EDXESI 027
-#define EDXEDI 030
-#define ECXEBX 031
-#define ECXESI 032
-#define ECXEDI 033
-#define EBXESI 034
-#define EBXEDI 035
-#define ESIEDI 036
-
-/* The 8 math registers in class D lacks names */
-
-#define MAXREGS 047 /* 39 registers */
-
-#define RSTATUS \
- SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, \
- SAREG|PERMREG, SAREG|PERMREG, 0, 0, \
- SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
- SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
- SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
- SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG,
-
-#define ROVERLAP \
- /* 8 basic registers */\
- { AL, AH, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
- { DL, DH, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
- { CL, CH, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
- { BL, BH, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
- { EAXESI, EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\
- { EAXEDI, EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
- { -1 },\
- { -1 },\
-\
- /* 8 char registers */\
- { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
- { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
- { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
- { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
- { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
- { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
- { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
- { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
-\
- /* 15 long-long-emulating registers */\
- { EAX, AL, AH, EDX, DL, DH, EAXECX, EAXEBX, EAXESI, /* eaxedx */\
- EAXEDI, EDXECX, EDXEBX, EDXESI, EDXEDI, -1, },\
- { EAX, AL, AH, ECX, CL, CH, EAXEDX, EAXEBX, EAXESI, /* eaxecx */\
- EAXEDI, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
- { EAX, AL, AH, EBX, BL, BH, EAXEDX, EAXECX, EAXESI, /* eaxebx */\
- EAXEDI, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
- { EAX, AL, AH, ESI, EAXEDX, EAXECX, EAXEBX, EAXEDI, /* eaxesi */\
- EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\
- { EAX, AL, AH, EDI, EAXEDX, EAXECX, EAXEBX, EAXESI, /* eaxedi */\
- EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
- { EDX, DL, DH, ECX, CL, CH, EAXEDX, EAXECX, EDXEBX, /* edxecx */\
- EDXESI, EDXEDI, ECXEBX, ECXESI, ECXEDI, -1 },\
- { EDX, DL, DH, EBX, BL, BH, EAXEDX, EDXECX, EDXESI, /* edxebx */\
- EDXEDI, EAXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
- { EDX, DL, DH, ESI, EAXEDX, EDXECX, EDXEBX, EDXEDI, /* edxesi */\
- EAXESI, ECXESI, EBXESI, ESIEDI, -1 },\
- { EDX, DL, DH, EDI, EAXEDX, EDXECX, EDXEBX, EDXESI, /* edxedi */\
- EAXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
- { ECX, CL, CH, EBX, BL, BH, EAXECX, EDXECX, ECXESI, /* ecxebx */\
- ECXEDI, EAXEBX, EDXEBX, EBXESI, EBXEDI, -1 },\
- { ECX, CL, CH, ESI, EAXECX, EDXECX, ECXEBX, ECXEDI, /* ecxesi */\
- EAXESI, EDXESI, EBXESI, ESIEDI, -1 },\
- { ECX, CL, CH, EDI, EAXECX, EDXECX, ECXEBX, ECXESI, /* ecxedi */\
- EAXEDI, EDXEDI, EBXEDI, ESIEDI, -1 },\
- { EBX, BL, BH, ESI, EAXEBX, EDXEBX, ECXEBX, EBXEDI, /* ebxesi */\
- EAXESI, EDXESI, ECXESI, ESIEDI, -1 },\
- { EBX, BL, BH, EDI, EAXEBX, EDXEBX, ECXEBX, EBXESI, /* ebxedi */\
- EAXEDI, EDXEDI, ECXEDI, ESIEDI, -1 },\
- { ESI, EDI, EAXESI, EDXESI, ECXESI, EBXESI, /* esiedi */\
- EAXEDI, EDXEDI, ECXEDI, EBXEDI, -1 },\
-\
- /* The fp registers do not overlap with anything */\
- { -1 },\
- { -1 },\
- { -1 },\
- { -1 },\
- { -1 },\
- { -1 },\
- { -1 },\
- { -1 },
-
-
-/* Return a register class based on the type of the node */
-#define PCLASS(p) (p->n_type <= UCHAR ? SBREG : \
- (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SCREG : \
- (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SDREG : SAREG)))
-
-#define NUMCLASS 4 /* highest number of reg classes used */
-
-int COLORMAP(int c, int *r);
-#define GCLASS(x) (x < 8 ? CLASSA : x < 16 ? CLASSB : x < 31 ? CLASSC : CLASSD)
-#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
-#define ENCRD(x) (x) /* Encode dest reg in n_reg */
-#define ENCRA1(x) ((x) << 6) /* A1 */
-#define ENCRA2(x) ((x) << 12) /* A2 */
-#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
-/* XXX - return char in al? */
-#define RETREG(x) (x == CHAR || x == UCHAR ? AL : \
- x == LONGLONG || x == ULONGLONG ? EAXEDX : \
- x == FLOAT || x == DOUBLE || x == LDOUBLE ? 31 : EAX)
-
-//#define R2REGS 1 /* permit double indexing */
-
-/* XXX - to die */
-#define FPREG EBP /* frame pointer */
-#define STKREG ESP /* stack pointer */
-
-#define MYREADER(p) myreader(p)
-#define MYCANON(p) mycanon(p)
-#define MYOPTIM
-
-#define SHSTR (MAXSPECIAL+1) /* short struct */
-#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */
-#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */
--- usr.bin/pcc/arch/x86/table.c
+++ /dev/null
@@ -1,1464 +0,0 @@
-/* $Id: table.c,v 1.96 2007/09/20 14:52:13 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-# include "pass2.h"
-
-# define TLL TLONGLONG|TULONGLONG
-# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR
-# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
-# define ANYFIXED ANYSIGNED|ANYUSIGNED
-# define TUWORD TUNSIGNED|TULONG
-# define TSWORD TINT|TLONG
-# define TWORD TUWORD|TSWORD
-#define SHINT SAREG /* short and int */
-#define ININT INAREG
-#define SHCH SBREG /* shape for char */
-#define INCH INBREG
-#define SHLL SCREG /* shape for long long */
-#define INLL INCREG
-#define SHFL SDREG /* shape for float/double */
-#define INFL INDREG /* shape for float/double */
-
-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,
- "", },
-
-/*
- * A bunch conversions of integral<->integral types
- * There are lots of them, first in table conversions to itself
- * and then conversions from each type to the others.
- */
-
-/* itself to itself, including pointers */
-
-/* convert (u)char to (u)char. */
-{ SCONV, INCH,
- SHCH, TCHAR|TUCHAR,
- SHCH, TCHAR|TUCHAR,
- 0, RLEFT,
- "", },
-
-/* convert pointers to int. */
-{ SCONV, ININT,
- SHINT, TPOINT|TWORD,
- SANY, TWORD,
- 0, RLEFT,
- "", },
-
-/* convert (u)longlong to (u)longlong. */
-{ SCONV, INLL,
- SHLL, TLL,
- SHLL, TLL,
- 0, RLEFT,
- "", },
-
-/* convert double <-> float. nothing to do here */
-{ SCONV, INFL,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RLEFT,
- "", },
-
-/* convert pointers to pointers. */
-{ SCONV, ININT,
- SHINT, TPOINT,
- SANY, TPOINT,
- 0, RLEFT,
- "", },
-
-/* char to something */
-
-/* convert char to (unsigned) short. */
-{ SCONV, ININT,
- SBREG|SOREG|SNAME, TCHAR,
- SAREG, TSHORT|TUSHORT,
- NASL|NAREG, RESC1,
- " movsbw AL,A1\n", },
-
-/* convert unsigned char to (u)short. */
-{ SCONV, ININT,
- SHCH|SOREG|SNAME, TUCHAR,
- SAREG, TSHORT|TUSHORT,
- NASL|NAREG, RESC1,
- " movzbw AL,A1\n", },
-
-/* convert signed char to int (or pointer). */
-{ SCONV, ININT,
- SHCH|SOREG|SNAME, TCHAR,
- SAREG, TWORD|TPOINT,
- NASL|NAREG, RESC1,
- " movsbl AL,A1\n", },
-
-/* convert unsigned char to (u)int. */
-{ SCONV, ININT,
- SHCH|SOREG|SNAME, TUCHAR,
- SAREG, TWORD,
- NASL|NAREG, RESC1,
- " movzbl AL,A1\n", },
-
-/* convert char to (u)long long */
-{ SCONV, INLL,
- SHCH|SOREG|SNAME, TCHAR,
- SANY, TLL,
- NSPECIAL|NAREG|NASL, RESC1,
- " movsbl AL,%eax\n cltd\n", },
-
-/* convert unsigned char to (u)long long */
-{ SCONV, INLL,
- SHCH|SOREG|SNAME, TUCHAR,
- SANY, TLL,
- NCREG|NCSL, RESC1,
- " movzbl AL,A1\n xorl U1,U1\n", },
-
-/* convert char (in register) to double XXX - use NTEMP */
-{ SCONV, INFL,
- SHCH|SOREG|SNAME, TCHAR,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NAREG|NASL|NDREG, RESC2,
- " movsbl AL,A1\n pushl A1\n"
- " fildl (%esp)\n addl $4,%esp\n", },
-
-/* convert (u)char (in register) to double XXX - use NTEMP */
-{ SCONV, INFL,
- SHCH|SOREG|SNAME, TUCHAR,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NAREG|NASL|NDREG, RESC2,
- " movzbl AL,A1\n pushl A1\n"
- " fildl (%esp)\n addl $4,%esp\n", },
-
-/* short to something */
-
-/* convert short (in memory) to char */
-{ SCONV, INCH,
- SNAME|SOREG, TSHORT|TUSHORT,
- SHCH, TCHAR|TUCHAR,
- NBREG|NBSL, RESC1,
- " movb AL,A1\n", },
-
-/* convert short (in reg) to char. */
-{ SCONV, INCH,
- SAREG|SNAME|SOREG, TSHORT|TUSHORT,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL|NBREG|NBSL, RESC1,
- "ZM", },
-
-/* convert short to (u)int. */
-{ SCONV, ININT,
- SAREG|SOREG|SNAME, TSHORT,
- SAREG, TWORD,
- NASL|NAREG, RESC1,
- " movswl AL,A1\n", },
-
-/* convert unsigned short to (u)int. */
-{ SCONV, ININT,
- SAREG|SOREG|SNAME, TUSHORT,
- SAREG, TWORD,
- NASL|NAREG, RESC1,
- " movzwl AL,A1\n", },
-
-/* convert short to (u)long long */
-{ SCONV, INLL,
- SAREG|SOREG|SNAME, TSHORT,
- SHLL, TLL,
- NSPECIAL|NCREG|NCSL, RESC1,
- " movswl AL,%eax\n cltd\n", },
-
-/* convert unsigned short to (u)long long */
-{ SCONV, INLL,
- SAREG|SOREG|SNAME, TUSHORT,
- SHLL, TLL,
- NCREG|NCSL, RESC1,
- " movzwl AL,A1\n xorl U1,U1\n", },
-
-/* convert short (in memory) to float/double */
-{ SCONV, INFL,
- SOREG|SNAME, TSHORT,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- NDREG, RESC1,
- " fild AL\n", },
-
-/* convert short (in register) to float/double */
-{ SCONV, INFL,
- SAREG, TSHORT,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- NTEMP|NDREG, RESC1,
- " pushw AL\n fild (%esp)\n addl $2,%esp\n", },
-
-/* convert unsigned short to double XXX - use NTEMP */
-{ SCONV, INFL,
- SAREG|SOREG|SNAME, TUSHORT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NAREG|NASL|NDREG|NTEMP, RESC2,
- " movzwl AL,A1\n pushl A1\n"
- " fildl (%esp)\n addl $4,%esp\n", },
-
-/* int to something */
-
-/* convert int to char. This is done when register is loaded */
-{ SCONV, INCH,
- SAREG, TWORD,
- SANY, TCHAR|TUCHAR,
- NSPECIAL|NBREG|NBSL, RESC1,
- "ZM", },
-
-/* convert int to short. Nothing to do */
-{ SCONV, INAREG,
- SAREG, TWORD,
- SANY, TSHORT|TUSHORT,
- 0, RLEFT,
- "", },
-
-/* convert int to long long */
-{ SCONV, INLL,
- SAREG, TWORD|TPOINT,
- SCREG, TLONGLONG,
- NSPECIAL|NCREG|NCSL, RESC1,
- " cltd\n", },
-
-/* convert int to unsigned long long */
-{ SCONV, INLL,
- SAREG|SOREG|SNAME, TWORD|TPOINT,
- SHLL, TULONGLONG,
- NCSL|NCREG, RESC1,
- " movl AL,A1\n xorl U1,U1\n", },
-
-/* convert int (in memory) to double */
-{ SCONV, INFL,
- SOREG|SNAME, TWORD,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NDREG, RESC1,
- " fildl AL\n", },
-
-/* convert int (in register) to double */
-{ SCONV, INFL,
- SAREG, TWORD,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NTEMP|NDREG, RESC1,
- " pushl AL\n fildl (%esp)\n addl $4,%esp\n", },
-
-/* long long to something */
-
-/* convert (u)long long to (u)char (mem->reg) */
-{ SCONV, INCH,
- SOREG|SNAME, TLL,
- SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
- " movb AL,A1\n", },
-
-/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */
-{ SCONV, INCH,
- SHLL, TLL,
- SANY, TCHAR|TUCHAR,
- NAREG|NASL, RESC1,
- "ZS", },
-
-/* convert (u)long long to (u)short (mem->reg) */
-{ SCONV, INAREG,
- SOREG|SNAME, TLL,
- SAREG, TSHORT|TUSHORT,
- NAREG|NASL, RESC1,
- " movw AL,A1\n", },
-
-/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */
-{ SCONV, INAREG,
- SHLL|SOREG|SNAME, TLL,
- SAREG, TSHORT|TUSHORT,
- NAREG|NASL, RESC1,
- "ZS", },
-
-/* convert long long to int (mem->reg) */
-{ SCONV, INAREG,
- SOREG|SNAME, TLL,
- SAREG, TWORD|TPOINT,
- NAREG|NASL, RESC1,
- " movl AL,A1\n", },
-
-/* convert long long to int (reg->reg, hopefully nothing) */
-{ SCONV, INAREG,
- SHLL|SOREG|SNAME, TLL,
- SAREG, TWORD|TPOINT,
- NAREG|NASL, RESC1,
- "ZS", },
-
-/* convert long long (in memory) to floating */
-{ SCONV, INFL,
- SOREG|SNAME, TLONGLONG,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NDREG, RESC1,
- " fildq AL\n", },
-
-/* convert long long (in register) to floating */
-{ SCONV, INFL,
- SHLL, TLONGLONG,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- NTEMP|NDREG, RESC1,
- " pushl UL\n pushl AL\n"
- " fildq (%esp)\n addl $8,%esp\n", },
-
-/* convert unsigned long long to floating */
-{ SCONV, INFL,
- SCREG, TULONGLONG,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- NDREG, RESC1,
- "ZJ", },
-
-/* float to something */
-
-#if 0 /* go via int by adding an extra sconv in clocal() */
-/* convert float/double to (u) char. XXX should use NTEMP here */
-{ SCONV, INCH,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- NBREG, RESC1,
- " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
-
-/* convert float/double to (u) int/short/char. XXX should use NTEMP here */
-{ SCONV, INCH,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- NCREG, RESC1,
- " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
-#endif
-
-/* convert float/double to (u)int. XXX should use NTEMP here */
-{ SCONV, INAREG,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SAREG, TWORD,
- NAREG, RESC1,
- " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
-
-/* convert float/double (in register) to (unsigned) long long */
-/* XXX - unsigned is not handled correct */
-{ SCONV, INLL,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHLL, TLONGLONG|TULONGLONG,
- NCREG, RESC1,
- " subl $8,%esp\n fistpq (%esp)\n"
- " popl A1\n popl U1\n", },
-
-/* slut sconv */
-
-/*
- * Subroutine calls.
- */
-
-{ CALL, FOREFF,
- SCON, TANY,
- SANY, TANY,
- 0, 0,
- " call CL\nZC", },
-
-{ UCALL, FOREFF,
- SCON, TANY,
- SAREG, TWORD|TPOINT,
- 0, 0,
- " call CL\n", },
-
-{ CALL, INAREG,
- SCON, TANY,
- SAREG, TWORD|TPOINT,
- NAREG|NASL, RESC1, /* should be 0 */
- " call CL\nZC", },
-
-{ UCALL, INAREG,
- SCON, TANY,
- SAREG, TWORD|TPOINT,
- NAREG|NASL, RESC1, /* should be 0 */
- " call CL\n", },
-
-{ CALL, INBREG,
- SCON, TANY,
- SBREG, TCHAR|TUCHAR,
- NBREG, RESC1, /* should be 0 */
- " call CL\nZC", },
-
-{ UCALL, INBREG,
- SCON, TANY,
- SBREG, TCHAR|TUCHAR,
- NBREG, RESC1, /* should be 0 */
- " call CL\n", },
-
-{ CALL, INCREG,
- SCON, TANY,
- SCREG, TANY,
- NCREG|NCSL, RESC1, /* should be 0 */
- " call CL\nZC", },
-
-{ UCALL, INCREG,
- SCON, TANY,
- SCREG, TANY,
- NCREG|NCSL, RESC1, /* should be 0 */
- " call CL\n", },
-
-{ CALL, INDREG,
- SCON, TANY,
- SDREG, TANY,
- NDREG|NDSL, RESC1, /* should be 0 */
- " call CL\nZC", },
-
-{ UCALL, INDREG,
- SCON, TANY,
- SDREG, TANY,
- NDREG|NDSL, RESC1, /* should be 0 */
- " call CL\nZC", },
-
-{ CALL, FOREFF,
- SAREG, TANY,
- SANY, TANY,
- 0, 0,
- " call *AL\nZC", },
-
-{ UCALL, FOREFF,
- SAREG, TANY,
- SANY, TANY,
- 0, 0,
- " call *AL\nZC", },
-
-{ CALL, INAREG,
- SAREG, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ UCALL, INAREG,
- SAREG, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ CALL, INBREG,
- SAREG, TANY,
- SANY, TANY,
- NBREG|NBSL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ UCALL, INBREG,
- SAREG, TANY,
- SANY, TANY,
- NBREG|NBSL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ CALL, INCREG,
- SAREG, TANY,
- SANY, TANY,
- NCREG|NCSL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ UCALL, INCREG,
- SAREG, TANY,
- SANY, TANY,
- NCREG|NCSL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ CALL, INDREG,
- SAREG, TANY,
- SANY, TANY,
- NDREG|NDSL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-{ UCALL, INDREG,
- SAREG, TANY,
- SANY, TANY,
- NDREG|NDSL, RESC1, /* should be 0 */
- " call *AL\nZC", },
-
-/* struct return */
-{ USTCALL, FOREFF,
- SCON, TANY,
- SANY, TANY,
- NAREG|NASL, 0,
- "ZP call CL\nZC", },
-
-{ USTCALL, INAREG,
- SCON, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- "ZP call CL\nZC", },
-
-{ USTCALL, INAREG,
- SNAME|SAREG, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- "ZP call *AL\nZC", },
-
-{ STCALL, FOREFF,
- SCON, TANY,
- SANY, TANY,
- NAREG|NASL, 0,
- "ZP call CL\nZC", },
-
-{ STCALL, INAREG,
- SCON, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- "ZP call CL\nZC", },
-
-{ STCALL, INAREG,
- SNAME|SAREG, TANY,
- SANY, TANY,
- NAREG|NASL, RESC1, /* should be 0 */
- "ZP call *AL\nZC", },
-
-/*
- * The next rules handle all binop-style operators.
- */
-/* Special treatment for long long */
-{ PLUS, INLL|FOREFF,
- SHLL, TLL,
- SHLL|SNAME|SOREG, TLL,
- 0, RLEFT,
- " addl AR,AL\n adcl UR,UL\n", },
-
-/* Special treatment for long long XXX - fix commutative check */
-{ PLUS, INLL|FOREFF,
- SHLL|SNAME|SOREG, TLL,
- SHLL, TLL,
- 0, RRIGHT,
- " addl AL,AR\n adcl UL,UR\n", },
-
-{ PLUS, INFL,
- SHFL, TDOUBLE,
- SNAME|SOREG, TDOUBLE,
- 0, RLEFT,
- " faddl AR\n", },
-
-{ PLUS, INFL|FOREFF,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RLEFT,
- " faddp\n", },
-
-{ PLUS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TWORD|TPOINT,
- SONE, TANY,
- 0, RLEFT,
- " incl AL\n", },
-
-{ PLUS, INAREG,
- SAREG, TWORD|TPOINT,
- SCON, TANY,
- NAREG|NASL, RESC1,
- " leal CR(AL),A1\n", },
-
-{ PLUS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SONE, TANY,
- 0, RLEFT,
- " incb AL\n", },
-
-{ PLUS, INAREG,
- SAREG, TWORD,
- SAREG, TWORD,
- NAREG|NASL|NASR, RESC1,
- " leal (AL,AR),A1\n", },
-
-{ MINUS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TWORD|TPOINT,
- SONE, TANY,
- 0, RLEFT,
- " decl AL\n", },
-
-{ MINUS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SONE, TANY,
- 0, RLEFT,
- " decb AL\n", },
-
-/* address as register offset, negative */
-{ MINUS, INAREG,
- SAREG, TWORD|TPOINT,
- SPCON, TANY,
- NAREG|NASL, RESC1,
- " leal -CR(AL),A1\n", },
-
-{ MINUS, INLL|FOREFF,
- SHLL, TLL,
- SHLL|SNAME|SOREG, TLL,
- 0, RLEFT,
- " subl AR,AL\n sbbl UR,UL\n", },
-
-{ MINUS, INFL,
- SHFL, TDOUBLE,
- SNAME|SOREG, TDOUBLE,
- 0, RLEFT,
- " fsubl AR\n", },
-
-{ MINUS, INFL|FOREFF,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RLEFT,
- " fsubZAp\n", },
-
-/* Simple r/m->reg ops */
-{ OPSIMP, INAREG|FOREFF,
- SAREG, TWORD|TPOINT,
- SAREG|SNAME|SOREG, TWORD|TPOINT,
- 0, RLEFT,
- " Ol AR,AL\n", },
-
-{ OPSIMP, INAREG|FOREFF,
- SHINT, TSHORT|TUSHORT,
- SHINT|SNAME|SOREG, TSHORT|TUSHORT,
- 0, RLEFT,
- " Ow AR,AL\n", },
-
-{ OPSIMP, INCH|FOREFF,
- SHCH, TCHAR|TUCHAR,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- 0, RLEFT,
- " Ob AR,AL\n", },
-
-{ OPSIMP, INAREG|FOREFF,
- SAREG, TWORD|TPOINT,
- SCON, TWORD|TPOINT,
- 0, RLEFT,
- " Ol AR,AL\n", },
-
-{ OPSIMP, INAREG|FOREFF,
- SHINT|SNAME|SOREG, TSHORT|TUSHORT,
- SCON, TANY,
- 0, RLEFT,
- " Ow AR,AL\n", },
-
-{ OPSIMP, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SCON, TANY,
- 0, RLEFT,
- " Ob AR,AL\n", },
-
-{ OPSIMP, INLL|FOREFF,
- SHLL, TLL,
- SHLL|SNAME|SOREG, TLL,
- 0, RLEFT,
- " Ol AR,AL\n Ol UR,UL\n", },
-
-
-/*
- * The next rules handle all shift operators.
- */
-/* (u)longlong left shift is emulated */
-{ LS, INCREG,
- SCREG|SNAME|SOREG|SCON, TLL,
- SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
- NSPECIAL|NCREG|NCSL|NCSR, RESC1,
- "ZO", },
-
-{ LS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TWORD,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " sall AR,AL\n", },
-
-{ LS, INAREG|FOREFF,
- SAREG, TWORD,
- SCON, TANY,
- 0, RLEFT,
- " sall AR,AL\n", },
-
-{ LS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TSHORT|TUSHORT,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " shlw AR,AL\n", },
-
-{ LS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TSHORT|TUSHORT,
- SCON, TANY,
- 0, RLEFT,
- " shlw AR,AL\n", },
-
-{ LS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " salb AR,AL\n", },
-
-{ LS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SCON, TANY,
- 0, RLEFT,
- " salb AR,AL\n", },
-
-/* (u)longlong right shift is emulated */
-{ RS, INCREG,
- SCREG|SNAME|SOREG|SCON, TLL,
- SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
- NSPECIAL|NCREG|NCSL|NCSR, RESC1,
- "ZO", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TSWORD,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " sarl AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TSWORD,
- SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
- 0, RLEFT,
- " sarl AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TUWORD,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " shrl AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TUWORD,
- SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
- 0, RLEFT,
- " shrl AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TSHORT,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " sarw AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TSHORT,
- SCON, TANY,
- 0, RLEFT,
- " sarw AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TUSHORT,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " shrw AR,AL\n", },
-
-{ RS, INAREG|FOREFF,
- SAREG|SNAME|SOREG, TUSHORT,
- SCON, TANY,
- 0, RLEFT,
- " shrw AR,AL\n", },
-
-{ RS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " sarb AR,AL\n", },
-
-{ RS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TCHAR,
- SCON, TANY,
- 0, RLEFT,
- " sarb AR,AL\n", },
-
-{ RS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TUCHAR,
- SHCH, TCHAR|TUCHAR,
- NSPECIAL, RLEFT,
- " shrb AR,AL\n", },
-
-{ RS, INCH|FOREFF,
- SHCH|SNAME|SOREG, TUCHAR,
- SCON, TANY,
- 0, RLEFT,
- " shrb AR,AL\n", },
-
-/*
- * The next rules takes care of assignments. "=".
- */
-{ ASSIGN, FOREFF,
- SHLL|SNAME|SOREG, TLL,
- SCON, TANY,
- 0, 0,
- " movl AR,AL\n movl UR,UL\n", },
-
-{ ASSIGN, FOREFF|INLL,
- SHLL, TLL,
- SCON, TANY,
- 0, RDEST,
- " movl AR,AL\n movl UR,UL\n", },
-
-{ ASSIGN, FOREFF,
- SAREG|SNAME|SOREG, TWORD|TPOINT,
- SCON, TANY,
- 0, 0,
- " movl AR,AL\n", },
-
-{ ASSIGN, FOREFF|INAREG,
- SAREG, TWORD|TPOINT,
- SCON, TANY,
- 0, RDEST,
- " movl AR,AL\n", },
-
-{ ASSIGN, FOREFF,
- SAREG|SNAME|SOREG, TSHORT|TUSHORT,
- SCON, TANY,
- 0, 0,
- " movw AR,AL\n", },
-
-{ ASSIGN, FOREFF|INAREG,
- SAREG, TSHORT|TUSHORT,
- SCON, TANY,
- 0, RDEST,
- " movw AR,AL\n", },
-
-{ ASSIGN, FOREFF,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SCON, TANY,
- 0, 0,
- " movb AR,AL\n", },
-
-{ ASSIGN, FOREFF|INCH,
- SHCH, TCHAR|TUCHAR,
- SCON, TANY,
- 0, RDEST,
- " movb AR,AL\n", },
-
-{ ASSIGN, FOREFF|INLL,
- SHLL|SNAME|SOREG, TLL,
- SHLL, TLL,
- 0, RDEST,
- " movl AR,AL\n movl UR,UL\n", },
-
-{ ASSIGN, FOREFF|INAREG,
- SAREG|SNAME|SOREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
- 0, RDEST,
- " movl AR,AL\n", },
-
-{ ASSIGN, FOREFF|INAREG,
- SAREG, TWORD|TPOINT,
- SAREG|SNAME|SOREG, TWORD|TPOINT,
- 0, RDEST,
- " movl AR,AL\n", },
-
-{ ASSIGN, FOREFF|INAREG,
- SAREG|SNAME|SOREG, TSHORT|TUSHORT,
- SAREG, TSHORT|TUSHORT,
- 0, RDEST,
- " movw AR,AL\n", },
-
-{ ASSIGN, FOREFF|INCH,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- SHCH, TCHAR|TUCHAR|TWORD,
- 0, RDEST,
- " movb AR,AL\n", },
-
-{ ASSIGN, FOREFF|INBREG,
- SFLD, TCHAR|TUCHAR,
- SBREG|SCON, TCHAR|TUCHAR,
- NBREG, RDEST,
- "ZE", },
-
-{ ASSIGN, FOREFF|INAREG,
- SFLD, TANY,
- SAREG, TANY,
- NAREG, RDEST,
- "ZE", },
-
-{ ASSIGN, FOREFF,
- SFLD, TANY,
- SAREG|SNAME|SOREG|SCON, TANY,
- NAREG, 0,
- "ZE", },
-
-{ ASSIGN, INDREG|FOREFF,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, RDEST,
- "", }, /* This will always be in the correct register */
-
-/* order of table entries is very important here! */
-{ ASSIGN, INFL,
- SNAME|SOREG, TLDOUBLE,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, RDEST,
- " fstt AL\n", },
-
-{ ASSIGN, FOREFF,
- SNAME|SOREG, TLDOUBLE,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, 0,
- " fstpt AL\n", },
-
-{ ASSIGN, INFL,
- SNAME|SOREG, TDOUBLE,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, RDEST,
- " fstl AL\n", },
-
-{ ASSIGN, FOREFF,
- SNAME|SOREG, TDOUBLE,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, 0,
- " fstpl AL\n", },
-
-{ ASSIGN, INFL,
- SNAME|SOREG, TFLOAT,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, RDEST,
- " fsts AL\n", },
-
-{ ASSIGN, FOREFF,
- SNAME|SOREG, TFLOAT,
- SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
- 0, 0,
- " fstps AL\n", },
-/* end very important order */
-
-{ ASSIGN, INFL|FOREFF,
- SHFL, TLDOUBLE,
- SHFL|SOREG|SNAME, TLDOUBLE,
- 0, RDEST,
- " fldt AR\n", },
-
-{ ASSIGN, INFL|FOREFF,
- SHFL, TDOUBLE,
- SHFL|SOREG|SNAME, TDOUBLE,
- 0, RDEST,
- " fldl AR\n", },
-
-{ ASSIGN, INFL|FOREFF,
- SHFL, TFLOAT,
- SHFL|SOREG|SNAME, TFLOAT,
- 0, RDEST,
- " flds AR\n", },
-
-/* Do not generate memcpy if return from funcall */
-#if 0
-{ STASG, INAREG|FOREFF,
- SOREG|SNAME|SAREG, TPTRTO|TSTRUCT,
- SFUNCALL, TPTRTO|TSTRUCT,
- 0, RRIGHT,
- "", },
-#endif
-
-{ STASG, INAREG|FOREFF,
- SOREG|SNAME, TANY,
- SAREG|SOREG|SNAME, TPTRTO|TANY,
- NSPECIAL, RRIGHT,
- "ZQ", },
-
-/*
- * DIV/MOD/MUL
- */
-/* long long div is emulated */
-{ DIV, INCREG,
- SCREG|SNAME|SOREG|SCON, TLL,
- SCREG|SNAME|SOREG|SCON, TLL,
- NSPECIAL|NCREG|NCSL|NCSR, RESC1,
- "ZO", },
-
-{ DIV, INAREG,
- SAREG, TSWORD,
- SAREG|SNAME|SOREG, TWORD,
- NSPECIAL, RDEST,
- " cltd\n idivl AR\n", },
-
-{ DIV, INAREG,
- SAREG, TUWORD|TPOINT,
- SAREG|SNAME|SOREG, TUWORD|TPOINT,
- NSPECIAL, RDEST,
- " xorl %edx,%edx\n divl AR\n", },
-
-{ DIV, INAREG,
- SAREG, TUSHORT,
- SAREG|SNAME|SOREG, TUSHORT,
- NSPECIAL, RDEST,
- " xorl %edx,%edx\n divw AR\n", },
-
-{ DIV, INCH,
- SHCH, TUCHAR,
- SHCH|SNAME|SOREG, TUCHAR,
- NSPECIAL, RDEST,
- " xorb %ah,%ah\n divb AR\n", },
-
-{ DIV, INFL,
- SHFL, TDOUBLE,
- SNAME|SOREG, TDOUBLE,
- 0, RLEFT,
- " fdivl AR\n", },
-
-{ DIV, INFL,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RLEFT,
- " fdivZAp\n", },
-
-/* (u)longlong mod is emulated */
-{ MOD, INCREG,
- SCREG|SNAME|SOREG|SCON, TLL,
- SCREG|SNAME|SOREG|SCON, TLL,
- NSPECIAL|NCREG|NCSL|NCSR, RESC1,
- "ZO", },
-
-{ MOD, INAREG,
- SAREG, TSWORD,
- SAREG|SNAME|SOREG, TSWORD,
- NAREG|NSPECIAL, RESC1,
- " cltd\n idivl AR\n", },
-
-{ MOD, INAREG,
- SAREG, TWORD|TPOINT,
- SAREG|SNAME|SOREG, TUWORD|TPOINT,
- NAREG|NSPECIAL, RESC1,
- " xorl %edx,%edx\n divl AR\n", },
-
-{ MOD, INAREG,
- SAREG, TUSHORT,
- SAREG|SNAME|SOREG, TUSHORT,
- NAREG|NSPECIAL, RESC1,
- " xorl %edx,%edx\n divw AR\n", },
-
-{ MOD, INCH,
- SHCH, TUCHAR,
- SHCH|SNAME|SOREG, TUCHAR,
- NBREG|NSPECIAL, RESC1,
- " xorb %ah,%ah\n divb AR\n", },
-
-/* (u)longlong mul is emulated */
-{ MUL, INCREG,
- SCREG|SNAME|SOREG|SCON, TLL,
- SCREG|SNAME|SOREG|SCON, TLL,
- NSPECIAL|NCREG|NCSL|NCSR, RESC1,
- "ZO", },
-
-{ MUL, INAREG,
- SAREG, TWORD|TPOINT,
- SAREG|SNAME|SOREG|SCON, TWORD|TPOINT,
- 0, RLEFT,
- " imull AR,AL\n", },
-
-{ MUL, INAREG,
- SAREG, TSHORT|TUSHORT,
- SAREG|SNAME|SOREG, TSHORT|TUSHORT,
- 0, RLEFT,
- " imulw AR,AL\n", },
-
-{ MUL, INCH,
- SHCH, TCHAR|TUCHAR,
- SHCH|SNAME|SOREG, TCHAR|TUCHAR,
- NSPECIAL, RDEST,
- " imulb AR\n", },
-
-{ MUL, INFL,
- SHFL, TDOUBLE,
- SNAME|SOREG, TDOUBLE,
- 0, RLEFT,
- " fmull AR\n", },
-
-{ MUL, INFL,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RLEFT,
- " fmulp\n", },
-
-/*
- * Indirection operators.
- */
-{ UMUL, INLL,
- SANY, TANY,
- SOREG, TLL,
- NCREG|NCSL, RESC1,
- " movl UL,U1\n movl AL,A1\n", },
-
-{ UMUL, INAREG,
- SANY, TPOINT|TWORD,
- SOREG, TPOINT|TWORD,
- NAREG|NASL, RESC1,
- " movl AL,A1\n", },
-
-{ UMUL, INCH,
- SANY, TANY,
- SOREG, TCHAR|TUCHAR,
- NBREG|NBSL, RESC1,
- " movb AL,A1\n", },
-
-{ UMUL, INAREG,
- SANY, TANY,
- SOREG, TSHORT|TUSHORT,
- NAREG|NASL, RESC1,
- " movw AL,A1\n", },
-
-{ UMUL, INFL,
- SANY, TANY,
- SOREG, TLDOUBLE,
- NDREG|NDSL, RESC1,
- " fldt AL\n", },
-
-{ UMUL, INFL,
- SANY, TANY,
- SOREG, TDOUBLE,
- NDREG|NDSL, RESC1,
- " fldl AL\n", },
-
-{ UMUL, INFL,
- SANY, TANY,
- SOREG, TFLOAT,
- NDREG|NDSL, RESC1,
- " flds AL\n", },
-
-/*
- * Logical/branching operators
- */
-
-/* Comparisions, take care of everything */
-{ OPLOG, FORCC,
- SHLL|SOREG|SNAME, TLL,
- SHLL, TLL,
- 0, 0,
- "ZD", },
-
-{ OPLOG, FORCC,
- SAREG|SOREG|SNAME, TWORD|TPOINT,
- SCON|SAREG, TWORD|TPOINT,
- 0, RESCC,
- " cmpl AR,AL\n", },
-
-{ OPLOG, FORCC,
- SCON|SAREG, TWORD|TPOINT,
- SAREG|SOREG|SNAME, TWORD|TPOINT,
- 0, RESCC,
- " cmpl AR,AL\n", },
-
-{ OPLOG, FORCC,
- SAREG|SOREG|SNAME, TSHORT|TUSHORT,
- SCON|SAREG, TANY,
- 0, RESCC,
- " cmpw AR,AL\n", },
-
-{ OPLOG, FORCC,
- SBREG|SOREG|SNAME, TCHAR|TUCHAR,
- SCON|SBREG, TANY,
- 0, RESCC,
- " cmpb AR,AL\n", },
-
-{ OPLOG, FORCC,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- NSPECIAL, 0,
- "ZG", },
-
-{ OPLOG, FORCC,
- SOREG|SNAME, TDOUBLE|TFLOAT,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- NSPECIAL, 0,
- "ZG", },
-
-#if 0
-/* Ppro and later only */
-{ OPLOG, FORCC,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RESCC,
- "ZA fucomip %st,%st(1)\n", },
-#endif
-
-{ OPLOG, FORCC,
- SANY, TANY,
- SANY, TANY,
- REWRITE, 0,
- "diediedie!", },
-
-/* AND/OR/ER/NOT */
-{ AND, INAREG|FOREFF,
- SAREG|SOREG|SNAME, TWORD,
- SCON|SAREG, TWORD,
- 0, RLEFT,
- " andl AR,AL\n", },
-
-{ AND, INCREG|FOREFF,
- SCREG, TLL,
- SCREG|SOREG|SNAME, TLL,
- 0, RLEFT,
- " andl AR,AL\n andl UR,UL\n", },
-
-{ AND, INAREG|FOREFF,
- SAREG, TWORD,
- SAREG|SOREG|SNAME, TWORD,
- 0, RLEFT,
- " andl AR,AL\n", },
-
-{ AND, INAREG|FOREFF,
- SAREG|SOREG|SNAME, TSHORT|TUSHORT,
- SCON|SAREG, TSHORT|TUSHORT,
- 0, RLEFT,
- " andw AR,AL\n", },
-
-{ AND, INAREG|FOREFF,
- SAREG, TSHORT|TUSHORT,
- SAREG|SOREG|SNAME, TSHORT|TUSHORT,
- 0, RLEFT,
- " andw AR,AL\n", },
-
-{ AND, INBREG|FOREFF,
- SBREG|SOREG|SNAME, TCHAR|TUCHAR,
- SCON|SBREG, TCHAR|TUCHAR,
- 0, RLEFT,
- " andb AR,AL\n", },
-
-{ AND, INBREG|FOREFF,
- SBREG, TCHAR|TUCHAR,
- SBREG|SOREG|SNAME, TCHAR|TUCHAR,
- 0, RLEFT,
- " andb AR,AL\n", },
-/* AND/OR/ER/NOT */
-
-/*
- * Jumps.
- */
-{ GOTO, FOREFF,
- SCON, TANY,
- SANY, TANY,
- 0, RNOP,
- " jmp LL\n", },
-
-#ifdef GCC_COMPAT
-{ GOTO, FOREFF,
- SAREG, TANY,
- SANY, TANY,
- 0, RNOP,
- " jmp *AL\n", },
-#endif
-
-/*
- * Convert LTYPE to reg.
- */
-{ OPLTYPE, INLL,
- SANY, TANY,
- SCREG|SCON|SOREG|SNAME, TLL,
- NCREG, RESC1,
- " movl UL,U1\n movl AL,A1\n", },
-
-{ OPLTYPE, INAREG,
- SANY, TANY,
- SAREG|SCON|SOREG|SNAME, TWORD|TPOINT,
- NAREG|NASL, RESC1,
- " movl AL,A1\n", },
-
-{ OPLTYPE, INBREG,
- SANY, TANY,
- SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR,
- NBREG, RESC1,
- " movb AL,A1\n", },
-
-{ OPLTYPE, INAREG,
- SANY, TANY,
- SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT,
- NAREG, RESC1,
- " movw AL,A1\n", },
-
-{ OPLTYPE, INDREG,
- SANY, TLDOUBLE,
- SOREG|SNAME, TLDOUBLE,
- NDREG, RESC1,
- " fldt AL\n", },
-
-{ OPLTYPE, INDREG,
- SANY, TDOUBLE,
- SOREG|SNAME, TDOUBLE,
- NDREG, RESC1,
- " fldl AL\n", },
-
-{ OPLTYPE, INDREG,
- SANY, TFLOAT,
- SOREG|SNAME, TFLOAT,
- NDREG, RESC1,
- " flds AL\n", },
-
-/* Only used in ?: constructs. The stack already contains correct value */
-{ OPLTYPE, INDREG,
- SANY, TFLOAT|TDOUBLE|TLDOUBLE,
- SDREG, TFLOAT|TDOUBLE|TLDOUBLE,
- NDREG, RESC1,
- "", },
-
-/*
- * Negate a word.
- */
-
-{ UMINUS, INCREG|FOREFF,
- SCREG, TLL,
- SCREG, TLL,
- 0, RLEFT,
- " negl AL\n adcl $0,UL\n negl UL\n", },
-
-{ UMINUS, INAREG|FOREFF,
- SAREG, TWORD|TPOINT,
- SAREG, TWORD|TPOINT,
- 0, RLEFT,
- " negl AL\n", },
-
-{ UMINUS, INAREG|FOREFF,
- SAREG, TSHORT|TUSHORT,
- SAREG, TSHORT|TUSHORT,
- 0, RLEFT,
- " negw AL\n", },
-
-{ UMINUS, INBREG|FOREFF,
- SBREG, TCHAR|TUCHAR,
- SBREG, TCHAR|TUCHAR,
- 0, RLEFT,
- " negb AL\n", },
-
-{ UMINUS, INFL|FOREFF,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
- 0, RLEFT,
- " fchs\n", },
-
-{ COMPL, INCREG,
- SCREG, TLL,
- SANY, TANY,
- 0, RLEFT,
- " notl AL\n notl UL\n", },
-
-{ COMPL, INAREG,
- SAREG, TWORD,
- SANY, TANY,
- 0, RLEFT,
- " notl AL\n", },
-
-{ COMPL, INAREG,
- SAREG, TSHORT|TUSHORT,
- SANY, TANY,
- 0, RLEFT,
- " notw AL\n", },
-
-{ COMPL, INBREG,
- SBREG, TCHAR|TUCHAR,
- SANY, TANY,
- 0, RLEFT,
- " notb AL\n", },
-
-/*
- * Arguments to functions.
- */
-{ FUNARG, FOREFF,
- SCON|SCREG|SNAME|SOREG, TLL,
- SANY, TLL,
- 0, RNULL,
- " pushl UL\n pushl AL\n", },
-
-{ FUNARG, FOREFF,
- SCON|SAREG|SNAME|SOREG, TWORD|TPOINT,
- SANY, TWORD|TPOINT,
- 0, RNULL,
- " pushl AL\n", },
-
-{ FUNARG, FOREFF,
- SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
- 0, RNULL,
- " pushl AL\n", },
-
-{ FUNARG, FOREFF,
- SAREG|SNAME|SOREG, TSHORT,
- SANY, TSHORT,
- NAREG, 0,
- " movswl AL,ZN\n pushl ZN\n", },
-
-{ FUNARG, FOREFF,
- SAREG|SNAME|SOREG, TUSHORT,
- SANY, TUSHORT,
- NAREG, 0,
- " movzwl AL,ZN\n pushl ZN\n", },
-
-{ FUNARG, FOREFF,
- SHCH|SNAME|SOREG, TCHAR,
- SANY, TCHAR,
- NAREG, 0,
- " movsbl AL,A1\n pushl A1\n", },
-
-{ FUNARG, FOREFF,
- SHCH|SNAME|SOREG, TUCHAR,
- SANY, TUCHAR,
- NAREG, 0,
- " movzbl AL,A1\n pushl A1\n", },
-
-{ FUNARG, FOREFF,
- SNAME|SOREG, TDOUBLE,
- SANY, TDOUBLE,
- 0, 0,
- " pushl UL\n pushl AL\n", },
-
-{ FUNARG, FOREFF,
- SDREG, TDOUBLE,
- SANY, TDOUBLE,
- 0, 0,
- " subl $8,%esp\n fstpl (%esp)\n", },
-
-{ FUNARG, FOREFF,
- SNAME|SOREG, TFLOAT,
- SANY, TFLOAT,
- 0, 0,
- " pushl AL\n", },
-
-{ FUNARG, FOREFF,
- SDREG, TFLOAT,
- SANY, TFLOAT,
- 0, 0,
- " subl $4,%esp\n fstps (%esp)\n", },
-
-{ FUNARG, FOREFF,
- SDREG, TLDOUBLE,
- SANY, TLDOUBLE,
- 0, 0,
- " subl $12,%esp\n fstpt (%esp)\n", },
-
-{ STARG, FOREFF,
- SAREG|SOREG|SNAME|SCON, TANY,
- SANY, TSTRUCT,
- NSPECIAL|NAREG, 0,
- "ZF", },
-
-# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
-
-{ UMUL, DF( UMUL ), },
-
-{ ASSIGN, DF(ASSIGN), },
-
-{ STASG, DF(STASG), },
-
-{ FLD, DF(FLD), },
-
-{ OPLEAF, DF(NAME), },
-
-/* { INIT, DF(INIT), }, */
-
-{ OPUNARY, DF(UMINUS), },
-
-{ OPANY, DF(BITYPE), },
-
-{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
-};
-
-int tablesize = sizeof(table)/sizeof(table[0]);
--- usr.bin/pcc/arch/x86/local2.c
+++ /dev/null
@@ -1,1052 +0,0 @@
-/* $Id: local2.c,v 1.89 2007/09/16 19:08:16 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-# include "pass2.h"
-# include <ctype.h>
-# include <string.h>
-
-void acon(NODE *p);
-int argsize(NODE *p);
-
-static int stkpos;
-
-void
-lineid(int l, char *fn)
-{
- /* identify line l and file fn */
- printf("# line %d, file %s\n", l, fn);
-}
-
-void
-deflab(int label)
-{
- printf(LABFMT ":\n", label);
-}
-
-static int regoff[7];
-static TWORD ftype;
-
-/*
- * Print out the prolog assembler.
- * addto and regoff are already calculated.
- */
-static void
-prtprolog(struct interpass_prolog *ipp, int addto)
-{
- int i, j;
-
- printf(" pushl %%ebp\n");
- printf(" movl %%esp,%%ebp\n");
- if (addto)
- printf(" subl $%d,%%esp\n", addto);
- for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
- if (i & 1)
- fprintf(stdout, " movl %s,-%d(%s)\n",
- rnames[j], regoff[j], rnames[FPREG]);
-}
-
-/*
- * calculate stack size and offsets
- */
-static int
-offcalc(struct interpass_prolog *ipp)
-{
- int i, j, addto;
-
- addto = p2maxautooff;
- if (addto >= AUTOINIT/SZCHAR)
- addto -= AUTOINIT/SZCHAR;
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1) {
- addto += SZINT/SZCHAR;
- regoff[j] = addto;
- }
- }
- return addto;
-}
-
-void
-prologue(struct interpass_prolog *ipp)
-{
- int addto;
-
- ftype = ipp->ipp_type;
- if (ipp->ipp_vis)
- printf(" .globl %s\n", ipp->ipp_name);
- printf(" .align 4\n");
- printf("%s:\n", ipp->ipp_name);
- /*
- * We here know what register to save and how much to
- * add to the stack.
- */
- addto = offcalc(ipp);
- prtprolog(ipp, addto);
-}
-
-void
-eoftn(struct interpass_prolog *ipp)
-{
- int i, j;
-
- if (ipp->ipp_ip.ip_lbl == 0)
- return; /* no code needs to be generated */
-
- /* return from function code */
- for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
- if (i & 1)
- fprintf(stdout, " movl -%d(%s),%s\n",
- regoff[j], rnames[FPREG], rnames[j]);
-
- }
-
- /* struct return needs special treatment */
- if (ftype == STRTY || ftype == UNIONTY) {
- printf(" movl 8(%%ebp),%%eax\n");
- printf(" leave\n");
- printf(" ret $4\n");
- } else {
- printf(" leave\n");
- printf(" ret\n");
- }
-}
-
-/*
- * add/sub/...
- *
- * Param given:
- */
-void
-hopcode(int f, int o)
-{
- char *str;
-
- switch (o) {
- case PLUS:
- str = "add";
- break;
- case MINUS:
- str = "sub";
- break;
- case AND:
- str = "and";
- break;
- case OR:
- str = "or";
- break;
- case ER:
- str = "xor";
- break;
- default:
- comperr("hopcode2: %d", o);
- str = 0; /* XXX gcc */
- }
- printf("%s%c", str, f);
-}
-
-/*
- * Return type size in bytes. Used by R2REGS, arg 2 to offset().
- */
-int
-tlen(p) NODE *p;
-{
- switch(p->n_type) {
- case CHAR:
- case UCHAR:
- return(1);
-
- case SHORT:
- case USHORT:
- return(SZSHORT/SZCHAR);
-
- case DOUBLE:
- return(SZDOUBLE/SZCHAR);
-
- case INT:
- case UNSIGNED:
- case LONG:
- case ULONG:
- return(SZINT/SZCHAR);
-
- case LONGLONG:
- case ULONGLONG:
- return SZLONGLONG/SZCHAR;
-
- default:
- if (!ISPTR(p->n_type))
- comperr("tlen type %d not pointer");
- return SZPOINT(p->n_type)/SZCHAR;
- }
-}
-
-/*
- * Emit code to compare two longlong numbers.
- */
-static void
-twollcomp(NODE *p)
-{
- int o = p->n_op;
- int s = getlab();
- int e = p->n_label;
- int cb1, cb2;
-
- if (o >= ULE)
- o -= (ULE-LE);
- switch (o) {
- case NE:
- cb1 = 0;
- cb2 = NE;
- break;
- case EQ:
- cb1 = NE;
- cb2 = 0;
- break;
- case LE:
- case LT:
- cb1 = GT;
- cb2 = LT;
- break;
- case GE:
- case GT:
- cb1 = LT;
- cb2 = GT;
- break;
-
- default:
- cb1 = cb2 = 0; /* XXX gcc */
- }
- if (p->n_op >= ULE)
- cb1 += 4, cb2 += 4;
- expand(p, 0, " cmpl UR,UL\n");
- if (cb1) cbgen(cb1, s);
- if (cb2) cbgen(cb2, e);
- expand(p, 0, " cmpl AR,AL\n");
- cbgen(p->n_op, e);
- deflab(s);
-}
-
-/*
- * Assign to a bitfield.
- * Clumsy at least, but what to do?
- */
-static void
-bfasg(NODE *p)
-{
- NODE *fn = p->n_left;
- int shift = UPKFOFF(fn->n_rval);
- int fsz = UPKFSZ(fn->n_rval);
- int andval, tch = 0;
-
- /* get instruction size */
- switch (p->n_type) {
- case CHAR: case UCHAR: tch = 'b'; break;
- case SHORT: case USHORT: tch = 'w'; break;
- case INT: case UNSIGNED: tch = 'l'; break;
- default: comperr("bfasg");
- }
-
- /* put src into a temporary reg */
- fprintf(stdout, " mov%c ", tch);
- adrput(stdout, getlr(p, 'R'));
- fprintf(stdout, ",");
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, "\n");
-
- /* AND away the bits from dest */
- andval = ~(((1 << fsz) - 1) << shift);
- fprintf(stdout, " and%c $%d,", tch, andval);
- adrput(stdout, fn->n_left);
- fprintf(stdout, "\n");
-
- /* AND away unwanted bits from src */
- andval = ((1 << fsz) - 1);
- fprintf(stdout, " and%c $%d,", tch, andval);
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, "\n");
-
- /* SHIFT left src number of bits */
- if (shift) {
- fprintf(stdout, " sal%c $%d,", tch, shift);
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, "\n");
- }
-
- /* OR in src to dest */
- fprintf(stdout, " or%c ", tch);
- adrput(stdout, getlr(p, '1'));
- fprintf(stdout, ",");
- adrput(stdout, fn->n_left);
- fprintf(stdout, "\n");
-}
-
-/*
- * Push a structure on stack as argument.
- * the scratch registers are already free here
- */
-static void
-starg(NODE *p)
-{
- FILE *fp = stdout;
-
- fprintf(fp, " subl $%d,%%esp\n", p->n_stsize);
- fprintf(fp, " pushl $%d\n", p->n_stsize);
- expand(p, 0, " pushl AL\n");
- expand(p, 0, " leal 8(%esp),A1\n");
- expand(p, 0, " pushl A1\n");
- fprintf(fp, " call memcpy\n");
- fprintf(fp, " addl $12,%%esp\n");
-}
-
-/*
- * Compare two floating point numbers.
- */
-static void
-fcomp(NODE *p)
-{
-
- if (p->n_left->n_op == REG) {
- if (p->n_su & DORIGHT)
- expand(p, 0, " fxch\n");
- expand(p, 0, " fucompp\n"); /* emit compare insn */
- } else if (p->n_left->n_type == DOUBLE)
- expand(p, 0, " fcompl AL\n"); /* emit compare insn */
- else if (p->n_left->n_type == FLOAT)
- expand(p, 0, " fcomp AL\n"); /* emit compare insn */
- else
- comperr("bad compare %p\n", p);
- expand(p, 0, " fnstsw %ax\n"); /* move status reg to ax */
-
- switch (p->n_op) {
- case EQ:
- expand(p, 0, " andb $64,%ah\n jne LC\n");
- break;
- case NE:
- expand(p, 0, " andb $64,%ah\n je LC\n");
- break;
- case LE:
- expand(p, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n");
- break;
- case LT:
- expand(p, 0, " andb $65,%ah\n je LC\n");
- break;
- case GT:
- expand(p, 0, " andb $1,%ah\n jne LC\n");
- break;
- case GE:
- expand(p, 0, " andb $65,%ah\n jne LC\n");
- break;
- default:
- comperr("fcomp op %d\n", p->n_op);
- }
-}
-
-/*
- * Convert an unsigned long long to floating point number.
- */
-static void
-ulltofp(NODE *p)
-{
- static int loadlab;
- int jmplab;
-
- if (loadlab == 0) {
- loadlab = getlab();
- expand(p, 0, " .data\n");
- printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
- expand(p, 0, " .text\n");
- }
- jmplab = getlab();
- expand(p, 0, " pushl UL\n pushl AL\n");
- expand(p, 0, " fildq (%esp)\n");
- expand(p, 0, " addl $8,%esp\n");
- expand(p, 0, " cmpl $0,UL\n");
- printf(" jge " LABFMT "\n", jmplab);
- printf(" fldt " LABFMT "\n", loadlab);
- printf(" faddp %%st,%%st(1)\n");
- printf(LABFMT ":\n", jmplab);
-}
-
-static int
-argsiz(NODE *p)
-{
- TWORD t = p->n_type;
-
- if (t < LONGLONG || t == FLOAT || t > BTMASK)
- return 4;
- if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
- return 8;
- if (t == LDOUBLE)
- return 12;
- if (t == STRTY || t == UNIONTY)
- return p->n_stsize;
- comperr("argsiz");
- return 0;
-}
-
-void
-zzzcode(NODE *p, int c)
-{
- NODE *r, *l;
- int pr, lr, s;
- char *ch;
-
- switch (c) {
- case 'A': /* swap st0 and st1 if right is evaluated second */
- if ((p->n_su & DORIGHT) == 0) {
- if (logop(p->n_op))
- printf(" fxch\n");
- else
- printf("r");
- }
- break;
-
- case 'C': /* remove from stack after subroutine call */
- pr = p->n_qual;
- if (p->n_op == STCALL || p->n_op == USTCALL)
- pr += 4;
- if (p->n_op == UCALL)
- return; /* XXX remove ZC from UCALL */
- if (pr)
- printf(" addl $%d, %s\n", pr, rnames[ESP]);
- break;
-
- case 'D': /* Long long comparision */
- twollcomp(p);
- break;
-
- case 'E': /* Assign to bitfield */
- bfasg(p);
- break;
-
- case 'F': /* Structure argument */
- if (p->n_stalign != 0) /* already on stack */
- starg(p);
- break;
-
- case 'G': /* Floating point compare */
- fcomp(p);
- break;
-
- case 'J': /* convert unsigned long long to floating point */
- ulltofp(p);
- break;
-
- case 'M': /* Output sconv move, if needed */
- l = getlr(p, 'L');
- /* XXX fixneed: regnum */
- pr = DECRA(p->n_reg, 0);
- lr = DECRA(l->n_reg, 0);
- if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
- (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
- ;
- else
- printf(" movb %%%cl,%s\n",
- rnames[lr][2], rnames[pr]);
- l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
- break;
-
- case 'N': /* output extended reg name */
- printf("%s", rnames[getlr(p, '1')->n_rval]);
- break;
-
- case 'O': /* print out emulated ops */
- pr = 16;
- if (p->n_op == RS || p->n_op == LS) {
- expand(p, INAREG, "\tpushl AR\n");
- pr = 12;
- } else
- expand(p, INCREG, "\tpushl UR\n\tpushl AR\n");
- expand(p, INCREG, "\tpushl UL\n\tpushl AL\n");
- if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv";
- else if (p->n_op == DIV) ch = "div";
- else if (p->n_op == MUL) ch = "mul";
- else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod";
- else if (p->n_op == MOD) ch = "mod";
- else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshr";
- else if (p->n_op == RS) ch = "ashr";
- else if (p->n_op == LS) ch = "ashl";
- else ch = 0, comperr("ZO");
- printf("\tcall __%sdi3\n\taddl $%d,%s\n", ch, pr, rnames[ESP]);
- break;
-
- case 'P': /* push hidden argument on stack */
- r = (NODE *)p->n_sue;
- printf("\tleal -%d(%%ebp),", stkpos);
- adrput(stdout, getlr(p, '1'));
- printf("\n\tpushl ");
- adrput(stdout, getlr(p, '1'));
- putchar('\n');
- break;
-
- case 'Q': /* emit struct assign */
- /* XXX - optimize for small structs */
- printf("\tpushl $%d\n", p->n_stsize);
- expand(p, INAREG, "\tpushl AR\n");
- expand(p, INAREG, "\tleal AL,%eax\n\tpushl %eax\n");
- printf("\tcall memcpy\n");
- printf("\taddl $12,%%esp\n");
- break;
-
- case 'S': /* emit eventual move after cast from longlong */
- pr = DECRA(p->n_reg, 0);
- lr = p->n_left->n_rval;
- switch (p->n_type) {
- case CHAR:
- case UCHAR:
- if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
- rnames[pr][1] == rnames[lr][1])
- break;
- if (rnames[lr][2] == 'x') {
- printf("\tmovb %%%cl,%s\n",
- rnames[lr][1], rnames[pr]);
- break;
- }
- /* Must go via stack */
- s = BITOOR(freetemp(1));
- printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s);
- printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]);
-// comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]);
- break;
-
- case SHORT:
- case USHORT:
- if (rnames[lr][1] == rnames[pr][2] &&
- rnames[lr][2] == rnames[pr][3])
- break;
- printf("\tmovw %%%c%c,%%%s\n",
- rnames[lr][1], rnames[lr][2], rnames[pr]+2);
- break;
- case INT:
- case UNSIGNED:
- if (rnames[lr][1] == rnames[pr][2] &&
- rnames[lr][2] == rnames[pr][3])
- break;
- printf("\tmovl %%e%c%c,%s\n",
- rnames[lr][1], rnames[lr][2], rnames[pr]);
- break;
-
- default:
- if (rnames[lr][1] == rnames[pr][2] &&
- rnames[lr][2] == rnames[pr][3])
- break;
- comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]);
- break;
- }
- break;
-
- default:
- comperr("zzzcode %c", c);
- }
-}
-
-/*ARGSUSED*/
-int
-rewfld(NODE *p)
-{
- return(1);
-}
-
-int canaddr(NODE *);
-int
-canaddr(NODE *p)
-{
- int o = p->n_op;
-
- if (o==NAME || o==REG || o==ICON || o==OREG ||
- (o==UMUL && shumul(p->n_left)))
- return(1);
- return(0);
-}
-
-/*
- * Does the bitfield shape match?
- */
-int
-flshape(NODE *p)
-{
- int o = p->n_op;
-
- if (o == OREG || o == REG || o == NAME)
- return SRDIR; /* Direct match */
- if (o == UMUL && shumul(p->n_left))
- return SROREG; /* Convert into oreg */
- return SRREG; /* put it into a register */
-}
-
-/* INTEMP shapes must not contain any temporary registers */
-/* XXX should this go away now? */
-int
-shtemp(NODE *p)
-{
- return 0;
-#if 0
- int r;
-
- if (p->n_op == STARG )
- p = p->n_left;
-
- switch (p->n_op) {
- case REG:
- return (!istreg(p->n_rval));
-
- case OREG:
- r = p->n_rval;
- if (R2TEST(r)) {
- if (istreg(R2UPK1(r)))
- return(0);
- r = R2UPK2(r);
- }
- return (!istreg(r));
-
- case UMUL:
- p = p->n_left;
- return (p->n_op != UMUL && shtemp(p));
- }
-
- if (optype(p->n_op) != LTYPE)
- return(0);
- return(1);
-#endif
-}
-
-void
-adrcon(CONSZ val)
-{
- printf("$" CONFMT, val);
-}
-
-void
-conput(FILE *fp, NODE *p)
-{
- int val = p->n_lval;
-
- switch (p->n_op) {
- case ICON:
- if (p->n_name[0] != '\0') {
- fprintf(fp, "%s", p->n_name);
- if (val)
- fprintf(fp, "+%d", val);
- } else
- fprintf(fp, "%d", val);
- return;
-
- default:
- comperr("illegal conput, p %p", p);
- }
-}
-
-/*ARGSUSED*/
-void
-insput(NODE *p)
-{
- comperr("insput");
-}
-
-/*
- * Write out the upper address, like the upper register of a 2-register
- * reference, or the next memory location.
- */
-void
-upput(NODE *p, int size)
-{
-
- size /= SZCHAR;
- switch (p->n_op) {
- case REG:
- fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
- break;
-
- case NAME:
- case OREG:
- p->n_lval += size;
- adrput(stdout, p);
- p->n_lval -= size;
- break;
- case ICON:
- fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
- break;
- default:
- comperr("upput bad op %d size %d", p->n_op, size);
- }
-}
-
-void
-adrput(FILE *io, NODE *p)
-{
- int r;
- /* output an address, with offsets, from p */
-
- if (p->n_op == FLD)
- p = p->n_left;
-
- switch (p->n_op) {
-
- case NAME:
- if (p->n_name[0] != '\0') {
- fputs(p->n_name, io);
- if (p->n_lval != 0)
- fprintf(io, "+" CONFMT, p->n_lval);
- } else
- fprintf(io, CONFMT, p->n_lval);
- return;
-
- case OREG:
- r = p->n_rval;
- if (p->n_lval)
- fprintf(io, "%d", (int)p->n_lval);
- if (R2TEST(r)) {
- fprintf(io, "(%s,%s,4)", rnames[R2UPK1(r)],
- rnames[R2UPK2(r)]);
- } else
- fprintf(io, "(%s)", rnames[p->n_rval]);
- return;
- case ICON:
- /* addressable value of the constant */
- fputc('$', io);
- conput(io, p);
- return;
-
- case MOVE:
- case REG:
- switch (p->n_type) {
- case LONGLONG:
- case ULONGLONG:
- fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
- rnames[p->n_rval][1], rnames[p->n_rval][2]);
- break;
- case SHORT:
- case USHORT:
- fprintf(io, "%%%s", &rnames[p->n_rval][2]);
- break;
- default:
- fprintf(io, "%s", rnames[p->n_rval]);
- }
- return;
-
- default:
- comperr("illegal address, op %d, node %p", p->n_op, p);
- return;
-
- }
-}
-
-static char *
-ccbranches[] = {
- "je", /* jumpe */
- "jne", /* jumpn */
- "jle", /* jumple */
- "jl", /* jumpl */
- "jge", /* jumpge */
- "jg", /* jumpg */
- "jbe", /* jumple (jlequ) */
- "jb", /* jumpl (jlssu) */
- "jae", /* jumpge (jgequ) */
- "ja", /* jumpg (jgtru) */
-};
-
-
-/* printf conditional and unconditional branches */
-void
-cbgen(int o, int lab)
-{
- if (o < EQ || o > UGT)
- comperr("bad conditional branch: %s", opst[o]);
- printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
-}
-
-static void
-fixcalls(NODE *p)
-{
- /* Prepare for struct return by allocating bounce space on stack */
- switch (p->n_op) {
- case STCALL:
- case USTCALL:
- if (p->n_stsize+p2autooff > stkpos)
- stkpos = p->n_stsize+p2autooff;
- break;
- }
-}
-
-/*
- * Must store floats in memory if there are two function calls involved.
- */
-static int
-storefloat(struct interpass *ip, NODE *p)
-{
- int l, r;
-
- switch (optype(p->n_op)) {
- case BITYPE:
- l = storefloat(ip, p->n_left);
- r = storefloat(ip, p->n_right);
- if (p->n_op == CM)
- return 0; /* arguments, don't care */
- if (callop(p->n_op))
- return 1; /* found one */
-#define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
- (p)->n_type == LDOUBLE)
- if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
- /* must store one. store left */
- struct interpass *nip;
- TWORD t = p->n_left->n_type;
- NODE *ll;
- int off;
-
- off = BITOOR(freetemp(szty(t)));
- ll = mklnode(OREG, off, FPREG, t);
- nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
- p->n_left = mklnode(OREG, off, FPREG, t);
- DLIST_INSERT_BEFORE(ip, nip, qelem);
- }
- return l|r;
-
- case UTYPE:
- l = storefloat(ip, p->n_left);
- if (callop(p->n_op))
- l = 1;
- return l;
- default:
- return 0;
- }
-}
-
-void
-myreader(struct interpass *ipole)
-{
- struct interpass *ip;
-
- stkpos = p2autooff;
- DLIST_FOREACH(ip, ipole, qelem) {
- if (ip->type != IP_NODE)
- continue;
- walkf(ip->ip_node, fixcalls);
- storefloat(ip, ip->ip_node);
- }
- if (stkpos > p2autooff)
- p2autooff = stkpos;
- if (stkpos > p2maxautooff)
- p2maxautooff = stkpos;
- if (x2debug)
- printip(ipole);
-}
-
-/*
- * Remove some PCONVs after OREGs are created.
- */
-static void
-pconv2(NODE *p)
-{
- NODE *q;
-
- if (p->n_op == PLUS) {
- if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
- if (p->n_right->n_op != ICON)
- return;
- if (p->n_left->n_op != PCONV)
- return;
- if (p->n_left->n_left->n_op != OREG)
- return;
- q = p->n_left->n_left;
- nfree(p->n_left);
- p->n_left = q;
- /*
- * This will be converted to another OREG later.
- */
- }
- }
-}
-
-void
-mycanon(NODE *p)
-{
- walkf(p, pconv2);
-}
-
-void
-myoptim(struct interpass *ip)
-{
-}
-
-static char rl[] =
- { EAX, EAX, EAX, EAX, EAX, EDX, EDX, EDX, EDX, ECX, ECX, ECX, EBX, EBX, ESI };
-static char rh[] =
- { EDX, ECX, EBX, ESI, EDI, ECX, EBX, ESI, EDI, EBX, ESI, EDI, ESI, EDI, EDI };
-
-void
-rmove(int s, int d, TWORD t)
-{
- int sl, sh, dl, dh;
-
- switch (t) {
- case LONGLONG:
- case ULONGLONG:
-#if 1
- sl = rl[s-EAXEDX];
- sh = rh[s-EAXEDX];
- dl = rl[d-EAXEDX];
- dh = rh[d-EAXEDX];
-
- /* sanity checks, remove when satisfied */
- if (memcmp(rnames[s], rnames[sl]+1, 3) != 0 ||
- memcmp(rnames[s]+3, rnames[sh]+1, 3) != 0)
- comperr("rmove source error");
- if (memcmp(rnames[d], rnames[dl]+1, 3) != 0 ||
- memcmp(rnames[d]+3, rnames[dh]+1, 3) != 0)
- comperr("rmove dest error");
-#define SW(x,y) { int i = x; x = y; y = i; }
- if (sl == dh || sh == dl) {
- /* Swap if moving to itself */
- SW(sl, sh);
- SW(dl, dh);
- }
- if (sl != dl)
- printf(" movl %s,%s\n", rnames[sl], rnames[dl]);
- if (sh != dh)
- printf(" movl %s,%s\n", rnames[sh], rnames[dh]);
-#else
- if (memcmp(rnames[s], rnames[d], 3) != 0)
- printf(" movl %%%c%c%c,%%%c%c%c\n",
- rnames[s][0],rnames[s][1],rnames[s][2],
- rnames[d][0],rnames[d][1],rnames[d][2]);
- if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0)
- printf(" movl %%%c%c%c,%%%c%c%c\n",
- rnames[s][3],rnames[s][4],rnames[s][5],
- rnames[d][3],rnames[d][4],rnames[d][5]);
-#endif
- break;
- case CHAR:
- case UCHAR:
- printf(" movb %s,%s\n", rnames[s], rnames[d]);
- break;
- case FLOAT:
- case DOUBLE:
- case LDOUBLE:
-#ifdef notdef
- /* a=b()*c(); will generate this */
- comperr("bad float rmove: %d %d", s, d);
-#endif
- break;
- default:
- printf(" movl %s,%s\n", rnames[s], rnames[d]);
- }
-}
-
-/*
- * For class c, find worst-case displacement of the number of
- * registers in the array r[] indexed by class.
- */
-int
-COLORMAP(int c, int *r)
-{
- int num;
-
- switch (c) {
- case CLASSA:
- num = r[CLASSB] > 4 ? 4 : r[CLASSB];
- num += 2*r[CLASSC];
- num += r[CLASSA];
- return num < 6;
- case CLASSB:
- num = r[CLASSA];
- num += 2*r[CLASSC];
- num += r[CLASSB];
- return num < 4;
- case CLASSC:
- num = r[CLASSA];
- num += r[CLASSB] > 4 ? 4 : r[CLASSB];
- num += 2*r[CLASSC];
- return num < 5;
- case CLASSD:
- return r[CLASSD] < DREGCNT;
- }
- return 0; /* XXX gcc */
-}
-
-char *rnames[] = {
- "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
- "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
- "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
- "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
- "ebxesi", "ebxedi", "esiedi",
- "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
-};
-
-/*
- * Return a class suitable for a specific type.
- */
-int
-gclass(TWORD t)
-{
- if (t == CHAR || t == UCHAR)
- return CLASSB;
- if (t == LONGLONG || t == ULONGLONG)
- return CLASSC;
- if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
- return CLASSD;
- return CLASSA;
-}
-
-/*
- * Calculate argument sizes.
- */
-void
-lastcall(NODE *p)
-{
- NODE *op = p;
- int size = 0;
-
- p->n_qual = 0;
- if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
- return;
- for (p = p->n_right; p->n_op == CM; p = p->n_left)
- size += argsiz(p->n_right);
- size += argsiz(p);
- op->n_qual = size; /* XXX */
-}
-
-/*
- * Special shapes.
- */
-int
-special(NODE *p, int shape)
-{
- int o = p->n_op;
-
- switch (shape) {
- case SFUNCALL:
- if (o == STCALL || o == USTCALL)
- return SRREG;
- break;
- case SPCON:
- if (o != ICON || p->n_name[0] ||
- p->n_lval < 0 || p->n_lval > 0x7fffffff)
- break;
- return SRDIR;
- }
- return SRNOPE;
-}
--- usr.bin/pcc/arch/x86/code.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* $Id: code.c,v 1.15 2007/07/06 17:02:27 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-# include "pass1.h"
-
-/*
- * cause the alignment to become a multiple of n
- * never called for text segment.
- */
-void
-defalign(int n)
-{
- n /= SZCHAR;
- if (n == 1)
- return;
- printf(" .align %d\n", n);
-}
-
-/*
- * define the current location as the name p->sname
- * never called for text segment.
- */
-void
-defnam(struct symtab *p)
-{
- char *c = p->sname;
-
-#ifdef GCC_COMPAT
- c = gcc_findname(p);
-#endif
- if (p->sclass == EXTDEF)
- printf(" .globl %s\n", c);
- printf("%s:\n", c);
-}
-
-
-/*
- * code for the end of a function
- * deals with struct return here
- */
-void
-efcode()
-{
- NODE *p, *q;
- int sz;
-
- if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
- return;
- /* address of return struct is in eax */
- /* create a call to memcpy() */
- /* will get the result in eax */
- p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
- p->n_rval = EAX;
- q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
- q->n_rval = EBP;
- q->n_lval = 8; /* return buffer offset */
- p = block(CM, q, p, INT, 0, MKSUE(INT));
- sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR;
- p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT));
- p->n_right->n_name = "";
- p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR));
- p->n_left->n_name = "memcpy";
- p = clocal(p);
- send_passt(IP_NODE, p);
-}
-
-/*
- * code for the beginning of a function; a is an array of
- * indices in symtab for the arguments; n is the number
- */
-void
-bfcode(struct symtab **a, int n)
-{
- int i;
-
- if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
- return;
- /* Function returns struct, adjust arg offset */
- for (i = 0; i < n; i++)
- a[i]->soffset += SZPOINT(INT);
-}
-
-
-/*
- * by now, the automatics and register variables are allocated
- */
-void
-bccode()
-{
- SETOFF(autooff, SZINT);
-}
-
-/* called just before final exit */
-/* flag is 1 if errors, 0 if none */
-void
-ejobcode(int flag )
-{
-}
-
-void
-bjobcode()
-{
-}
-
-/*
- * Print character t at position i in one string, until t == -1.
- * Locctr & label is already defined.
- */
-void
-bycode(int t, int i)
-{
- static int lastoctal = 0;
-
- /* put byte i+1 in a string */
-
- if (t < 0) {
- if (i != 0)
- puts("\"");
- } else {
- if (i == 0)
- printf("\t.ascii \"");
- if (t == '\\' || t == '"') {
- lastoctal = 0;
- putchar('\\');
- putchar(t);
- } else if (t < 040 || t >= 0177) {
- lastoctal++;
- printf("\\%o",t);
- } else if (lastoctal && '0' <= t && t <= '9') {
- lastoctal = 0;
- printf("\"\n\t.ascii \"%c", t);
- } else {
- lastoctal = 0;
- putchar(t);
- }
- }
-}
-
-/*
- * n integer words of zeros
- */
-void
-zecode(int n)
-{
- printf(" .zero %d\n", n * (SZINT/SZCHAR));
-// inoff += n * SZINT;
-}
-
-/*
- * return the alignment of field of type t
- */
-int
-fldal(unsigned int t)
-{
- uerror("illegal field type");
- return(ALINT);
-}
-
-/* fix up type of field p */
-void
-fldty(struct symtab *p)
-{
-}
-
-/* p points to an array of structures, each consisting
- * of a constant value and a label.
- * The first is >=0 if there is a default label;
- * its value is the label number
- * The entries p[1] to p[n] are the nontrivial cases
- * XXX - fix genswitch.
- */
-void
-genswitch(int num, struct swents **p, int n)
-{
- NODE *r;
- int i;
-
- /* simple switch code */
- for (i = 1; i <= n; ++i) {
- /* already in 1 */
- r = tempnode(num, INT, 0, MKSUE(INT));
- r = buildtree(NE, r, bcon(p[i]->sval));
- cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
- }
- if (p[0]->slab > 0)
- branch(p[0]->slab);
-}
--- usr.bin/pcc/arch/x86/local.c
+++ /dev/null
@@ -1,743 +0,0 @@
-/* $Id: local.c,v 1.56 2007/09/24 16:23:36 ragge Exp $ */
-/*
- * Copyright (c) 2003 Anders Magnusson (ragge at 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.
- */
-
-
-#include "pass1.h"
-
-/* this file contains code which is dependent on the target machine */
-
-/* clocal() is called to do local transformations on
- * an expression tree preparitory to its being
- * written out in intermediate code.
- *
- * the major essential job is rewriting the
- * automatic variables and arguments in terms of
- * REG and OREG nodes
- * conversion ops which are not necessary are also clobbered here
- * in addition, any special features (such as rewriting
- * exclusive or) are easily handled here as well
- */
-NODE *
-clocal(NODE *p)
-{
-
- register struct symtab *q;
- register NODE *r, *l;
- register int o;
- register int m;
- TWORD t;
-
-#ifdef PCC_DEBUG
- if (xdebug) {
- printf("clocal: %p\n", p);
- fwalk(p, eprint, 0);
- }
-#endif
- switch( o = p->n_op ){
-
- case NAME:
- if ((q = p->n_sp) == NULL)
- return p; /* Nothing to care about */
-
- switch (q->sclass) {
-
- case PARAM:
- case AUTO:
- /* fake up a structure reference */
- r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
- r->n_lval = 0;
- r->n_rval = FPREG;
- p = stref(block(STREF, r, p, 0, 0, 0));
- break;
-
- case STATIC:
- if (q->slevel == 0)
- break;
- p->n_lval = 0;
- p->n_sp = q;
- break;
-
- case REGISTER:
- p->n_op = REG;
- p->n_lval = 0;
- p->n_rval = q->soffset;
- break;
-
- }
- break;
-
- case STCALL:
- case CALL:
- /* Fix function call arguments. On x86, just add funarg */
- for (r = p->n_right; r->n_op == CM; r = r->n_left) {
- if (r->n_right->n_op != STARG &&
- r->n_right->n_op != FUNARG)
- r->n_right = block(FUNARG, r->n_right, NIL,
- r->n_right->n_type, r->n_right->n_df,
- r->n_right->n_sue);
- }
- if (r->n_op != STARG && r->n_op != FUNARG) {
- l = talloc();
- *l = *r;
- r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type;
- }
- break;
-
- case CBRANCH:
- l = p->n_left;
-
- /*
- * Remove unneccessary conversion ops.
- */
- if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
- if (coptype(l->n_op) != BITYPE)
- break;
- if (l->n_right->n_op == ICON) {
- r = l->n_left->n_left;
- if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
- break;
- /* Type must be correct */
- t = r->n_type;
- nfree(l->n_left);
- l->n_left = r;
- l->n_type = t;
- l->n_right->n_type = t;
- }
- }
- break;
-
- case PCONV:
- /* Remove redundant PCONV's. Be careful */
- l = p->n_left;
- if (l->n_op == ICON) {
- l->n_lval = (unsigned)l->n_lval;
- goto delp;
- }
- if (l->n_type < INT || l->n_type == LONGLONG ||
- l->n_type == ULONGLONG) {
- /* float etc? */
- p->n_left = block(SCONV, l, NIL,
- UNSIGNED, 0, MKSUE(UNSIGNED));
- break;
- }
- /* if left is SCONV, cannot remove */
- if (l->n_op == SCONV)
- break;
-
- /* avoid ADDROF TEMP */
- if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
- break;
-
- /* if conversion to another pointer type, just remove */
- if (p->n_type > BTMASK && l->n_type > BTMASK)
- goto delp;
- break;
-
- delp: l->n_type = p->n_type;
- l->n_qual = p->n_qual;
- l->n_df = p->n_df;
- l->n_sue = p->n_sue;
- nfree(p);
- p = l;
- break;
-
- case SCONV:
- l = p->n_left;
-
- if (p->n_type == l->n_type) {
- nfree(p);
- return l;
- }
-
- if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
- btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
- if (p->n_type != FLOAT && p->n_type != DOUBLE &&
- l->n_type != FLOAT && l->n_type != DOUBLE &&
- l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
- if (l->n_op == NAME || l->n_op == UMUL ||
- l->n_op == TEMP) {
- l->n_type = p->n_type;
- nfree(p);
- return l;
- }
- }
- }
-
- if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
- coptype(l->n_op) == BITYPE) {
- l->n_type = p->n_type;
- nfree(p);
- return l;
- }
-
- o = l->n_op;
- m = p->n_type;
-
- if (o == ICON) {
- CONSZ val = l->n_lval;
-
- if (!ISPTR(m)) /* Pointers don't need to be conv'd */
- switch (m) {
- case BOOL:
- l->n_lval = l->n_lval != 0;
- break;
- case CHAR:
- l->n_lval = (char)val;
- break;
- case UCHAR:
- l->n_lval = val & 0377;
- break;
- case SHORT:
- l->n_lval = (short)val;
- break;
- case USHORT:
- l->n_lval = val & 0177777;
- break;
- case ULONG:
- case UNSIGNED:
- l->n_lval = val & 0xffffffff;
- break;
- case ENUMTY:
- case MOETY:
- case LONG:
- case INT:
- l->n_lval = (int)val;
- break;
- case LONGLONG:
- l->n_lval = (long long)val;
- break;
- case ULONGLONG:
- l->n_lval = val;
- break;
- case VOID:
- break;
- case LDOUBLE:
- case DOUBLE:
- case FLOAT:
- l->n_op = FCON;
- l->n_dcon = val;
- break;
- default:
- cerror("unknown type %d", m);
- }
- l->n_type = m;
- l->n_sue = MKSUE(m);
- nfree(p);
- return l;
- }
- if (DEUNSIGN(p->n_type) == SHORT &&
- DEUNSIGN(l->n_type) == SHORT) {
- nfree(p);
- p = l;
- }
- if ((p->n_type == CHAR || p->n_type == UCHAR ||
- p->n_type == SHORT || p->n_type == USHORT) &&
- (l->n_type == FLOAT || l->n_type == DOUBLE ||
- l->n_type == LDOUBLE)) {
- p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
- p->n_left->n_type = INT;
- return p;
- }
- break;
-
- case MOD:
- case DIV:
- if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
- break;
- if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
- break;
- /* make it an int division by inserting conversions */
- p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
- p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
- p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type));
- p->n_left->n_type = INT;
- break;
-
- case PMCONV:
- case PVCONV:
- if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
- nfree(p);
- return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
-
- case FORCE:
- /* put return value in return reg */
- p->n_op = ASSIGN;
- p->n_right = p->n_left;
- p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
- p->n_left->n_rval = p->n_left->n_type == BOOL ?
- RETREG(CHAR) : RETREG(p->n_type);
- break;
-
- case LS:
- case RS:
- /* shift count must be in a char
- * unless longlong, where it must be int */
- if (p->n_right->n_op == ICON)
- break; /* do not do anything */
- if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
- if (p->n_right->n_type != INT)
- p->n_right = block(SCONV, p->n_right, NIL,
- INT, 0, MKSUE(INT));
- break;
- }
- if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
- break;
- p->n_right = block(SCONV, p->n_right, NIL,
- CHAR, 0, MKSUE(CHAR));
- break;
- }
-#ifdef PCC_DEBUG
- if (xdebug) {
- printf("clocal end: %p\n", p);
- fwalk(p, eprint, 0);
- }
-#endif
- return(p);
-}
-
-void
-myp2tree(NODE *p)
-{
-}
-
-/*ARGSUSED*/
-int
-andable(NODE *p)
-{
- return(1); /* all names can have & taken on them */
-}
-
-/*
- * at the end of the arguments of a ftn, set the automatic offset
- */
-void
-cendarg()
-{
- autooff = AUTOINIT;
-}
-
-/*
- * Return 1 if a variable of type type is OK to put in register.
- */
-int
-cisreg(TWORD t)
-{
- if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
- return 0; /* not yet */
- return 1;
-}
-
-/*
- * return a node, for structure references, which is suitable for
- * being added to a pointer of type t, in order to be off bits offset
- * into a structure
- * t, d, and s are the type, dimension offset, and sizeoffset
- * For pdp10, return the type-specific index number which calculation
- * is based on its size. For example, short a[3] would return 3.
- * Be careful about only handling first-level pointers, the following
- * indirections must be fullword.
- */
-NODE *
-offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
-{
- register NODE *p;
-
- if (xdebug)
- printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
- off, t, d, sue->suesize);
-
- p = bcon(0);
- p->n_lval = off/SZCHAR; /* Default */
- return(p);
-}
-
-/*
- * Allocate off bits on the stack. p is a tree that when evaluated
- * is the multiply count for off, t is a storeable node where to write
- * the allocated address.
- */
-void
-spalloc(NODE *t, NODE *p, OFFSZ off)
-{
- NODE *sp;
-
- p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
-
- /* sub the size from sp */
- sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
- sp->n_lval = 0;
- sp->n_rval = STKREG;
- ecomp(buildtree(MINUSEQ, sp, p));
-
- /* save the address of sp */
- sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
- sp->n_lval = 0;
- sp->n_rval = STKREG;
- t->n_type = sp->n_type;
- ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
-
-}
-
-#if 0
-/*
- * Print out an integer constant of size size.
- * can only be sizes <= SZINT.
- */
-void
-indata(CONSZ val, int size)
-{
- switch (size) {
- case SZCHAR:
- printf("\t.byte %d\n", (int)val & 0xff);
- break;
- case SZSHORT:
- printf("\t.word %d\n", (int)val & 0xffff);
- break;
- case SZINT:
- printf("\t.long %d\n", (int)val & 0xffffffff);
- break;
- default:
- cerror("indata");
- }
-}
-#endif
-
-/*
- * Print out a string of characters.
- * Assume that the assembler understands C-style escape
- * sequences. Location is already set.
- */
-void
-instring(char *str)
-{
- char *s;
-
- /* be kind to assemblers and avoid long strings */
- printf("\t.ascii \"");
- for (s = str; *s != 0; ) {
- if (*s++ == '\\') {
- (void)esccon(&s);
- }
- if (s - str > 64) {
- fwrite(str, 1, s - str, stdout);
- printf("\"\n\t.ascii \"");
- str = s;
- }
- }
- fwrite(str, 1, s - str, stdout);
- printf("\\0\"\n");
-}
-
-static int inbits, inval;
-
-/*
- * set fsz bits in sequence to zero.
- */
-void
-zbits(OFFSZ off, int fsz)
-{
- int m;
-
- if (idebug)
- printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
- if ((m = (inbits % SZCHAR))) {
- m = SZCHAR - m;
- if (fsz < m) {
- inbits += fsz;
- return;
- } else {
- fsz -= m;
- printf("\t.byte %d\n", inval);
- inval = inbits = 0;
- }
- }
- if (fsz >= SZCHAR) {
- printf("\t.zero %d\n", fsz/SZCHAR);
- fsz -= (fsz/SZCHAR) * SZCHAR;
- }
- if (fsz) {
- inval = 0;
- inbits = fsz;
- }
-}
-
-/*
- * Initialize a bitfield.
- */
-void
-infld(CONSZ off, int fsz, CONSZ val)
-{
- if (idebug)
- printf("infld off %lld, fsz %d, val %lld inbits %d\n",
- off, fsz, val, inbits);
- val &= ((CONSZ)1 << fsz)-1;
- while (fsz + inbits >= SZCHAR) {
- inval |= (val << inbits);
- printf("\t.byte %d\n", inval & 255);
- fsz -= (SZCHAR - inbits);
- val >>= (SZCHAR - inbits);
- inval = inbits = 0;
- }
- if (fsz) {
- inval |= (val << inbits);
- inbits += fsz;
- }
-}
-
-/*
- * print out a constant node, may be associated with a label.
- * Do not free the node after use.
- * off is bit offset from the beginning of the aggregate
- * fsz is the number of bits this is referring to
- */
-void
-ninval(CONSZ off, int fsz, NODE *p)
-{
- union { float f; double d; long double l; int i[3]; } u;
- struct symtab *q;
- TWORD t;
- int i;
-
- t = p->n_type;
- if (t > BTMASK)
- t = INT; /* pointer */
-
- if (p->n_op != ICON && p->n_op != FCON)
- cerror("ninval: init node not constant");
-
- if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
- uerror("element not constant");
-
- switch (t) {
- case LONGLONG:
- case ULONGLONG:
- i = (p->n_lval >> 32);
- p->n_lval &= 0xffffffff;
- p->n_type = INT;
- ninval(off, 32, p);
- p->n_lval = i;
- ninval(off+32, 32, p);
- break;
- case INT:
- case UNSIGNED:
- printf("\t.long 0x%x", (int)p->n_lval);
- if ((q = p->n_sp) != NULL) {
- if ((q->sclass == STATIC && q->slevel > 0) ||
- q->sclass == ILABEL) {
- printf("+" LABFMT, q->soffset);
- } else
- printf("+%s", exname(q->sname));
- }
- printf("\n");
- break;
- case SHORT:
- case USHORT:
- printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
- break;
- case BOOL:
- if (p->n_lval > 1)
- p->n_lval = p->n_lval != 0;
- /* FALLTHROUGH */
- case CHAR:
- case UCHAR:
- printf("\t.byte %d\n", (int)p->n_lval & 0xff);
- break;
- case LDOUBLE:
- u.i[2] = 0;
- u.l = (long double)p->n_dcon;
- printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
- break;
- case DOUBLE:
- u.d = (double)p->n_dcon;
- printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
- break;
- case FLOAT:
- u.f = (float)p->n_dcon;
- printf("\t.long\t0x%x\n", u.i[0]);
- break;
- default:
- cerror("ninval");
- }
-}
-
-#if 0
-/*
- * print out an integer.
- */
-void
-inval(CONSZ word)
-{
- word &= 0xffffffff;
- printf(" .long 0x%llx\n", word);
-}
-
-/* output code to initialize a floating point value */
-/* the proper alignment has been obtained */
-void
-finval(NODE *p)
-{
- union { float f; double d; long double l; int i[3]; } u;
-
- switch (p->n_type) {
- case LDOUBLE:
- u.i[2] = 0;
- u.l = (long double)p->n_dcon;
- printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
- break;
- case DOUBLE:
- u.d = (double)p->n_dcon;
- printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
- break;
- case FLOAT:
- u.f = (float)p->n_dcon;
- printf("\t.long\t0x%x\n", u.i[0]);
- break;
- }
-}
-#endif
-
-/* make a name look like an external name in the local machine */
-char *
-exname(char *p)
-{
- if (p == NULL)
- return "";
- return p;
-}
-
-/*
- * map types which are not defined on the local machine
- */
-TWORD
-ctype(TWORD type)
-{
- switch (BTYPE(type)) {
- case LONG:
- MODTYPE(type,INT);
- break;
-
- case ULONG:
- MODTYPE(type,UNSIGNED);
-
- }
- return (type);
-}
-
-void
-calldec(NODE *p, NODE *q)
-{
-}
-
-void
-extdec(struct symtab *q)
-{
-}
-
-/* make a common declaration for id, if reasonable */
-void
-commdec(struct symtab *q)
-{
- int off;
-
- off = tsize(q->stype, q->sdf, q->ssue);
- off = (off+(SZCHAR-1))/SZCHAR;
-#ifdef GCC_COMPAT
- printf(" .comm %s,0%o\n", gcc_findname(q), off);
-#else
- printf(" .comm %s,0%o\n", exname(q->sname), off);
-#endif
-}
-
-/* make a local common declaration for id, if reasonable */
-void
-lcommdec(struct symtab *q)
-{
- int off;
-
- off = tsize(q->stype, q->sdf, q->ssue);
- off = (off+(SZCHAR-1))/SZCHAR;
- if (q->slevel == 0)
-#ifdef GCC_COMPAT
- printf(" .lcomm %s,0%o\n", gcc_findname(q), off);
-#else
- printf(" .lcomm %s,0%o\n", exname(q->sname), off);
-#endif
- else
- printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
-}
-
-/*
- * print a (non-prog) label.
- */
-void
-deflab1(int label)
-{
- printf(LABFMT ":\n", label);
-}
-
-static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
-
-void
-setloc1(int locc)
-{
- if (locc == lastloc)
- return;
- lastloc = locc;
- printf(" .%s\n", loctbl[locc]);
-}
-
-#if 0
-int
-ftoint(NODE *p, CONSZ **c)
-{
- static CONSZ cc[3];
- union { float f; double d; long double l; int i[3]; } u;
- int n;
-
- switch (p->n_type) {
- case LDOUBLE:
- u.i[2] = 0;
- u.l = (long double)p->n_dcon;
- n = SZLDOUBLE;
- break;
- case DOUBLE:
- u.d = (double)p->n_dcon;
- n = SZDOUBLE;
- break;
- case FLOAT:
- u.f = (float)p->n_dcon;
- n = SZFLOAT;
- break;
- }
- cc[0] = u.i[0];
- cc[1] = u.i[1];
- cc[2] = u.i[2];
- *c = cc;
- return n;
-}
-#endif
Index: Makefile
===================================================================
RCS file: /home/cvs/src/usr.bin/pcc/cpp/Makefile,v
retrieving revision 1.3
retrieving revision 1.4
diff -L usr.bin/pcc/cpp/Makefile -L usr.bin/pcc/cpp/Makefile -u -r1.3 -r1.4
--- usr.bin/pcc/cpp/Makefile
+++ usr.bin/pcc/cpp/Makefile
@@ -5,6 +5,7 @@
PROG= cpp
TARGOS= midnightbsd
BINDIR= ${libexecdir}
+NO_MAN=
CFLAGS+= -DCPP_DEBUG -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror
CFLAGS+= -DLIBEXECDIR=\"${libexecdir}\"
--- /dev/null
+++ usr.bin/pcc/i386/order.c
@@ -0,0 +1,287 @@
+/* $Id: order.c,v 1.49 2007/08/01 04:53:58 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+# include "pass2.h"
+
+#include <string.h>
+
+int canaddr(NODE *);
+
+/* is it legal to make an OREG or NAME entry which has an
+ * offset of off, (from a register of r), if the
+ * resulting thing had type t */
+int
+notoff(TWORD t, int r, CONSZ off, char *cp)
+{
+ return(0); /* YES */
+}
+
+/*
+ * Turn a UMUL-referenced node into OREG.
+ * Be careful about register classes, this is a place where classes change.
+ */
+void
+offstar(NODE *p, int shape)
+{
+ NODE *r;
+
+ if (x2debug)
+ printf("offstar(%p)\n", p);
+
+ if (isreg(p))
+ return; /* Is already OREG */
+
+ r = p->n_right;
+ if( p->n_op == PLUS || p->n_op == MINUS ){
+ if( r->n_op == ICON ){
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ /* Converted in ormake() */
+ return;
+ }
+ if (r->n_op == LS && r->n_right->n_op == ICON &&
+ r->n_right->n_lval == 2 && p->n_op == PLUS) {
+ if (isreg(p->n_left) == 0)
+ (void)geninsn(p->n_left, INAREG);
+ if (isreg(r->n_left) == 0)
+ (void)geninsn(r->n_left, INAREG);
+ return;
+ }
+ }
+ (void)geninsn(p, INAREG);
+}
+
+/*
+ * Do the actual conversion of offstar-found OREGs into real OREGs.
+ */
+void
+myormake(NODE *q)
+{
+ NODE *p, *r;
+
+ if (x2debug)
+ printf("myormake(%p)\n", q);
+
+ p = q->n_left;
+ if (p->n_op == PLUS && (r = p->n_right)->n_op == LS &&
+ r->n_right->n_op == ICON && r->n_right->n_lval == 2 &&
+ p->n_left->n_op == REG && r->n_left->n_op == REG) {
+ q->n_op = OREG;
+ q->n_lval = 0;
+ q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval, 0);
+ tfree(p);
+ }
+}
+
+/*
+ * Shape matches for UMUL. Cooperates with offstar().
+ */
+int
+shumul(NODE *p)
+{
+
+ if (x2debug)
+ printf("shumul(%p)\n", p);
+
+ /* Turns currently anything into OREG on x86 */
+ return SOREG;
+}
+
+/*
+ * Rewrite increment/decrement operation.
+ */
+int
+setincr(NODE *p)
+{
+ if (x2debug)
+ printf("setincr(%p)\n", p);
+
+ return(0);
+}
+
+/*
+ * Rewrite operations on binary operators (like +, -, etc...).
+ * Called as a result of table lookup.
+ */
+int
+setbin(NODE *p)
+{
+
+ if (x2debug)
+ printf("setbin(%p)\n", p);
+ return 0;
+
+}
+
+/* setup for assignment operator */
+int
+setasg(NODE *p, int cookie)
+{
+ if (x2debug)
+ printf("setasg(%p)\n", p);
+ return(0);
+}
+
+/* setup for unary operator */
+int
+setuni(NODE *p, int cookie)
+{
+ return 0;
+}
+
+/*
+ * Special handling of some instruction register allocation.
+ */
+struct rspecial *
+nspecial(struct optab *q)
+{
+ switch (q->op) {
+ case OPLOG:
+ {
+ static struct rspecial s[] = { { NEVER, EAX }, { 0 } };
+ return s;
+ }
+
+ case STASG:
+ case STARG:
+ {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { 0 } };
+ return s;
+ }
+
+ case SCONV:
+ if ((q->ltype & (TINT|TUNSIGNED|TSHORT|TUSHORT)) &&
+ q->rtype == (TCHAR|TUCHAR)) {
+ static struct rspecial s[] = {
+ { NOLEFT, ESI }, { NOLEFT, EDI }, { 0 } };
+ return s;
+ } else if ((q->ltype & (TINT|TUNSIGNED)) &&
+ q->rtype == TLONGLONG) {
+ static struct rspecial s[] = {
+ { NLEFT, EAX }, { NRES, EAXEDX },
+ { NEVER, EAX }, { NEVER, EDX }, { 0 } };
+ return s;
+ } else if (q->ltype == TSHORT &&
+ q->rtype == (TLONGLONG|TULONGLONG)) {
+ static struct rspecial s[] = {
+ { NRES, EAXEDX },
+ { NEVER, EAX }, { NEVER, EDX }, { 0 } };
+ return s;
+ } else if (q->ltype == TCHAR &&
+ q->rtype == (TLONGLONG|TULONGLONG)) {
+ static struct rspecial s[] = {
+ { NRES, EAXEDX },
+ { NEVER, EAX }, { NEVER, EDX }, { 0 } };
+ return s;
+ }
+ break;
+ case DIV:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AL },
+ { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NLEFT, EAX }, { NRES, EAX },
+ { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+ case MOD:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AH },
+ { NORIGHT, AH }, { NORIGHT, AL }, { 0 } };
+ return s;
+ } else if (q->lshape == SAREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NLEFT, EAX }, { NRES, EDX },
+ { NORIGHT, EDX }, { NORIGHT, EAX }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+ case MUL:
+ if (q->lshape == SBREG) {
+ static struct rspecial s[] = {
+ { NEVER, AL }, { NEVER, AH },
+ { NLEFT, AL }, { NRES, AL }, { 0 } };
+ return s;
+ } else if (q->lshape & SCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+ case LS:
+ case RS:
+ if (q->visit & (INAREG|INBREG)) {
+ static struct rspecial s[] = {
+ { NRIGHT, CL }, { NOLEFT, ECX }, { 0 } };
+ return s;
+ } else if (q->visit & INCREG) {
+ static struct rspecial s[] = {
+ { NEVER, EAX }, { NEVER, EDX },
+ { NEVER, ECX }, { NRES, EAXEDX }, { 0 } };
+ return s;
+ }
+ break;
+
+ default:
+ break;
+ }
+ comperr("nspecial entry %d", q - table);
+ return 0; /* XXX gcc */
+}
+
+/*
+ * Set evaluation order of a binary node if it differs from default.
+ */
+int
+setorder(NODE *p)
+{
+ return 0; /* nothing differs on x86 */
+}
--- /dev/null
+++ usr.bin/pcc/i386/macdefs.h
@@ -0,0 +1,301 @@
+/* $Id: macdefs.h,v 1.46 2007/08/19 19:25:22 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+/*
+ * Machine-dependent defines for both passes.
+ */
+
+/*
+ * Convert (multi-)character constant to integer.
+ */
+#define makecc(val,i) lastcon = (lastcon<<8)|((val<<24)>>24);
+
+#define ARGINIT 64 /* # bits above fp where arguments start */
+#define AUTOINIT 0 /* # bits below fp where automatics start */
+
+/*
+ * Storage space requirements
+ */
+#define SZCHAR 8
+#define SZBOOL 8
+#define SZINT 32
+#define SZFLOAT 32
+#define SZDOUBLE 64
+#define SZLDOUBLE 96
+#define SZLONG 32
+#define SZSHORT 16
+#define SZLONGLONG 64
+#define SZPOINT(t) 32
+
+/*
+ * Alignment constraints
+ */
+#define ALCHAR 8
+#define ALBOOL 8
+#define ALINT 32
+#define ALFLOAT 32
+#define ALDOUBLE 32
+#define ALLDOUBLE 32
+#define ALLONG 32
+#define ALLONGLONG 32
+#define ALSHORT 16
+#define ALPOINT 32
+#define ALSTRUCT 32
+#define ALSTACK 32
+
+/*
+ * Min/max values.
+ */
+#define MIN_CHAR -128
+#define MAX_CHAR 127
+#define MAX_UCHAR 255
+#define MIN_SHORT -32768
+#define MAX_SHORT 32767
+#define MAX_USHORT 65535
+#define MIN_INT -1
+#define MAX_INT 0x7fffffff
+#define MAX_UNSIGNED 0xffffffff
+#define MIN_LONG MIN_INT
+#define MAX_LONG MAX_INT
+#define MAX_ULONG MAX_UNSIGNED
+#define MIN_LONGLONG 0x8000000000000000LL
+#define MAX_LONGLONG 0x7fffffffffffffffLL
+#define MAX_ULONGLONG 0xffffffffffffffffULL
+
+/* Default char is signed */
+#undef CHAR_UNSIGNED
+#define BOOL_TYPE CHAR /* what used to store _Bool */
+#define WCHAR_TYPE INT /* what used to store wchar_t */
+
+/*
+ * Use large-enough types.
+ */
+typedef long long CONSZ;
+typedef unsigned long long U_CONSZ;
+typedef long long OFFSZ;
+
+#define CONFMT "%lld" /* format for printing constants */
+#define LABFMT ".L%d" /* format for printing labels */
+#define STABLBL ".LL%d" /* format for stab (debugging) labels */
+#ifdef FORTRAN
+#define XL 8
+#define FLABELFMT "%s:\n"
+#define USETEXT ".text"
+#define USECONST ".data\t0" /* XXX - fix */
+#define USEBSS ".data\t1" /* XXX - fix */
+#define USEINIT ".data\t2" /* XXX - fix */
+#define MAXREGVAR 3 /* XXX - fix */
+#define BLANKCOMMON "_BLNK_"
+#define MSKIREG (M(TYSHORT)|M(TYLONG))
+#define TYIREG TYLONG
+#define FSZLENG FSZLONG
+#define FUDGEOFFSET 1
+#define AUTOREG EBP
+#define ARGREG EBP
+#define ARGOFFSET 4
+#endif
+
+#define BACKAUTO /* stack grows negatively for automatics */
+#define BACKTEMP /* stack grows negatively for temporaries */
+
+#define MYP2TREE(p) myp2tree(p);
+
+#undef FIELDOPS /* no bit-field instructions */
+#define RTOLBYTES /* bytes are numbered right to left */
+
+#define ENUMSIZE(high,low) INT /* enums are always stored in full int */
+
+/* Definitions mostly used in pass2 */
+
+#define BYTEOFF(x) ((x)&03)
+#define wdal(k) (BYTEOFF(k)==0)
+#define BITOOR(x) (x) /* bit offset to oreg offset XXX die! */
+
+#define STOARG(p)
+#define STOFARG(p)
+#define STOSTARG(p)
+#define genfcall(a,b) gencall(a,b)
+
+#define szty(t) (((t) == DOUBLE || (t) == FLOAT || \
+ (t) == LONGLONG || (t) == ULONGLONG) ? 2 : (t) == LDOUBLE ? 3 : 1)
+
+/*
+ * The x86 has a bunch of register classes, most of them interfering
+ * with each other. All registers are given a sequential number to
+ * identify it which must match rnames[] in local2.c.
+ * Class membership and overlaps are defined in the macros RSTATUS
+ * and ROVERLAP below.
+ *
+ * The classes used on x86 are:
+ * A - short and int regs
+ * B - char regs
+ * C - long long regs
+ * D - floating point
+ */
+#define EAX 000 /* Scratch and return register */
+#define EDX 001 /* Scratch and secondary return register */
+#define ECX 002 /* Scratch (and shift count) register */
+#define EBX 003 /* GDT pointer or callee-saved temporary register */
+#define ESI 004 /* Callee-saved temporary register */
+#define EDI 005 /* Callee-saved temporary register */
+#define EBP 006 /* Frame pointer */
+#define ESP 007 /* Stack pointer */
+
+#define AL 010
+#define AH 011
+#define DL 012
+#define DH 013
+#define CL 014
+#define CH 015
+#define BL 016
+#define BH 017
+
+#define EAXEDX 020
+#define EAXECX 021
+#define EAXEBX 022
+#define EAXESI 023
+#define EAXEDI 024
+#define EDXECX 025
+#define EDXEBX 026
+#define EDXESI 027
+#define EDXEDI 030
+#define ECXEBX 031
+#define ECXESI 032
+#define ECXEDI 033
+#define EBXESI 034
+#define EBXEDI 035
+#define ESIEDI 036
+
+/* The 8 math registers in class D lacks names */
+
+#define MAXREGS 047 /* 39 registers */
+
+#define RSTATUS \
+ SAREG|TEMPREG, SAREG|TEMPREG, SAREG|TEMPREG, SAREG|PERMREG, \
+ SAREG|PERMREG, SAREG|PERMREG, 0, 0, \
+ SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, SBREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, SCREG, \
+ SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG, SDREG,
+
+#define ROVERLAP \
+ /* 8 basic registers */\
+ { AL, AH, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
+ { DL, DH, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
+ { CL, CH, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { BL, BH, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EAXESI, EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\
+ { EAXEDI, EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
+ { -1 },\
+ { -1 },\
+\
+ /* 8 char registers */\
+ { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
+ { EAX, EAXEDX, EAXECX, EAXEBX, EAXESI, EAXEDI, -1 },\
+ { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
+ { EDX, EAXEDX, EDXECX, EDXEBX, EDXESI, EDXEDI, -1 },\
+ { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { ECX, EAXECX, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EBX, EAXEBX, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+\
+ /* 15 long-long-emulating registers */\
+ { EAX, AL, AH, EDX, DL, DH, EAXECX, EAXEBX, EAXESI, /* eaxedx */\
+ EAXEDI, EDXECX, EDXEBX, EDXESI, EDXEDI, -1, },\
+ { EAX, AL, AH, ECX, CL, CH, EAXEDX, EAXEBX, EAXESI, /* eaxecx */\
+ EAXEDI, EDXECX, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { EAX, AL, AH, EBX, BL, BH, EAXEDX, EAXECX, EAXESI, /* eaxebx */\
+ EAXEDI, EDXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EAX, AL, AH, ESI, EAXEDX, EAXECX, EAXEBX, EAXEDI, /* eaxesi */\
+ EDXESI, ECXESI, EBXESI, ESIEDI, -1 },\
+ { EAX, AL, AH, EDI, EAXEDX, EAXECX, EAXEBX, EAXESI, /* eaxedi */\
+ EDXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
+ { EDX, DL, DH, ECX, CL, CH, EAXEDX, EAXECX, EDXEBX, /* edxecx */\
+ EDXESI, EDXEDI, ECXEBX, ECXESI, ECXEDI, -1 },\
+ { EDX, DL, DH, EBX, BL, BH, EAXEDX, EDXECX, EDXESI, /* edxebx */\
+ EDXEDI, EAXEBX, ECXEBX, EBXESI, EBXEDI, -1 },\
+ { EDX, DL, DH, ESI, EAXEDX, EDXECX, EDXEBX, EDXEDI, /* edxesi */\
+ EAXESI, ECXESI, EBXESI, ESIEDI, -1 },\
+ { EDX, DL, DH, EDI, EAXEDX, EDXECX, EDXEBX, EDXESI, /* edxedi */\
+ EAXEDI, ECXEDI, EBXEDI, ESIEDI, -1 },\
+ { ECX, CL, CH, EBX, BL, BH, EAXECX, EDXECX, ECXESI, /* ecxebx */\
+ ECXEDI, EAXEBX, EDXEBX, EBXESI, EBXEDI, -1 },\
+ { ECX, CL, CH, ESI, EAXECX, EDXECX, ECXEBX, ECXEDI, /* ecxesi */\
+ EAXESI, EDXESI, EBXESI, ESIEDI, -1 },\
+ { ECX, CL, CH, EDI, EAXECX, EDXECX, ECXEBX, ECXESI, /* ecxedi */\
+ EAXEDI, EDXEDI, EBXEDI, ESIEDI, -1 },\
+ { EBX, BL, BH, ESI, EAXEBX, EDXEBX, ECXEBX, EBXEDI, /* ebxesi */\
+ EAXESI, EDXESI, ECXESI, ESIEDI, -1 },\
+ { EBX, BL, BH, EDI, EAXEBX, EDXEBX, ECXEBX, EBXESI, /* ebxedi */\
+ EAXEDI, EDXEDI, ECXEDI, ESIEDI, -1 },\
+ { ESI, EDI, EAXESI, EDXESI, ECXESI, EBXESI, /* esiedi */\
+ EAXEDI, EDXEDI, ECXEDI, EBXEDI, -1 },\
+\
+ /* The fp registers do not overlap with anything */\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },\
+ { -1 },
+
+
+/* Return a register class based on the type of the node */
+#define PCLASS(p) (p->n_type <= UCHAR ? SBREG : \
+ (p->n_type == LONGLONG || p->n_type == ULONGLONG ? SCREG : \
+ (p->n_type >= FLOAT && p->n_type <= LDOUBLE ? SDREG : SAREG)))
+
+#define NUMCLASS 4 /* highest number of reg classes used */
+
+int COLORMAP(int c, int *r);
+#define GCLASS(x) (x < 8 ? CLASSA : x < 16 ? CLASSB : x < 31 ? CLASSC : CLASSD)
+#define DECRA(x,y) (((x) >> (y*6)) & 63) /* decode encoded regs */
+#define ENCRD(x) (x) /* Encode dest reg in n_reg */
+#define ENCRA1(x) ((x) << 6) /* A1 */
+#define ENCRA2(x) ((x) << 12) /* A2 */
+#define ENCRA(x,y) ((x) << (6+y*6)) /* encode regs in int */
+/* XXX - return char in al? */
+#define RETREG(x) (x == CHAR || x == UCHAR ? AL : \
+ x == LONGLONG || x == ULONGLONG ? EAXEDX : \
+ x == FLOAT || x == DOUBLE || x == LDOUBLE ? 31 : EAX)
+
+//#define R2REGS 1 /* permit double indexing */
+
+/* XXX - to die */
+#define FPREG EBP /* frame pointer */
+#define STKREG ESP /* stack pointer */
+
+#define MYREADER(p) myreader(p)
+#define MYCANON(p) mycanon(p)
+#define MYOPTIM
+
+#define SHSTR (MAXSPECIAL+1) /* short struct */
+#define SFUNCALL (MAXSPECIAL+2) /* struct assign after function call */
+#define SPCON (MAXSPECIAL+3) /* positive nonnamed constant */
--- /dev/null
+++ usr.bin/pcc/i386/table.c
@@ -0,0 +1,1464 @@
+/* $Id: table.c,v 1.96 2007/09/20 14:52:13 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+# include "pass2.h"
+
+# define TLL TLONGLONG|TULONGLONG
+# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR
+# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
+# define ANYFIXED ANYSIGNED|ANYUSIGNED
+# define TUWORD TUNSIGNED|TULONG
+# define TSWORD TINT|TLONG
+# define TWORD TUWORD|TSWORD
+#define SHINT SAREG /* short and int */
+#define ININT INAREG
+#define SHCH SBREG /* shape for char */
+#define INCH INBREG
+#define SHLL SCREG /* shape for long long */
+#define INLL INCREG
+#define SHFL SDREG /* shape for float/double */
+#define INFL INDREG /* shape for float/double */
+
+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,
+ "", },
+
+/*
+ * A bunch conversions of integral<->integral types
+ * There are lots of them, first in table conversions to itself
+ * and then conversions from each type to the others.
+ */
+
+/* itself to itself, including pointers */
+
+/* convert (u)char to (u)char. */
+{ SCONV, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to int. */
+{ SCONV, ININT,
+ SHINT, TPOINT|TWORD,
+ SANY, TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert (u)longlong to (u)longlong. */
+{ SCONV, INLL,
+ SHLL, TLL,
+ SHLL, TLL,
+ 0, RLEFT,
+ "", },
+
+/* convert double <-> float. nothing to do here */
+{ SCONV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ "", },
+
+/* convert pointers to pointers. */
+{ SCONV, ININT,
+ SHINT, TPOINT,
+ SANY, TPOINT,
+ 0, RLEFT,
+ "", },
+
+/* char to something */
+
+/* convert char to (unsigned) short. */
+{ SCONV, ININT,
+ SBREG|SOREG|SNAME, TCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movsbw AL,A1\n", },
+
+/* convert unsigned char to (u)short. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TSHORT|TUSHORT,
+ NASL|NAREG, RESC1,
+ " movzbw AL,A1\n", },
+
+/* convert signed char to int (or pointer). */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TCHAR,
+ SAREG, TWORD|TPOINT,
+ NASL|NAREG, RESC1,
+ " movsbl AL,A1\n", },
+
+/* convert unsigned char to (u)int. */
+{ SCONV, ININT,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzbl AL,A1\n", },
+
+/* convert char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SANY, TLL,
+ NSPECIAL|NAREG|NASL, RESC1,
+ " movsbl AL,%eax\n cltd\n", },
+
+/* convert unsigned char to (u)long long */
+{ SCONV, INLL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SANY, TLL,
+ NCREG|NCSL, RESC1,
+ " movzbl AL,A1\n xorl U1,U1\n", },
+
+/* convert char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movsbl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* convert (u)char (in register) to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SHCH|SOREG|SNAME, TUCHAR,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG, RESC2,
+ " movzbl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* short to something */
+
+/* convert short (in memory) to char */
+{ SCONV, INCH,
+ SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert short (in reg) to char. */
+{ SCONV, INCH,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movswl AL,A1\n", },
+
+/* convert unsigned short to (u)int. */
+{ SCONV, ININT,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SAREG, TWORD,
+ NASL|NAREG, RESC1,
+ " movzwl AL,A1\n", },
+
+/* convert short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TSHORT,
+ SHLL, TLL,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " movswl AL,%eax\n cltd\n", },
+
+/* convert unsigned short to (u)long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHLL, TLL,
+ NCREG|NCSL, RESC1,
+ " movzwl AL,A1\n xorl U1,U1\n", },
+
+/* convert short (in memory) to float/double */
+{ SCONV, INFL,
+ SOREG|SNAME, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fild AL\n", },
+
+/* convert short (in register) to float/double */
+{ SCONV, INFL,
+ SAREG, TSHORT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushw AL\n fild (%esp)\n addl $2,%esp\n", },
+
+/* convert unsigned short to double XXX - use NTEMP */
+{ SCONV, INFL,
+ SAREG|SOREG|SNAME, TUSHORT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NAREG|NASL|NDREG|NTEMP, RESC2,
+ " movzwl AL,A1\n pushl A1\n"
+ " fildl (%esp)\n addl $4,%esp\n", },
+
+/* int to something */
+
+/* convert int to char. This is done when register is loaded */
+{ SCONV, INCH,
+ SAREG, TWORD,
+ SANY, TCHAR|TUCHAR,
+ NSPECIAL|NBREG|NBSL, RESC1,
+ "ZM", },
+
+/* convert int to short. Nothing to do */
+{ SCONV, INAREG,
+ SAREG, TWORD,
+ SANY, TSHORT|TUSHORT,
+ 0, RLEFT,
+ "", },
+
+/* convert int to long long */
+{ SCONV, INLL,
+ SAREG, TWORD|TPOINT,
+ SCREG, TLONGLONG,
+ NSPECIAL|NCREG|NCSL, RESC1,
+ " cltd\n", },
+
+/* convert int to unsigned long long */
+{ SCONV, INLL,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ SHLL, TULONGLONG,
+ NCSL|NCREG, RESC1,
+ " movl AL,A1\n xorl U1,U1\n", },
+
+/* convert int (in memory) to double */
+{ SCONV, INFL,
+ SOREG|SNAME, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildl AL\n", },
+
+/* convert int (in register) to double */
+{ SCONV, INFL,
+ SAREG, TWORD,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushl AL\n fildl (%esp)\n addl $4,%esp\n", },
+
+/* long long to something */
+
+/* convert (u)long long to (u)char (mem->reg) */
+{ SCONV, INCH,
+ SOREG|SNAME, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " movb AL,A1\n", },
+
+/* convert (u)long long to (u)char (reg->reg, hopefully nothing) */
+{ SCONV, INCH,
+ SHLL, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert (u)long long to (u)short (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+/* convert (u)long long to (u)short (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long to int (mem->reg) */
+{ SCONV, INAREG,
+ SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+/* convert long long to int (reg->reg, hopefully nothing) */
+{ SCONV, INAREG,
+ SHLL|SOREG|SNAME, TLL,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ "ZS", },
+
+/* convert long long (in memory) to floating */
+{ SCONV, INFL,
+ SOREG|SNAME, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ " fildq AL\n", },
+
+/* convert long long (in register) to floating */
+{ SCONV, INFL,
+ SHLL, TLONGLONG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ NTEMP|NDREG, RESC1,
+ " pushl UL\n pushl AL\n"
+ " fildq (%esp)\n addl $8,%esp\n", },
+
+/* convert unsigned long long to floating */
+{ SCONV, INFL,
+ SCREG, TULONGLONG,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NDREG, RESC1,
+ "ZJ", },
+
+/* float to something */
+
+#if 0 /* go via int by adding an extra sconv in clocal() */
+/* convert float/double to (u) char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double to (u) int/short/char. XXX should use NTEMP here */
+{ SCONV, INCH,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHCH, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NCREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+#endif
+
+/* convert float/double to (u)int. XXX should use NTEMP here */
+{ SCONV, INAREG,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SAREG, TWORD,
+ NAREG, RESC1,
+ " subl $4,%esp\n fistpl (%esp)\n popl A1\n", },
+
+/* convert float/double (in register) to (unsigned) long long */
+/* XXX - unsigned is not handled correct */
+{ SCONV, INLL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHLL, TLONGLONG|TULONGLONG,
+ NCREG, RESC1,
+ " subl $8,%esp\n fistpq (%esp)\n"
+ " popl A1\n popl U1\n", },
+
+/* slut sconv */
+
+/*
+ * Subroutine calls.
+ */
+
+{ CALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call CL\nZC", },
+
+{ UCALL, FOREFF,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ 0, 0,
+ " call CL\n", },
+
+{ CALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INAREG,
+ SCON, TANY,
+ SAREG, TWORD|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INBREG,
+ SCON, TANY,
+ SBREG, TCHAR|TUCHAR,
+ NBREG, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INCREG,
+ SCON, TANY,
+ SCREG, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call CL\n", },
+
+{ CALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ UCALL, INDREG,
+ SCON, TANY,
+ SDREG, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call CL\nZC", },
+
+{ CALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ UCALL, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, 0,
+ " call *AL\nZC", },
+
+{ CALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INAREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INBREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NBREG|NBSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INCREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NCREG|NCSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ CALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+{ UCALL, INDREG,
+ SAREG, TANY,
+ SANY, TANY,
+ NDREG|NDSL, RESC1, /* should be 0 */
+ " call *AL\nZC", },
+
+/* struct return */
+{ USTCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ "ZP call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call CL\nZC", },
+
+{ USTCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call *AL\nZC", },
+
+{ STCALL, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, 0,
+ "ZP call CL\nZC", },
+
+{ STCALL, INAREG,
+ SCON, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call CL\nZC", },
+
+{ STCALL, INAREG,
+ SNAME|SAREG, TANY,
+ SANY, TANY,
+ NAREG|NASL, RESC1, /* should be 0 */
+ "ZP call *AL\nZC", },
+
+/*
+ * The next rules handle all binop-style operators.
+ */
+/* Special treatment for long long */
+{ PLUS, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " addl AR,AL\n adcl UR,UL\n", },
+
+/* Special treatment for long long XXX - fix commutative check */
+{ PLUS, INLL|FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RRIGHT,
+ " addl AL,AR\n adcl UL,UR\n", },
+
+{ PLUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " faddl AR\n", },
+
+{ PLUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " faddp\n", },
+
+{ PLUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " incl AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal CR(AL),A1\n", },
+
+{ PLUS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SONE, TANY,
+ 0, RLEFT,
+ " incb AL\n", },
+
+{ PLUS, INAREG,
+ SAREG, TWORD,
+ SAREG, TWORD,
+ NAREG|NASL|NASR, RESC1,
+ " leal (AL,AR),A1\n", },
+
+{ MINUS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SONE, TANY,
+ 0, RLEFT,
+ " decl AL\n", },
+
+{ MINUS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SONE, TANY,
+ 0, RLEFT,
+ " decb AL\n", },
+
+/* address as register offset, negative */
+{ MINUS, INAREG,
+ SAREG, TWORD|TPOINT,
+ SPCON, TANY,
+ NAREG|NASL, RESC1,
+ " leal -CR(AL),A1\n", },
+
+{ MINUS, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " subl AR,AL\n sbbl UR,UL\n", },
+
+{ MINUS, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fsubl AR\n", },
+
+{ MINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fsubZAp\n", },
+
+/* Simple r/m->reg ops */
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SHINT, TSHORT|TUSHORT,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " Ol AR,AL\n", },
+
+{ OPSIMP, INAREG|FOREFF,
+ SHINT|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " Ow AR,AL\n", },
+
+{ OPSIMP, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " Ob AR,AL\n", },
+
+{ OPSIMP, INLL|FOREFF,
+ SHLL, TLL,
+ SHLL|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " Ol AR,AL\n Ol UR,UL\n", },
+
+
+/*
+ * The next rules handle all shift operators.
+ */
+/* (u)longlong left shift is emulated */
+{ LS, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sall AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG, TWORD,
+ SCON, TANY,
+ 0, RLEFT,
+ " sall AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shlw AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " salb AR,AL\n", },
+
+{ LS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " salb AR,AL\n", },
+
+/* (u)longlong right shift is emulated */
+{ RS, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SAREG|SNAME|SOREG|SCON, TINT, /* will be int */
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSWORD,
+ SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " sarl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUWORD,
+ SCON, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " shrl AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INAREG|FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrw AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " sarb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SHCH, TCHAR|TUCHAR,
+ NSPECIAL, RLEFT,
+ " shrb AR,AL\n", },
+
+{ RS, INCH|FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " shrb AR,AL\n", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+{ ASSIGN, FOREFF,
+ SHLL|SNAME|SOREG, TLL,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL, TLL,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, 0,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SCON, TANY,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, 0,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SCON, TANY,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, 0,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INLL,
+ SHLL|SNAME|SOREG, TLL,
+ SHLL, TLL,
+ 0, RDEST,
+ " movl AR,AL\n movl UR,UL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RDEST,
+ " movl AR,AL\n", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RDEST,
+ " movw AR,AL\n", },
+
+{ ASSIGN, FOREFF|INCH,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ SHCH, TCHAR|TUCHAR|TWORD,
+ 0, RDEST,
+ " movb AR,AL\n", },
+
+{ ASSIGN, FOREFF|INBREG,
+ SFLD, TCHAR|TUCHAR,
+ SBREG|SCON, TCHAR|TUCHAR,
+ NBREG, RDEST,
+ "ZE", },
+
+{ ASSIGN, FOREFF|INAREG,
+ SFLD, TANY,
+ SAREG, TANY,
+ NAREG, RDEST,
+ "ZE", },
+
+{ ASSIGN, FOREFF,
+ SFLD, TANY,
+ SAREG|SNAME|SOREG|SCON, TANY,
+ NAREG, 0,
+ "ZE", },
+
+{ ASSIGN, INDREG|FOREFF,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ "", }, /* This will always be in the correct register */
+
+/* order of table entries is very important here! */
+{ ASSIGN, INFL,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstt AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TLDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpt AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fstl AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstpl AL\n", },
+
+{ ASSIGN, INFL,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, RDEST,
+ " fsts AL\n", },
+
+{ ASSIGN, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SHFL, TFLOAT|TDOUBLE|TLDOUBLE,
+ 0, 0,
+ " fstps AL\n", },
+/* end very important order */
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TLDOUBLE,
+ SHFL|SOREG|SNAME, TLDOUBLE,
+ 0, RDEST,
+ " fldt AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TDOUBLE,
+ SHFL|SOREG|SNAME, TDOUBLE,
+ 0, RDEST,
+ " fldl AR\n", },
+
+{ ASSIGN, INFL|FOREFF,
+ SHFL, TFLOAT,
+ SHFL|SOREG|SNAME, TFLOAT,
+ 0, RDEST,
+ " flds AR\n", },
+
+/* Do not generate memcpy if return from funcall */
+#if 0
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME|SAREG, TPTRTO|TSTRUCT,
+ SFUNCALL, TPTRTO|TSTRUCT,
+ 0, RRIGHT,
+ "", },
+#endif
+
+{ STASG, INAREG|FOREFF,
+ SOREG|SNAME, TANY,
+ SAREG|SOREG|SNAME, TPTRTO|TANY,
+ NSPECIAL, RRIGHT,
+ "ZQ", },
+
+/*
+ * DIV/MOD/MUL
+ */
+/* long long div is emulated */
+{ DIV, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ DIV, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TWORD,
+ NSPECIAL, RDEST,
+ " cltd\n idivl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUWORD|TPOINT,
+ SAREG|SNAME|SOREG, TUWORD|TPOINT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ DIV, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NSPECIAL, RDEST,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ DIV, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NSPECIAL, RDEST,
+ " xorb %ah,%ah\n divb AR\n", },
+
+{ DIV, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fdivl AR\n", },
+
+{ DIV, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fdivZAp\n", },
+
+/* (u)longlong mod is emulated */
+{ MOD, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ MOD, INAREG,
+ SAREG, TSWORD,
+ SAREG|SNAME|SOREG, TSWORD,
+ NAREG|NSPECIAL, RESC1,
+ " cltd\n idivl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG, TUWORD|TPOINT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divl AR\n", },
+
+{ MOD, INAREG,
+ SAREG, TUSHORT,
+ SAREG|SNAME|SOREG, TUSHORT,
+ NAREG|NSPECIAL, RESC1,
+ " xorl %edx,%edx\n divw AR\n", },
+
+{ MOD, INCH,
+ SHCH, TUCHAR,
+ SHCH|SNAME|SOREG, TUCHAR,
+ NBREG|NSPECIAL, RESC1,
+ " xorb %ah,%ah\n divb AR\n", },
+
+/* (u)longlong mul is emulated */
+{ MUL, INCREG,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ SCREG|SNAME|SOREG|SCON, TLL,
+ NSPECIAL|NCREG|NCSL|NCSR, RESC1,
+ "ZO", },
+
+{ MUL, INAREG,
+ SAREG, TWORD|TPOINT,
+ SAREG|SNAME|SOREG|SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " imull AR,AL\n", },
+
+{ MUL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SNAME|SOREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " imulw AR,AL\n", },
+
+{ MUL, INCH,
+ SHCH, TCHAR|TUCHAR,
+ SHCH|SNAME|SOREG, TCHAR|TUCHAR,
+ NSPECIAL, RDEST,
+ " imulb AR\n", },
+
+{ MUL, INFL,
+ SHFL, TDOUBLE,
+ SNAME|SOREG, TDOUBLE,
+ 0, RLEFT,
+ " fmull AR\n", },
+
+{ MUL, INFL,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fmulp\n", },
+
+/*
+ * Indirection operators.
+ */
+{ UMUL, INLL,
+ SANY, TANY,
+ SOREG, TLL,
+ NCREG|NCSL, RESC1,
+ " movl UL,U1\n movl AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TPOINT|TWORD,
+ SOREG, TPOINT|TWORD,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ UMUL, INCH,
+ SANY, TANY,
+ SOREG, TCHAR|TUCHAR,
+ NBREG|NBSL, RESC1,
+ " movb AL,A1\n", },
+
+{ UMUL, INAREG,
+ SANY, TANY,
+ SOREG, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " movw AL,A1\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TLDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldt AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TDOUBLE,
+ NDREG|NDSL, RESC1,
+ " fldl AL\n", },
+
+{ UMUL, INFL,
+ SANY, TANY,
+ SOREG, TFLOAT,
+ NDREG|NDSL, RESC1,
+ " flds AL\n", },
+
+/*
+ * Logical/branching operators
+ */
+
+/* Comparisions, take care of everything */
+{ OPLOG, FORCC,
+ SHLL|SOREG|SNAME, TLL,
+ SHLL, TLL,
+ 0, 0,
+ "ZD", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ SCON|SAREG, TWORD|TPOINT,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SCON|SAREG, TWORD|TPOINT,
+ SAREG|SOREG|SNAME, TWORD|TPOINT,
+ 0, RESCC,
+ " cmpl AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TANY,
+ 0, RESCC,
+ " cmpw AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TANY,
+ 0, RESCC,
+ " cmpb AR,AL\n", },
+
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+{ OPLOG, FORCC,
+ SOREG|SNAME, TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ NSPECIAL, 0,
+ "ZG", },
+
+#if 0
+/* Ppro and later only */
+{ OPLOG, FORCC,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ SDREG, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RESCC,
+ "ZA fucomip %st,%st(1)\n", },
+#endif
+
+{ OPLOG, FORCC,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "diediedie!", },
+
+/* AND/OR/ER/NOT */
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TWORD,
+ SCON|SAREG, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG|SOREG|SNAME, TLL,
+ 0, RLEFT,
+ " andl AR,AL\n andl UR,UL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TWORD,
+ SAREG|SOREG|SNAME, TWORD,
+ 0, RLEFT,
+ " andl AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ SCON|SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG|SOREG|SNAME, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " andw AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ SCON|SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+
+{ AND, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG|SOREG|SNAME, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " andb AR,AL\n", },
+/* AND/OR/ER/NOT */
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp LL\n", },
+
+#ifdef GCC_COMPAT
+{ GOTO, FOREFF,
+ SAREG, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jmp *AL\n", },
+#endif
+
+/*
+ * Convert LTYPE to reg.
+ */
+{ OPLTYPE, INLL,
+ SANY, TANY,
+ SCREG|SCON|SOREG|SNAME, TLL,
+ NCREG, RESC1,
+ " movl UL,U1\n movl AL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SCON|SOREG|SNAME, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " movl AL,A1\n", },
+
+{ OPLTYPE, INBREG,
+ SANY, TANY,
+ SBREG|SOREG|SNAME|SCON, TCHAR|TUCHAR,
+ NBREG, RESC1,
+ " movb AL,A1\n", },
+
+{ OPLTYPE, INAREG,
+ SANY, TANY,
+ SAREG|SOREG|SNAME|SCON, TSHORT|TUSHORT,
+ NAREG, RESC1,
+ " movw AL,A1\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TLDOUBLE,
+ SOREG|SNAME, TLDOUBLE,
+ NDREG, RESC1,
+ " fldt AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TDOUBLE,
+ SOREG|SNAME, TDOUBLE,
+ NDREG, RESC1,
+ " fldl AL\n", },
+
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT,
+ SOREG|SNAME, TFLOAT,
+ NDREG, RESC1,
+ " flds AL\n", },
+
+/* Only used in ?: constructs. The stack already contains correct value */
+{ OPLTYPE, INDREG,
+ SANY, TFLOAT|TDOUBLE|TLDOUBLE,
+ SDREG, TFLOAT|TDOUBLE|TLDOUBLE,
+ NDREG, RESC1,
+ "", },
+
+/*
+ * Negate a word.
+ */
+
+{ UMINUS, INCREG|FOREFF,
+ SCREG, TLL,
+ SCREG, TLL,
+ 0, RLEFT,
+ " negl AL\n adcl $0,UL\n negl UL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TWORD|TPOINT,
+ SAREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " negl AL\n", },
+
+{ UMINUS, INAREG|FOREFF,
+ SAREG, TSHORT|TUSHORT,
+ SAREG, TSHORT|TUSHORT,
+ 0, RLEFT,
+ " negw AL\n", },
+
+{ UMINUS, INBREG|FOREFF,
+ SBREG, TCHAR|TUCHAR,
+ SBREG, TCHAR|TUCHAR,
+ 0, RLEFT,
+ " negb AL\n", },
+
+{ UMINUS, INFL|FOREFF,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ SHFL, TLDOUBLE|TDOUBLE|TFLOAT,
+ 0, RLEFT,
+ " fchs\n", },
+
+{ COMPL, INCREG,
+ SCREG, TLL,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n notl UL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TWORD,
+ SANY, TANY,
+ 0, RLEFT,
+ " notl AL\n", },
+
+{ COMPL, INAREG,
+ SAREG, TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, RLEFT,
+ " notw AL\n", },
+
+{ COMPL, INBREG,
+ SBREG, TCHAR|TUCHAR,
+ SANY, TANY,
+ 0, RLEFT,
+ " notb AL\n", },
+
+/*
+ * Arguments to functions.
+ */
+{ FUNARG, FOREFF,
+ SCON|SCREG|SNAME|SOREG, TLL,
+ SANY, TLL,
+ 0, RNULL,
+ " pushl UL\n pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON|SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ 0, RNULL,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR,
+ 0, RNULL,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TSHORT,
+ SANY, TSHORT,
+ NAREG, 0,
+ " movswl AL,ZN\n pushl ZN\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TUSHORT,
+ SANY, TUSHORT,
+ NAREG, 0,
+ " movzwl AL,ZN\n pushl ZN\n", },
+
+{ FUNARG, FOREFF,
+ SHCH|SNAME|SOREG, TCHAR,
+ SANY, TCHAR,
+ NAREG, 0,
+ " movsbl AL,A1\n pushl A1\n", },
+
+{ FUNARG, FOREFF,
+ SHCH|SNAME|SOREG, TUCHAR,
+ SANY, TUCHAR,
+ NAREG, 0,
+ " movzbl AL,A1\n pushl A1\n", },
+
+{ FUNARG, FOREFF,
+ SNAME|SOREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, 0,
+ " pushl UL\n pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TDOUBLE,
+ SANY, TDOUBLE,
+ 0, 0,
+ " subl $8,%esp\n fstpl (%esp)\n", },
+
+{ FUNARG, FOREFF,
+ SNAME|SOREG, TFLOAT,
+ SANY, TFLOAT,
+ 0, 0,
+ " pushl AL\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TFLOAT,
+ SANY, TFLOAT,
+ 0, 0,
+ " subl $4,%esp\n fstps (%esp)\n", },
+
+{ FUNARG, FOREFF,
+ SDREG, TLDOUBLE,
+ SANY, TLDOUBLE,
+ 0, 0,
+ " subl $12,%esp\n fstpt (%esp)\n", },
+
+{ STARG, FOREFF,
+ SAREG|SOREG|SNAME|SCON, TANY,
+ SANY, TSTRUCT,
+ NSPECIAL|NAREG, 0,
+ "ZF", },
+
+# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
+
+{ UMUL, DF( UMUL ), },
+
+{ ASSIGN, DF(ASSIGN), },
+
+{ STASG, DF(STASG), },
+
+{ FLD, DF(FLD), },
+
+{ OPLEAF, DF(NAME), },
+
+/* { INIT, DF(INIT), }, */
+
+{ OPUNARY, DF(UMINUS), },
+
+{ OPANY, DF(BITYPE), },
+
+{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);
--- /dev/null
+++ usr.bin/pcc/i386/local2.c
@@ -0,0 +1,1052 @@
+/* $Id: local2.c,v 1.89 2007/09/16 19:08:16 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+# include "pass2.h"
+# include <ctype.h>
+# include <string.h>
+
+void acon(NODE *p);
+int argsize(NODE *p);
+
+static int stkpos;
+
+void
+lineid(int l, char *fn)
+{
+ /* identify line l and file fn */
+ printf("# line %d, file %s\n", l, fn);
+}
+
+void
+deflab(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static int regoff[7];
+static TWORD ftype;
+
+/*
+ * Print out the prolog assembler.
+ * addto and regoff are already calculated.
+ */
+static void
+prtprolog(struct interpass_prolog *ipp, int addto)
+{
+ int i, j;
+
+ printf(" pushl %%ebp\n");
+ printf(" movl %%esp,%%ebp\n");
+ if (addto)
+ printf(" subl $%d,%%esp\n", addto);
+ for (i = ipp->ipp_regs, j = 0; i; i >>= 1, j++)
+ if (i & 1)
+ fprintf(stdout, " movl %s,-%d(%s)\n",
+ rnames[j], regoff[j], rnames[FPREG]);
+}
+
+/*
+ * calculate stack size and offsets
+ */
+static int
+offcalc(struct interpass_prolog *ipp)
+{
+ int i, j, addto;
+
+ addto = p2maxautooff;
+ if (addto >= AUTOINIT/SZCHAR)
+ addto -= AUTOINIT/SZCHAR;
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
+ if (i & 1) {
+ addto += SZINT/SZCHAR;
+ regoff[j] = addto;
+ }
+ }
+ return addto;
+}
+
+void
+prologue(struct interpass_prolog *ipp)
+{
+ int addto;
+
+ ftype = ipp->ipp_type;
+ if (ipp->ipp_vis)
+ printf(" .globl %s\n", ipp->ipp_name);
+ printf(" .align 4\n");
+ printf("%s:\n", ipp->ipp_name);
+ /*
+ * We here know what register to save and how much to
+ * add to the stack.
+ */
+ addto = offcalc(ipp);
+ prtprolog(ipp, addto);
+}
+
+void
+eoftn(struct interpass_prolog *ipp)
+{
+ int i, j;
+
+ if (ipp->ipp_ip.ip_lbl == 0)
+ return; /* no code needs to be generated */
+
+ /* return from function code */
+ for (i = ipp->ipp_regs, j = 0; i ; i >>= 1, j++) {
+ if (i & 1)
+ fprintf(stdout, " movl -%d(%s),%s\n",
+ regoff[j], rnames[FPREG], rnames[j]);
+
+ }
+
+ /* struct return needs special treatment */
+ if (ftype == STRTY || ftype == UNIONTY) {
+ printf(" movl 8(%%ebp),%%eax\n");
+ printf(" leave\n");
+ printf(" ret $4\n");
+ } else {
+ printf(" leave\n");
+ printf(" ret\n");
+ }
+}
+
+/*
+ * add/sub/...
+ *
+ * Param given:
+ */
+void
+hopcode(int f, int o)
+{
+ char *str;
+
+ switch (o) {
+ case PLUS:
+ str = "add";
+ break;
+ case MINUS:
+ str = "sub";
+ break;
+ case AND:
+ str = "and";
+ break;
+ case OR:
+ str = "or";
+ break;
+ case ER:
+ str = "xor";
+ break;
+ default:
+ comperr("hopcode2: %d", o);
+ str = 0; /* XXX gcc */
+ }
+ printf("%s%c", str, f);
+}
+
+/*
+ * Return type size in bytes. Used by R2REGS, arg 2 to offset().
+ */
+int
+tlen(p) NODE *p;
+{
+ switch(p->n_type) {
+ case CHAR:
+ case UCHAR:
+ return(1);
+
+ case SHORT:
+ case USHORT:
+ return(SZSHORT/SZCHAR);
+
+ case DOUBLE:
+ return(SZDOUBLE/SZCHAR);
+
+ case INT:
+ case UNSIGNED:
+ case LONG:
+ case ULONG:
+ return(SZINT/SZCHAR);
+
+ case LONGLONG:
+ case ULONGLONG:
+ return SZLONGLONG/SZCHAR;
+
+ default:
+ if (!ISPTR(p->n_type))
+ comperr("tlen type %d not pointer");
+ return SZPOINT(p->n_type)/SZCHAR;
+ }
+}
+
+/*
+ * Emit code to compare two longlong numbers.
+ */
+static void
+twollcomp(NODE *p)
+{
+ int o = p->n_op;
+ int s = getlab();
+ int e = p->n_label;
+ int cb1, cb2;
+
+ if (o >= ULE)
+ o -= (ULE-LE);
+ switch (o) {
+ case NE:
+ cb1 = 0;
+ cb2 = NE;
+ break;
+ case EQ:
+ cb1 = NE;
+ cb2 = 0;
+ break;
+ case LE:
+ case LT:
+ cb1 = GT;
+ cb2 = LT;
+ break;
+ case GE:
+ case GT:
+ cb1 = LT;
+ cb2 = GT;
+ break;
+
+ default:
+ cb1 = cb2 = 0; /* XXX gcc */
+ }
+ if (p->n_op >= ULE)
+ cb1 += 4, cb2 += 4;
+ expand(p, 0, " cmpl UR,UL\n");
+ if (cb1) cbgen(cb1, s);
+ if (cb2) cbgen(cb2, e);
+ expand(p, 0, " cmpl AR,AL\n");
+ cbgen(p->n_op, e);
+ deflab(s);
+}
+
+/*
+ * Assign to a bitfield.
+ * Clumsy at least, but what to do?
+ */
+static void
+bfasg(NODE *p)
+{
+ NODE *fn = p->n_left;
+ int shift = UPKFOFF(fn->n_rval);
+ int fsz = UPKFSZ(fn->n_rval);
+ int andval, tch = 0;
+
+ /* get instruction size */
+ switch (p->n_type) {
+ case CHAR: case UCHAR: tch = 'b'; break;
+ case SHORT: case USHORT: tch = 'w'; break;
+ case INT: case UNSIGNED: tch = 'l'; break;
+ default: comperr("bfasg");
+ }
+
+ /* put src into a temporary reg */
+ fprintf(stdout, " mov%c ", tch);
+ adrput(stdout, getlr(p, 'R'));
+ fprintf(stdout, ",");
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+
+ /* AND away the bits from dest */
+ andval = ~(((1 << fsz) - 1) << shift);
+ fprintf(stdout, " and%c $%d,", tch, andval);
+ adrput(stdout, fn->n_left);
+ fprintf(stdout, "\n");
+
+ /* AND away unwanted bits from src */
+ andval = ((1 << fsz) - 1);
+ fprintf(stdout, " and%c $%d,", tch, andval);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+
+ /* SHIFT left src number of bits */
+ if (shift) {
+ fprintf(stdout, " sal%c $%d,", tch, shift);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, "\n");
+ }
+
+ /* OR in src to dest */
+ fprintf(stdout, " or%c ", tch);
+ adrput(stdout, getlr(p, '1'));
+ fprintf(stdout, ",");
+ adrput(stdout, fn->n_left);
+ fprintf(stdout, "\n");
+}
+
+/*
+ * Push a structure on stack as argument.
+ * the scratch registers are already free here
+ */
+static void
+starg(NODE *p)
+{
+ FILE *fp = stdout;
+
+ fprintf(fp, " subl $%d,%%esp\n", p->n_stsize);
+ fprintf(fp, " pushl $%d\n", p->n_stsize);
+ expand(p, 0, " pushl AL\n");
+ expand(p, 0, " leal 8(%esp),A1\n");
+ expand(p, 0, " pushl A1\n");
+ fprintf(fp, " call memcpy\n");
+ fprintf(fp, " addl $12,%%esp\n");
+}
+
+/*
+ * Compare two floating point numbers.
+ */
+static void
+fcomp(NODE *p)
+{
+
+ if (p->n_left->n_op == REG) {
+ if (p->n_su & DORIGHT)
+ expand(p, 0, " fxch\n");
+ expand(p, 0, " fucompp\n"); /* emit compare insn */
+ } else if (p->n_left->n_type == DOUBLE)
+ expand(p, 0, " fcompl AL\n"); /* emit compare insn */
+ else if (p->n_left->n_type == FLOAT)
+ expand(p, 0, " fcomp AL\n"); /* emit compare insn */
+ else
+ comperr("bad compare %p\n", p);
+ expand(p, 0, " fnstsw %ax\n"); /* move status reg to ax */
+
+ switch (p->n_op) {
+ case EQ:
+ expand(p, 0, " andb $64,%ah\n jne LC\n");
+ break;
+ case NE:
+ expand(p, 0, " andb $64,%ah\n je LC\n");
+ break;
+ case LE:
+ expand(p, 0, " andb $65,%ah\n cmpb $1,%ah\n jne LC\n");
+ break;
+ case LT:
+ expand(p, 0, " andb $65,%ah\n je LC\n");
+ break;
+ case GT:
+ expand(p, 0, " andb $1,%ah\n jne LC\n");
+ break;
+ case GE:
+ expand(p, 0, " andb $65,%ah\n jne LC\n");
+ break;
+ default:
+ comperr("fcomp op %d\n", p->n_op);
+ }
+}
+
+/*
+ * Convert an unsigned long long to floating point number.
+ */
+static void
+ulltofp(NODE *p)
+{
+ static int loadlab;
+ int jmplab;
+
+ if (loadlab == 0) {
+ loadlab = getlab();
+ expand(p, 0, " .data\n");
+ printf(LABFMT ": .long 0,0x80000000,0x403f\n", loadlab);
+ expand(p, 0, " .text\n");
+ }
+ jmplab = getlab();
+ expand(p, 0, " pushl UL\n pushl AL\n");
+ expand(p, 0, " fildq (%esp)\n");
+ expand(p, 0, " addl $8,%esp\n");
+ expand(p, 0, " cmpl $0,UL\n");
+ printf(" jge " LABFMT "\n", jmplab);
+ printf(" fldt " LABFMT "\n", loadlab);
+ printf(" faddp %%st,%%st(1)\n");
+ printf(LABFMT ":\n", jmplab);
+}
+
+static int
+argsiz(NODE *p)
+{
+ TWORD t = p->n_type;
+
+ if (t < LONGLONG || t == FLOAT || t > BTMASK)
+ return 4;
+ if (t == LONGLONG || t == ULONGLONG || t == DOUBLE)
+ return 8;
+ if (t == LDOUBLE)
+ return 12;
+ if (t == STRTY || t == UNIONTY)
+ return p->n_stsize;
+ comperr("argsiz");
+ return 0;
+}
+
+void
+zzzcode(NODE *p, int c)
+{
+ NODE *r, *l;
+ int pr, lr, s;
+ char *ch;
+
+ switch (c) {
+ case 'A': /* swap st0 and st1 if right is evaluated second */
+ if ((p->n_su & DORIGHT) == 0) {
+ if (logop(p->n_op))
+ printf(" fxch\n");
+ else
+ printf("r");
+ }
+ break;
+
+ case 'C': /* remove from stack after subroutine call */
+ pr = p->n_qual;
+ if (p->n_op == STCALL || p->n_op == USTCALL)
+ pr += 4;
+ if (p->n_op == UCALL)
+ return; /* XXX remove ZC from UCALL */
+ if (pr)
+ printf(" addl $%d, %s\n", pr, rnames[ESP]);
+ break;
+
+ case 'D': /* Long long comparision */
+ twollcomp(p);
+ break;
+
+ case 'E': /* Assign to bitfield */
+ bfasg(p);
+ break;
+
+ case 'F': /* Structure argument */
+ if (p->n_stalign != 0) /* already on stack */
+ starg(p);
+ break;
+
+ case 'G': /* Floating point compare */
+ fcomp(p);
+ break;
+
+ case 'J': /* convert unsigned long long to floating point */
+ ulltofp(p);
+ break;
+
+ case 'M': /* Output sconv move, if needed */
+ l = getlr(p, 'L');
+ /* XXX fixneed: regnum */
+ pr = DECRA(p->n_reg, 0);
+ lr = DECRA(l->n_reg, 0);
+ if ((pr == AL && lr == EAX) || (pr == BL && lr == EBX) ||
+ (pr == CL && lr == ECX) || (pr == DL && lr == EDX))
+ ;
+ else
+ printf(" movb %%%cl,%s\n",
+ rnames[lr][2], rnames[pr]);
+ l->n_rval = l->n_reg = p->n_reg; /* XXX - not pretty */
+ break;
+
+ case 'N': /* output extended reg name */
+ printf("%s", rnames[getlr(p, '1')->n_rval]);
+ break;
+
+ case 'O': /* print out emulated ops */
+ pr = 16;
+ if (p->n_op == RS || p->n_op == LS) {
+ expand(p, INAREG, "\tpushl AR\n");
+ pr = 12;
+ } else
+ expand(p, INCREG, "\tpushl UR\n\tpushl AR\n");
+ expand(p, INCREG, "\tpushl UL\n\tpushl AL\n");
+ if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv";
+ else if (p->n_op == DIV) ch = "div";
+ else if (p->n_op == MUL) ch = "mul";
+ else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod";
+ else if (p->n_op == MOD) ch = "mod";
+ else if (p->n_op == RS && p->n_type == ULONGLONG) ch = "lshr";
+ else if (p->n_op == RS) ch = "ashr";
+ else if (p->n_op == LS) ch = "ashl";
+ else ch = 0, comperr("ZO");
+ printf("\tcall __%sdi3\n\taddl $%d,%s\n", ch, pr, rnames[ESP]);
+ break;
+
+ case 'P': /* push hidden argument on stack */
+ r = (NODE *)p->n_sue;
+ printf("\tleal -%d(%%ebp),", stkpos);
+ adrput(stdout, getlr(p, '1'));
+ printf("\n\tpushl ");
+ adrput(stdout, getlr(p, '1'));
+ putchar('\n');
+ break;
+
+ case 'Q': /* emit struct assign */
+ /* XXX - optimize for small structs */
+ printf("\tpushl $%d\n", p->n_stsize);
+ expand(p, INAREG, "\tpushl AR\n");
+ expand(p, INAREG, "\tleal AL,%eax\n\tpushl %eax\n");
+ printf("\tcall memcpy\n");
+ printf("\taddl $12,%%esp\n");
+ break;
+
+ case 'S': /* emit eventual move after cast from longlong */
+ pr = DECRA(p->n_reg, 0);
+ lr = p->n_left->n_rval;
+ switch (p->n_type) {
+ case CHAR:
+ case UCHAR:
+ if (rnames[pr][2] == 'l' && rnames[lr][2] == 'x' &&
+ rnames[pr][1] == rnames[lr][1])
+ break;
+ if (rnames[lr][2] == 'x') {
+ printf("\tmovb %%%cl,%s\n",
+ rnames[lr][1], rnames[pr]);
+ break;
+ }
+ /* Must go via stack */
+ s = BITOOR(freetemp(1));
+ printf("\tmovl %%e%ci,%d(%%ebp)\n", rnames[lr][1], s);
+ printf("\tmovb %d(%%ebp),%s\n", s, rnames[pr]);
+// comperr("SCONV1 %s->%s", rnames[lr], rnames[pr]);
+ break;
+
+ case SHORT:
+ case USHORT:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ printf("\tmovw %%%c%c,%%%s\n",
+ rnames[lr][1], rnames[lr][2], rnames[pr]+2);
+ break;
+ case INT:
+ case UNSIGNED:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ printf("\tmovl %%e%c%c,%s\n",
+ rnames[lr][1], rnames[lr][2], rnames[pr]);
+ break;
+
+ default:
+ if (rnames[lr][1] == rnames[pr][2] &&
+ rnames[lr][2] == rnames[pr][3])
+ break;
+ comperr("SCONV2 %s->%s", rnames[lr], rnames[pr]);
+ break;
+ }
+ break;
+
+ default:
+ comperr("zzzcode %c", c);
+ }
+}
+
+/*ARGSUSED*/
+int
+rewfld(NODE *p)
+{
+ return(1);
+}
+
+int canaddr(NODE *);
+int
+canaddr(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o==NAME || o==REG || o==ICON || o==OREG ||
+ (o==UMUL && shumul(p->n_left)))
+ return(1);
+ return(0);
+}
+
+/*
+ * Does the bitfield shape match?
+ */
+int
+flshape(NODE *p)
+{
+ int o = p->n_op;
+
+ if (o == OREG || o == REG || o == NAME)
+ return SRDIR; /* Direct match */
+ if (o == UMUL && shumul(p->n_left))
+ return SROREG; /* Convert into oreg */
+ return SRREG; /* put it into a register */
+}
+
+/* INTEMP shapes must not contain any temporary registers */
+/* XXX should this go away now? */
+int
+shtemp(NODE *p)
+{
+ return 0;
+#if 0
+ int r;
+
+ if (p->n_op == STARG )
+ p = p->n_left;
+
+ switch (p->n_op) {
+ case REG:
+ return (!istreg(p->n_rval));
+
+ case OREG:
+ r = p->n_rval;
+ if (R2TEST(r)) {
+ if (istreg(R2UPK1(r)))
+ return(0);
+ r = R2UPK2(r);
+ }
+ return (!istreg(r));
+
+ case UMUL:
+ p = p->n_left;
+ return (p->n_op != UMUL && shtemp(p));
+ }
+
+ if (optype(p->n_op) != LTYPE)
+ return(0);
+ return(1);
+#endif
+}
+
+void
+adrcon(CONSZ val)
+{
+ printf("$" CONFMT, val);
+}
+
+void
+conput(FILE *fp, NODE *p)
+{
+ int val = p->n_lval;
+
+ switch (p->n_op) {
+ case ICON:
+ if (p->n_name[0] != '\0') {
+ fprintf(fp, "%s", p->n_name);
+ if (val)
+ fprintf(fp, "+%d", val);
+ } else
+ fprintf(fp, "%d", val);
+ return;
+
+ default:
+ comperr("illegal conput, p %p", p);
+ }
+}
+
+/*ARGSUSED*/
+void
+insput(NODE *p)
+{
+ comperr("insput");
+}
+
+/*
+ * Write out the upper address, like the upper register of a 2-register
+ * reference, or the next memory location.
+ */
+void
+upput(NODE *p, int size)
+{
+
+ size /= SZCHAR;
+ switch (p->n_op) {
+ case REG:
+ fprintf(stdout, "%%%s", &rnames[p->n_rval][3]);
+ break;
+
+ case NAME:
+ case OREG:
+ p->n_lval += size;
+ adrput(stdout, p);
+ p->n_lval -= size;
+ break;
+ case ICON:
+ fprintf(stdout, "$" CONFMT, p->n_lval >> 32);
+ break;
+ default:
+ comperr("upput bad op %d size %d", p->n_op, size);
+ }
+}
+
+void
+adrput(FILE *io, NODE *p)
+{
+ int r;
+ /* output an address, with offsets, from p */
+
+ if (p->n_op == FLD)
+ p = p->n_left;
+
+ switch (p->n_op) {
+
+ case NAME:
+ if (p->n_name[0] != '\0') {
+ fputs(p->n_name, io);
+ if (p->n_lval != 0)
+ fprintf(io, "+" CONFMT, p->n_lval);
+ } else
+ fprintf(io, CONFMT, p->n_lval);
+ return;
+
+ case OREG:
+ r = p->n_rval;
+ if (p->n_lval)
+ fprintf(io, "%d", (int)p->n_lval);
+ if (R2TEST(r)) {
+ fprintf(io, "(%s,%s,4)", rnames[R2UPK1(r)],
+ rnames[R2UPK2(r)]);
+ } else
+ fprintf(io, "(%s)", rnames[p->n_rval]);
+ return;
+ case ICON:
+ /* addressable value of the constant */
+ fputc('$', io);
+ conput(io, p);
+ return;
+
+ case MOVE:
+ case REG:
+ switch (p->n_type) {
+ case LONGLONG:
+ case ULONGLONG:
+ fprintf(io, "%%%c%c%c", rnames[p->n_rval][0],
+ rnames[p->n_rval][1], rnames[p->n_rval][2]);
+ break;
+ case SHORT:
+ case USHORT:
+ fprintf(io, "%%%s", &rnames[p->n_rval][2]);
+ break;
+ default:
+ fprintf(io, "%s", rnames[p->n_rval]);
+ }
+ return;
+
+ default:
+ comperr("illegal address, op %d, node %p", p->n_op, p);
+ return;
+
+ }
+}
+
+static char *
+ccbranches[] = {
+ "je", /* jumpe */
+ "jne", /* jumpn */
+ "jle", /* jumple */
+ "jl", /* jumpl */
+ "jge", /* jumpge */
+ "jg", /* jumpg */
+ "jbe", /* jumple (jlequ) */
+ "jb", /* jumpl (jlssu) */
+ "jae", /* jumpge (jgequ) */
+ "ja", /* jumpg (jgtru) */
+};
+
+
+/* printf conditional and unconditional branches */
+void
+cbgen(int o, int lab)
+{
+ if (o < EQ || o > UGT)
+ comperr("bad conditional branch: %s", opst[o]);
+ printf(" %s " LABFMT "\n", ccbranches[o-EQ], lab);
+}
+
+static void
+fixcalls(NODE *p)
+{
+ /* Prepare for struct return by allocating bounce space on stack */
+ switch (p->n_op) {
+ case STCALL:
+ case USTCALL:
+ if (p->n_stsize+p2autooff > stkpos)
+ stkpos = p->n_stsize+p2autooff;
+ break;
+ }
+}
+
+/*
+ * Must store floats in memory if there are two function calls involved.
+ */
+static int
+storefloat(struct interpass *ip, NODE *p)
+{
+ int l, r;
+
+ switch (optype(p->n_op)) {
+ case BITYPE:
+ l = storefloat(ip, p->n_left);
+ r = storefloat(ip, p->n_right);
+ if (p->n_op == CM)
+ return 0; /* arguments, don't care */
+ if (callop(p->n_op))
+ return 1; /* found one */
+#define ISF(p) ((p)->n_type == FLOAT || (p)->n_type == DOUBLE || \
+ (p)->n_type == LDOUBLE)
+ if (ISF(p->n_left) && ISF(p->n_right) && l && r) {
+ /* must store one. store left */
+ struct interpass *nip;
+ TWORD t = p->n_left->n_type;
+ NODE *ll;
+ int off;
+
+ off = BITOOR(freetemp(szty(t)));
+ ll = mklnode(OREG, off, FPREG, t);
+ nip = ipnode(mkbinode(ASSIGN, ll, p->n_left, t));
+ p->n_left = mklnode(OREG, off, FPREG, t);
+ DLIST_INSERT_BEFORE(ip, nip, qelem);
+ }
+ return l|r;
+
+ case UTYPE:
+ l = storefloat(ip, p->n_left);
+ if (callop(p->n_op))
+ l = 1;
+ return l;
+ default:
+ return 0;
+ }
+}
+
+void
+myreader(struct interpass *ipole)
+{
+ struct interpass *ip;
+
+ stkpos = p2autooff;
+ DLIST_FOREACH(ip, ipole, qelem) {
+ if (ip->type != IP_NODE)
+ continue;
+ walkf(ip->ip_node, fixcalls);
+ storefloat(ip, ip->ip_node);
+ }
+ if (stkpos > p2autooff)
+ p2autooff = stkpos;
+ if (stkpos > p2maxautooff)
+ p2maxautooff = stkpos;
+ if (x2debug)
+ printip(ipole);
+}
+
+/*
+ * Remove some PCONVs after OREGs are created.
+ */
+static void
+pconv2(NODE *p)
+{
+ NODE *q;
+
+ if (p->n_op == PLUS) {
+ if (p->n_type == (PTR|SHORT) || p->n_type == (PTR|USHORT)) {
+ if (p->n_right->n_op != ICON)
+ return;
+ if (p->n_left->n_op != PCONV)
+ return;
+ if (p->n_left->n_left->n_op != OREG)
+ return;
+ q = p->n_left->n_left;
+ nfree(p->n_left);
+ p->n_left = q;
+ /*
+ * This will be converted to another OREG later.
+ */
+ }
+ }
+}
+
+void
+mycanon(NODE *p)
+{
+ walkf(p, pconv2);
+}
+
+void
+myoptim(struct interpass *ip)
+{
+}
+
+static char rl[] =
+ { EAX, EAX, EAX, EAX, EAX, EDX, EDX, EDX, EDX, ECX, ECX, ECX, EBX, EBX, ESI };
+static char rh[] =
+ { EDX, ECX, EBX, ESI, EDI, ECX, EBX, ESI, EDI, EBX, ESI, EDI, ESI, EDI, EDI };
+
+void
+rmove(int s, int d, TWORD t)
+{
+ int sl, sh, dl, dh;
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+#if 1
+ sl = rl[s-EAXEDX];
+ sh = rh[s-EAXEDX];
+ dl = rl[d-EAXEDX];
+ dh = rh[d-EAXEDX];
+
+ /* sanity checks, remove when satisfied */
+ if (memcmp(rnames[s], rnames[sl]+1, 3) != 0 ||
+ memcmp(rnames[s]+3, rnames[sh]+1, 3) != 0)
+ comperr("rmove source error");
+ if (memcmp(rnames[d], rnames[dl]+1, 3) != 0 ||
+ memcmp(rnames[d]+3, rnames[dh]+1, 3) != 0)
+ comperr("rmove dest error");
+#define SW(x,y) { int i = x; x = y; y = i; }
+ if (sl == dh || sh == dl) {
+ /* Swap if moving to itself */
+ SW(sl, sh);
+ SW(dl, dh);
+ }
+ if (sl != dl)
+ printf(" movl %s,%s\n", rnames[sl], rnames[dl]);
+ if (sh != dh)
+ printf(" movl %s,%s\n", rnames[sh], rnames[dh]);
+#else
+ if (memcmp(rnames[s], rnames[d], 3) != 0)
+ printf(" movl %%%c%c%c,%%%c%c%c\n",
+ rnames[s][0],rnames[s][1],rnames[s][2],
+ rnames[d][0],rnames[d][1],rnames[d][2]);
+ if (memcmp(&rnames[s][3], &rnames[d][3], 3) != 0)
+ printf(" movl %%%c%c%c,%%%c%c%c\n",
+ rnames[s][3],rnames[s][4],rnames[s][5],
+ rnames[d][3],rnames[d][4],rnames[d][5]);
+#endif
+ break;
+ case CHAR:
+ case UCHAR:
+ printf(" movb %s,%s\n", rnames[s], rnames[d]);
+ break;
+ case FLOAT:
+ case DOUBLE:
+ case LDOUBLE:
+#ifdef notdef
+ /* a=b()*c(); will generate this */
+ comperr("bad float rmove: %d %d", s, d);
+#endif
+ break;
+ default:
+ printf(" movl %s,%s\n", rnames[s], rnames[d]);
+ }
+}
+
+/*
+ * For class c, find worst-case displacement of the number of
+ * registers in the array r[] indexed by class.
+ */
+int
+COLORMAP(int c, int *r)
+{
+ int num;
+
+ switch (c) {
+ case CLASSA:
+ num = r[CLASSB] > 4 ? 4 : r[CLASSB];
+ num += 2*r[CLASSC];
+ num += r[CLASSA];
+ return num < 6;
+ case CLASSB:
+ num = r[CLASSA];
+ num += 2*r[CLASSC];
+ num += r[CLASSB];
+ return num < 4;
+ case CLASSC:
+ num = r[CLASSA];
+ num += r[CLASSB] > 4 ? 4 : r[CLASSB];
+ num += 2*r[CLASSC];
+ return num < 5;
+ case CLASSD:
+ return r[CLASSD] < DREGCNT;
+ }
+ return 0; /* XXX gcc */
+}
+
+char *rnames[] = {
+ "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%ebp", "%esp",
+ "%al", "%ah", "%dl", "%dh", "%cl", "%ch", "%bl", "%bh",
+ "eaxedx", "eaxecx", "eaxebx", "eaxesi", "eaxedi", "edxecx",
+ "edxebx", "edxesi", "edxedi", "ecxebx", "ecxesi", "ecxedi",
+ "ebxesi", "ebxedi", "esiedi",
+ "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7",
+};
+
+/*
+ * Return a class suitable for a specific type.
+ */
+int
+gclass(TWORD t)
+{
+ if (t == CHAR || t == UCHAR)
+ return CLASSB;
+ if (t == LONGLONG || t == ULONGLONG)
+ return CLASSC;
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ return CLASSD;
+ return CLASSA;
+}
+
+/*
+ * Calculate argument sizes.
+ */
+void
+lastcall(NODE *p)
+{
+ NODE *op = p;
+ int size = 0;
+
+ p->n_qual = 0;
+ if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
+ return;
+ for (p = p->n_right; p->n_op == CM; p = p->n_left)
+ size += argsiz(p->n_right);
+ size += argsiz(p);
+ op->n_qual = size; /* XXX */
+}
+
+/*
+ * Special shapes.
+ */
+int
+special(NODE *p, int shape)
+{
+ int o = p->n_op;
+
+ switch (shape) {
+ case SFUNCALL:
+ if (o == STCALL || o == USTCALL)
+ return SRREG;
+ break;
+ case SPCON:
+ if (o != ICON || p->n_name[0] ||
+ p->n_lval < 0 || p->n_lval > 0x7fffffff)
+ break;
+ return SRDIR;
+ }
+ return SRNOPE;
+}
--- /dev/null
+++ usr.bin/pcc/i386/code.c
@@ -0,0 +1,213 @@
+/* $Id: code.c,v 1.15 2007/07/06 17:02:27 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+# include "pass1.h"
+
+/*
+ * cause the alignment to become a multiple of n
+ * never called for text segment.
+ */
+void
+defalign(int n)
+{
+ n /= SZCHAR;
+ if (n == 1)
+ return;
+ printf(" .align %d\n", n);
+}
+
+/*
+ * define the current location as the name p->sname
+ * never called for text segment.
+ */
+void
+defnam(struct symtab *p)
+{
+ char *c = p->sname;
+
+#ifdef GCC_COMPAT
+ c = gcc_findname(p);
+#endif
+ if (p->sclass == EXTDEF)
+ printf(" .globl %s\n", c);
+ printf("%s:\n", c);
+}
+
+
+/*
+ * code for the end of a function
+ * deals with struct return here
+ */
+void
+efcode()
+{
+ NODE *p, *q;
+ int sz;
+
+ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ return;
+ /* address of return struct is in eax */
+ /* create a call to memcpy() */
+ /* will get the result in eax */
+ p = block(REG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ p->n_rval = EAX;
+ q = block(OREG, NIL, NIL, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ q->n_rval = EBP;
+ q->n_lval = 8; /* return buffer offset */
+ p = block(CM, q, p, INT, 0, MKSUE(INT));
+ sz = (tsize(STRTY, cftnsp->sdf, cftnsp->ssue)+SZCHAR-1)/SZCHAR;
+ p = block(CM, p, bcon(sz), INT, 0, MKSUE(INT));
+ p->n_right->n_name = "";
+ p = block(CALL, bcon(0), p, CHAR+PTR, 0, MKSUE(CHAR+PTR));
+ p->n_left->n_name = "memcpy";
+ p = clocal(p);
+ send_passt(IP_NODE, p);
+}
+
+/*
+ * code for the beginning of a function; a is an array of
+ * indices in symtab for the arguments; n is the number
+ */
+void
+bfcode(struct symtab **a, int n)
+{
+ int i;
+
+ if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
+ return;
+ /* Function returns struct, adjust arg offset */
+ for (i = 0; i < n; i++)
+ a[i]->soffset += SZPOINT(INT);
+}
+
+
+/*
+ * by now, the automatics and register variables are allocated
+ */
+void
+bccode()
+{
+ SETOFF(autooff, SZINT);
+}
+
+/* called just before final exit */
+/* flag is 1 if errors, 0 if none */
+void
+ejobcode(int flag )
+{
+}
+
+void
+bjobcode()
+{
+}
+
+/*
+ * Print character t at position i in one string, until t == -1.
+ * Locctr & label is already defined.
+ */
+void
+bycode(int t, int i)
+{
+ static int lastoctal = 0;
+
+ /* put byte i+1 in a string */
+
+ if (t < 0) {
+ if (i != 0)
+ puts("\"");
+ } else {
+ if (i == 0)
+ printf("\t.ascii \"");
+ if (t == '\\' || t == '"') {
+ lastoctal = 0;
+ putchar('\\');
+ putchar(t);
+ } else if (t < 040 || t >= 0177) {
+ lastoctal++;
+ printf("\\%o",t);
+ } else if (lastoctal && '0' <= t && t <= '9') {
+ lastoctal = 0;
+ printf("\"\n\t.ascii \"%c", t);
+ } else {
+ lastoctal = 0;
+ putchar(t);
+ }
+ }
+}
+
+/*
+ * n integer words of zeros
+ */
+void
+zecode(int n)
+{
+ printf(" .zero %d\n", n * (SZINT/SZCHAR));
+// inoff += n * SZINT;
+}
+
+/*
+ * return the alignment of field of type t
+ */
+int
+fldal(unsigned int t)
+{
+ uerror("illegal field type");
+ return(ALINT);
+}
+
+/* fix up type of field p */
+void
+fldty(struct symtab *p)
+{
+}
+
+/* p points to an array of structures, each consisting
+ * of a constant value and a label.
+ * The first is >=0 if there is a default label;
+ * its value is the label number
+ * The entries p[1] to p[n] are the nontrivial cases
+ * XXX - fix genswitch.
+ */
+void
+genswitch(int num, struct swents **p, int n)
+{
+ NODE *r;
+ int i;
+
+ /* simple switch code */
+ for (i = 1; i <= n; ++i) {
+ /* already in 1 */
+ r = tempnode(num, INT, 0, MKSUE(INT));
+ r = buildtree(NE, r, bcon(p[i]->sval));
+ cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
+ }
+ if (p[0]->slab > 0)
+ branch(p[0]->slab);
+}
--- /dev/null
+++ usr.bin/pcc/i386/local.c
@@ -0,0 +1,743 @@
+/* $Id: local.c,v 1.56 2007/09/24 16:23:36 ragge Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge at 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.
+ */
+
+
+#include "pass1.h"
+
+/* this file contains code which is dependent on the target machine */
+
+/* clocal() is called to do local transformations on
+ * an expression tree preparitory to its being
+ * written out in intermediate code.
+ *
+ * the major essential job is rewriting the
+ * automatic variables and arguments in terms of
+ * REG and OREG nodes
+ * conversion ops which are not necessary are also clobbered here
+ * in addition, any special features (such as rewriting
+ * exclusive or) are easily handled here as well
+ */
+NODE *
+clocal(NODE *p)
+{
+
+ register struct symtab *q;
+ register NODE *r, *l;
+ register int o;
+ register int m;
+ TWORD t;
+
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal: %p\n", p);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ switch( o = p->n_op ){
+
+ case NAME:
+ if ((q = p->n_sp) == NULL)
+ return p; /* Nothing to care about */
+
+ switch (q->sclass) {
+
+ case PARAM:
+ case AUTO:
+ /* fake up a structure reference */
+ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0);
+ r->n_lval = 0;
+ r->n_rval = FPREG;
+ p = stref(block(STREF, r, p, 0, 0, 0));
+ break;
+
+ case STATIC:
+ if (q->slevel == 0)
+ break;
+ p->n_lval = 0;
+ p->n_sp = q;
+ break;
+
+ case REGISTER:
+ p->n_op = REG;
+ p->n_lval = 0;
+ p->n_rval = q->soffset;
+ break;
+
+ }
+ break;
+
+ case STCALL:
+ case CALL:
+ /* Fix function call arguments. On x86, just add funarg */
+ for (r = p->n_right; r->n_op == CM; r = r->n_left) {
+ if (r->n_right->n_op != STARG &&
+ r->n_right->n_op != FUNARG)
+ r->n_right = block(FUNARG, r->n_right, NIL,
+ r->n_right->n_type, r->n_right->n_df,
+ r->n_right->n_sue);
+ }
+ if (r->n_op != STARG && r->n_op != FUNARG) {
+ l = talloc();
+ *l = *r;
+ r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type;
+ }
+ break;
+
+ case CBRANCH:
+ l = p->n_left;
+
+ /*
+ * Remove unneccessary conversion ops.
+ */
+ if (clogop(l->n_op) && l->n_left->n_op == SCONV) {
+ if (coptype(l->n_op) != BITYPE)
+ break;
+ if (l->n_right->n_op == ICON) {
+ r = l->n_left->n_left;
+ if (r->n_type >= FLOAT && r->n_type <= LDOUBLE)
+ break;
+ /* Type must be correct */
+ t = r->n_type;
+ nfree(l->n_left);
+ l->n_left = r;
+ l->n_type = t;
+ l->n_right->n_type = t;
+ }
+ }
+ break;
+
+ case PCONV:
+ /* Remove redundant PCONV's. Be careful */
+ l = p->n_left;
+ if (l->n_op == ICON) {
+ l->n_lval = (unsigned)l->n_lval;
+ goto delp;
+ }
+ if (l->n_type < INT || l->n_type == LONGLONG ||
+ l->n_type == ULONGLONG) {
+ /* float etc? */
+ p->n_left = block(SCONV, l, NIL,
+ UNSIGNED, 0, MKSUE(UNSIGNED));
+ break;
+ }
+ /* if left is SCONV, cannot remove */
+ if (l->n_op == SCONV)
+ break;
+
+ /* avoid ADDROF TEMP */
+ if (l->n_op == ADDROF && l->n_left->n_op == TEMP)
+ break;
+
+ /* if conversion to another pointer type, just remove */
+ if (p->n_type > BTMASK && l->n_type > BTMASK)
+ goto delp;
+ break;
+
+ delp: l->n_type = p->n_type;
+ l->n_qual = p->n_qual;
+ l->n_df = p->n_df;
+ l->n_sue = p->n_sue;
+ nfree(p);
+ p = l;
+ break;
+
+ case SCONV:
+ l = p->n_left;
+
+ if (p->n_type == l->n_type) {
+ nfree(p);
+ return l;
+ }
+
+ if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 &&
+ btdims[p->n_type].suesize == btdims[l->n_type].suesize) {
+ if (p->n_type != FLOAT && p->n_type != DOUBLE &&
+ l->n_type != FLOAT && l->n_type != DOUBLE &&
+ l->n_type != LDOUBLE && p->n_type != LDOUBLE) {
+ if (l->n_op == NAME || l->n_op == UMUL ||
+ l->n_op == TEMP) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+ }
+ }
+
+ if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT &&
+ coptype(l->n_op) == BITYPE) {
+ l->n_type = p->n_type;
+ nfree(p);
+ return l;
+ }
+
+ o = l->n_op;
+ m = p->n_type;
+
+ if (o == ICON) {
+ CONSZ val = l->n_lval;
+
+ if (!ISPTR(m)) /* Pointers don't need to be conv'd */
+ switch (m) {
+ case BOOL:
+ l->n_lval = l->n_lval != 0;
+ break;
+ case CHAR:
+ l->n_lval = (char)val;
+ break;
+ case UCHAR:
+ l->n_lval = val & 0377;
+ break;
+ case SHORT:
+ l->n_lval = (short)val;
+ break;
+ case USHORT:
+ l->n_lval = val & 0177777;
+ break;
+ case ULONG:
+ case UNSIGNED:
+ l->n_lval = val & 0xffffffff;
+ break;
+ case ENUMTY:
+ case MOETY:
+ case LONG:
+ case INT:
+ l->n_lval = (int)val;
+ break;
+ case LONGLONG:
+ l->n_lval = (long long)val;
+ break;
+ case ULONGLONG:
+ l->n_lval = val;
+ break;
+ case VOID:
+ break;
+ case LDOUBLE:
+ case DOUBLE:
+ case FLOAT:
+ l->n_op = FCON;
+ l->n_dcon = val;
+ break;
+ default:
+ cerror("unknown type %d", m);
+ }
+ l->n_type = m;
+ l->n_sue = MKSUE(m);
+ nfree(p);
+ return l;
+ }
+ if (DEUNSIGN(p->n_type) == SHORT &&
+ DEUNSIGN(l->n_type) == SHORT) {
+ nfree(p);
+ p = l;
+ }
+ if ((p->n_type == CHAR || p->n_type == UCHAR ||
+ p->n_type == SHORT || p->n_type == USHORT) &&
+ (l->n_type == FLOAT || l->n_type == DOUBLE ||
+ l->n_type == LDOUBLE)) {
+ p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue);
+ p->n_left->n_type = INT;
+ return p;
+ }
+ break;
+
+ case MOD:
+ case DIV:
+ if (o == DIV && p->n_type != CHAR && p->n_type != SHORT)
+ break;
+ if (o == MOD && p->n_type != CHAR && p->n_type != SHORT)
+ break;
+ /* make it an int division by inserting conversions */
+ p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT));
+ p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT));
+ p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type));
+ p->n_left->n_type = INT;
+ break;
+
+ case PMCONV:
+ case PVCONV:
+ if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0);
+ nfree(p);
+ return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right));
+
+ case FORCE:
+ /* put return value in return reg */
+ p->n_op = ASSIGN;
+ p->n_right = p->n_left;
+ p->n_left = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ p->n_left->n_rval = p->n_left->n_type == BOOL ?
+ RETREG(CHAR) : RETREG(p->n_type);
+ break;
+
+ case LS:
+ case RS:
+ /* shift count must be in a char
+ * unless longlong, where it must be int */
+ if (p->n_right->n_op == ICON)
+ break; /* do not do anything */
+ if (p->n_type == LONGLONG || p->n_type == ULONGLONG) {
+ if (p->n_right->n_type != INT)
+ p->n_right = block(SCONV, p->n_right, NIL,
+ INT, 0, MKSUE(INT));
+ break;
+ }
+ if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR)
+ break;
+ p->n_right = block(SCONV, p->n_right, NIL,
+ CHAR, 0, MKSUE(CHAR));
+ break;
+ }
+#ifdef PCC_DEBUG
+ if (xdebug) {
+ printf("clocal end: %p\n", p);
+ fwalk(p, eprint, 0);
+ }
+#endif
+ return(p);
+}
+
+void
+myp2tree(NODE *p)
+{
+}
+
+/*ARGSUSED*/
+int
+andable(NODE *p)
+{
+ return(1); /* all names can have & taken on them */
+}
+
+/*
+ * at the end of the arguments of a ftn, set the automatic offset
+ */
+void
+cendarg()
+{
+ autooff = AUTOINIT;
+}
+
+/*
+ * Return 1 if a variable of type type is OK to put in register.
+ */
+int
+cisreg(TWORD t)
+{
+ if (t == FLOAT || t == DOUBLE || t == LDOUBLE)
+ return 0; /* not yet */
+ return 1;
+}
+
+/*
+ * return a node, for structure references, which is suitable for
+ * being added to a pointer of type t, in order to be off bits offset
+ * into a structure
+ * t, d, and s are the type, dimension offset, and sizeoffset
+ * For pdp10, return the type-specific index number which calculation
+ * is based on its size. For example, short a[3] would return 3.
+ * Be careful about only handling first-level pointers, the following
+ * indirections must be fullword.
+ */
+NODE *
+offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue)
+{
+ register NODE *p;
+
+ if (xdebug)
+ printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
+ off, t, d, sue->suesize);
+
+ p = bcon(0);
+ p->n_lval = off/SZCHAR; /* Default */
+ return(p);
+}
+
+/*
+ * Allocate off bits on the stack. p is a tree that when evaluated
+ * is the multiply count for off, t is a storeable node where to write
+ * the allocated address.
+ */
+void
+spalloc(NODE *t, NODE *p, OFFSZ off)
+{
+ NODE *sp;
+
+ p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */
+
+ /* sub the size from sp */
+ sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT));
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ ecomp(buildtree(MINUSEQ, sp, p));
+
+ /* save the address of sp */
+ sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue);
+ sp->n_lval = 0;
+ sp->n_rval = STKREG;
+ t->n_type = sp->n_type;
+ ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */
+
+}
+
+#if 0
+/*
+ * Print out an integer constant of size size.
+ * can only be sizes <= SZINT.
+ */
+void
+indata(CONSZ val, int size)
+{
+ switch (size) {
+ case SZCHAR:
+ printf("\t.byte %d\n", (int)val & 0xff);
+ break;
+ case SZSHORT:
+ printf("\t.word %d\n", (int)val & 0xffff);
+ break;
+ case SZINT:
+ printf("\t.long %d\n", (int)val & 0xffffffff);
+ break;
+ default:
+ cerror("indata");
+ }
+}
+#endif
+
+/*
+ * Print out a string of characters.
+ * Assume that the assembler understands C-style escape
+ * sequences. Location is already set.
+ */
+void
+instring(char *str)
+{
+ char *s;
+
+ /* be kind to assemblers and avoid long strings */
+ printf("\t.ascii \"");
+ for (s = str; *s != 0; ) {
+ if (*s++ == '\\') {
+ (void)esccon(&s);
+ }
+ if (s - str > 64) {
+ fwrite(str, 1, s - str, stdout);
+ printf("\"\n\t.ascii \"");
+ str = s;
+ }
+ }
+ fwrite(str, 1, s - str, stdout);
+ printf("\\0\"\n");
+}
+
+static int inbits, inval;
+
+/*
+ * set fsz bits in sequence to zero.
+ */
+void
+zbits(OFFSZ off, int fsz)
+{
+ int m;
+
+ if (idebug)
+ printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits);
+ if ((m = (inbits % SZCHAR))) {
+ m = SZCHAR - m;
+ if (fsz < m) {
+ inbits += fsz;
+ return;
+ } else {
+ fsz -= m;
+ printf("\t.byte %d\n", inval);
+ inval = inbits = 0;
+ }
+ }
+ if (fsz >= SZCHAR) {
+ printf("\t.zero %d\n", fsz/SZCHAR);
+ fsz -= (fsz/SZCHAR) * SZCHAR;
+ }
+ if (fsz) {
+ inval = 0;
+ inbits = fsz;
+ }
+}
+
+/*
+ * Initialize a bitfield.
+ */
+void
+infld(CONSZ off, int fsz, CONSZ val)
+{
+ if (idebug)
+ printf("infld off %lld, fsz %d, val %lld inbits %d\n",
+ off, fsz, val, inbits);
+ val &= ((CONSZ)1 << fsz)-1;
+ while (fsz + inbits >= SZCHAR) {
+ inval |= (val << inbits);
+ printf("\t.byte %d\n", inval & 255);
+ fsz -= (SZCHAR - inbits);
+ val >>= (SZCHAR - inbits);
+ inval = inbits = 0;
+ }
+ if (fsz) {
+ inval |= (val << inbits);
+ inbits += fsz;
+ }
+}
+
+/*
+ * print out a constant node, may be associated with a label.
+ * Do not free the node after use.
+ * off is bit offset from the beginning of the aggregate
+ * fsz is the number of bits this is referring to
+ */
+void
+ninval(CONSZ off, int fsz, NODE *p)
+{
+ union { float f; double d; long double l; int i[3]; } u;
+ struct symtab *q;
+ TWORD t;
+ int i;
+
+ t = p->n_type;
+ if (t > BTMASK)
+ t = INT; /* pointer */
+
+ if (p->n_op != ICON && p->n_op != FCON)
+ cerror("ninval: init node not constant");
+
+ if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT)
+ uerror("element not constant");
+
+ switch (t) {
+ case LONGLONG:
+ case ULONGLONG:
+ i = (p->n_lval >> 32);
+ p->n_lval &= 0xffffffff;
+ p->n_type = INT;
+ ninval(off, 32, p);
+ p->n_lval = i;
+ ninval(off+32, 32, p);
+ break;
+ case INT:
+ case UNSIGNED:
+ printf("\t.long 0x%x", (int)p->n_lval);
+ if ((q = p->n_sp) != NULL) {
+ if ((q->sclass == STATIC && q->slevel > 0) ||
+ q->sclass == ILABEL) {
+ printf("+" LABFMT, q->soffset);
+ } else
+ printf("+%s", exname(q->sname));
+ }
+ printf("\n");
+ break;
+ case SHORT:
+ case USHORT:
+ printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff);
+ break;
+ case BOOL:
+ if (p->n_lval > 1)
+ p->n_lval = p->n_lval != 0;
+ /* FALLTHROUGH */
+ case CHAR:
+ case UCHAR:
+ printf("\t.byte %d\n", (int)p->n_lval & 0xff);
+ break;
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
+ break;
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ printf("\t.long\t0x%x\n", u.i[0]);
+ break;
+ default:
+ cerror("ninval");
+ }
+}
+
+#if 0
+/*
+ * print out an integer.
+ */
+void
+inval(CONSZ word)
+{
+ word &= 0xffffffff;
+ printf(" .long 0x%llx\n", word);
+}
+
+/* output code to initialize a floating point value */
+/* the proper alignment has been obtained */
+void
+finval(NODE *p)
+{
+ union { float f; double d; long double l; int i[3]; } u;
+
+ switch (p->n_type) {
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x,0x%x\n", u.i[0], u.i[1], u.i[2]);
+ break;
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]);
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ printf("\t.long\t0x%x\n", u.i[0]);
+ break;
+ }
+}
+#endif
+
+/* make a name look like an external name in the local machine */
+char *
+exname(char *p)
+{
+ if (p == NULL)
+ return "";
+ return p;
+}
+
+/*
+ * map types which are not defined on the local machine
+ */
+TWORD
+ctype(TWORD type)
+{
+ switch (BTYPE(type)) {
+ case LONG:
+ MODTYPE(type,INT);
+ break;
+
+ case ULONG:
+ MODTYPE(type,UNSIGNED);
+
+ }
+ return (type);
+}
+
+void
+calldec(NODE *p, NODE *q)
+{
+}
+
+void
+extdec(struct symtab *q)
+{
+}
+
+/* make a common declaration for id, if reasonable */
+void
+commdec(struct symtab *q)
+{
+ int off;
+
+ off = tsize(q->stype, q->sdf, q->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+#ifdef GCC_COMPAT
+ printf(" .comm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .comm %s,0%o\n", exname(q->sname), off);
+#endif
+}
+
+/* make a local common declaration for id, if reasonable */
+void
+lcommdec(struct symtab *q)
+{
+ int off;
+
+ off = tsize(q->stype, q->sdf, q->ssue);
+ off = (off+(SZCHAR-1))/SZCHAR;
+ if (q->slevel == 0)
+#ifdef GCC_COMPAT
+ printf(" .lcomm %s,0%o\n", gcc_findname(q), off);
+#else
+ printf(" .lcomm %s,0%o\n", exname(q->sname), off);
+#endif
+ else
+ printf(" .lcomm " LABFMT ",0%o\n", q->soffset, off);
+}
+
+/*
+ * print a (non-prog) label.
+ */
+void
+deflab1(int label)
+{
+ printf(LABFMT ":\n", label);
+}
+
+static char *loctbl[] = { "text", "data", "section .rodata", "section .rodata" };
+
+void
+setloc1(int locc)
+{
+ if (locc == lastloc)
+ return;
+ lastloc = locc;
+ printf(" .%s\n", loctbl[locc]);
+}
+
+#if 0
+int
+ftoint(NODE *p, CONSZ **c)
+{
+ static CONSZ cc[3];
+ union { float f; double d; long double l; int i[3]; } u;
+ int n;
+
+ switch (p->n_type) {
+ case LDOUBLE:
+ u.i[2] = 0;
+ u.l = (long double)p->n_dcon;
+ n = SZLDOUBLE;
+ break;
+ case DOUBLE:
+ u.d = (double)p->n_dcon;
+ n = SZDOUBLE;
+ break;
+ case FLOAT:
+ u.f = (float)p->n_dcon;
+ n = SZFLOAT;
+ break;
+ }
+ cc[0] = u.i[0];
+ cc[1] = u.i[1];
+ cc[2] = u.i[2];
+ *c = cc;
+ return n;
+}
+#endif
More information about the Midnightbsd-cvs
mailing list