+2003-11-06 Erik Petrich <epetrich@ivorytower.norman.ok.us>
+
+ * src/port.h,
+ * src/hc08/main.c,
+ * src/mcs51/main.c,
+ * src/ds390/main.c,
+ * src/z80/main.c,
+ * src/avr/main.c,
+ * src/pic/main.c,
+ * src/pic16/main.c,
+ * src/xa51/main.c: added hasExtBitOp & oclsExpense functions to ports
+ * src/SDCCicode.c: changed several IS_FARSPACE tests to isOclsExpensive
+ tests (which uses the port's oclsExpense function)
+ * src/SDCC.y,
+ * src/SDCCast.c,
+ * src/SDCCicode.c,
+ * src/hc08/gen.c,
+ * src/ds390/gen.c,
+ * src/mcs51/gen.c: added support for the SWAP iCode (RFE #834167)
+
2003-11-04 Erik Petrich <epetrich@ivorytower.norman.ok.us>
* src/SDCCcse.c (ifxOptimize),
%token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE
%token RRC RLC
%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
-%token DUMMY_READ_VOLATILE ENDCRITICAL
+%token DUMMY_READ_VOLATILE ENDCRITICAL SWAP
%type <yyint> Interrupt_storage
%type <sym> identifier declarator declarator2 enumerator_list enumerator
static ast *createIvalCharPtr (ast *, sym_link *, ast *);
static ast *optimizeCompare (ast *);
ast *optimizeRRCRLC (ast *);
+ast *optimizeSWAP (ast *);
ast *optimizeGetHbit (ast *);
ast *backPatchLabels (ast *, symbol *, symbol *);
void PA(ast *t);
case RRC:
case RLC:
case GETHBIT:
+ case SWAP:
if (IS_AST_SYM_VALUE (pbody->left) &&
isSymbolEqual (AST_SYMBOL (pbody->left), sym))
return FALSE;
ast *wtree = optimizeRRCRLC (tree);
if (wtree != tree)
return decorateType (wtree);
+
+ wtree = optimizeSWAP (tree);
+ if (wtree != tree)
+ return decorateType (wtree);
+
// fall through
}
/*----------------------------*/
case RRC:
case RLC:
+ case SWAP:
TTYPE (tree) = LTYPE (tree);
TETYPE (tree) = LETYPE (tree);
return tree;
if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
(j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
return tree;
+
+ /* make sure the port supports GETHBIT */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+ return tree;
return decorateType (newNode (GETHBIT, tree->left->left, NULL));
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext0;
+ /* make sure the port supports RLC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RLC, root->left->left, NULL);
}
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext1;
+ /* make sure the port supports RLC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RLC, root->left->left, NULL);
(getSize (TTYPE (root->left->left)) * 8 - 1))
goto tryNext2;
+ /* make sure the port supports RRC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RRC, root->left->left, NULL);
(getSize (TTYPE (root->left->left)) * 8 - 1))
return root;
+ /* make sure the port supports RRC */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
+ return root;
+
/* whew got the first case : create the AST */
return newNode (RRC, root->left->left, NULL);
return root;
}
+/*-----------------------------------------------------------------*/
+/* optimizeSWAP :- optimize for nibble/byte/word swaps */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeSWAP (ast * root)
+{
+ /* will look for trees of the form
+ (?expr << 4) | (?expr >> 4) or
+ (?expr >> 4) | (?expr << 4) will make that
+ into a SWAP : operation ..
+ note : by 4 I mean (number of bits required to hold the
+ variable /2 ) */
+ /* if the root operations is not a | operation the not */
+ if (!IS_BITOR (root))
+ return root;
+
+ /* (?expr << 4) | (?expr >> 4) */
+ if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
+ || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
+ {
+
+ if (!SPEC_USIGN (TETYPE (root->left->left)))
+ return root;
+
+ if (!IS_AST_LIT_VALUE (root->left->right) ||
+ !IS_AST_LIT_VALUE (root->right->right))
+ return root;
+
+ /* make sure it is the same expression */
+ if (!isAstEqual (root->left->left,
+ root->right->left))
+ return root;
+
+ if (AST_LIT_VALUE (root->left->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
+
+ if (AST_LIT_VALUE (root->right->right) !=
+ (getSize (TTYPE (root->left->left)) * 4))
+ return root;
+
+ /* make sure the port supports SWAP */
+ if (port->hasExtBitOp
+ && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
+ return root;
+
+ /* found it : create the AST */
+ return newNode (SWAP, root->left->left, NULL);
+ }
+
+
+ /* not found return root */
+ return root;
+}
+
/*-----------------------------------------------------------------*/
/* optimizeCompare - otimizes compares for bit variables */
/*-----------------------------------------------------------------*/
fprintf(outfile,")\n");
ast_print(tree->left,outfile,indent+2);
return ;
+ case SWAP:
+ fprintf(outfile,"SWAP (%p) type (",tree);
+ printTypeChain(tree->ftype,outfile);
+ fprintf(outfile,")\n");
+ ast_print(tree->left,outfile,indent+2);
+ return ;
case GETHBIT:
fprintf(outfile,"GETHBIT (%p) type (",tree);
printTypeChain(tree->ftype,outfile);
return FALSE;
}
+/*-----------------------------------------------------------------*/
+/* isOclsExpensive - will return true if accesses to an output */
+/* storage class are expensive */
+/*-----------------------------------------------------------------*/
+bool
+isOclsExpensive (struct memmap *oclass)
+{
+ if (port->oclsExpense)
+ return port->oclsExpense (oclass) > 0;
+
+ /* In the absence of port specific guidance, assume only */
+ /* farspace is expensive. */
+ return IN_FARSPACE (oclass);
+}
+
/*-----------------------------------------------------------------*/
/* operandLitValue - literal value of an operand */
/*-----------------------------------------------------------------*/
register equivalent for a local symbol */
if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
(IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+ !TARGET_IS_HC08 &&
(!(options.model == MODEL_FLAT24)) ) &&
options.stackAuto == 0)
ok = 0;
/* if this is not a temp symbol then */
if (!IS_ITEMP (op) &&
!force &&
- !IN_FARSPACE (SPEC_OCLS (etype)))
+ !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
{
op = operandFromOperand (op);
op->isaddr = 0;
if (IS_SPEC (type) &&
IS_TRUE_SYMOP (op) &&
- (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+ (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
(options.model == MODEL_FLAT24) ))
{
op = operandFromOperand (op);
else if (compareType (ltype, rtype) < 0)
right = geniCodeCast (ltype, right, TRUE);
- /* if left is a true symbol & ! volatile
+ /* If left is a true symbol & ! volatile
create an assignment to temporary for
the right & then assign this temporary
- to the symbol this is SSA . isn't it simple
- and folks have published mountains of paper on it */
+ to the symbol. This is SSA (static single
+ assignment). Isn't it simple and folks have
+ published mountains of paper on it */
if (IS_TRUE_SYMOP (left) &&
!isOperandVolatile (left, FALSE) &&
isOperandGlobal (left))
if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
{
- if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+ if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
options.stackAuto == 0 &&
(!(options.model == MODEL_FLAT24)) )
{
case '~':
case RRC:
case RLC:
+ case SWAP:
return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
case '!':
return TRUE;
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ || op == GETHBIT
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
NULL,
NULL,
NULL,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
freeAsmop (result, NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+ operand *left, *result;
+
+ D(emitcode ("; genSwap",""));
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, AOP_USESDPTR(left));
+
+ _startLazyDPSEvaluation ();
+ switch (AOP_SIZE (left))
+ {
+ case 1: /* swap nibbles in byte */
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ emitcode ("swap", "a");
+ aopPut (AOP (result), "a", 0);
+ break;
+ case 2: /* swap bytes in word */
+ if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+ aopPut (AOP (result), "a", 1);
+ }
+ else if (operandsEqu (left, result))
+ {
+ char * reg = "a";
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+ if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
+ {
+ emitcode ("mov", "b,a");
+ reg = "b";
+ _G.bInUse=1;
+ }
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+ aopPut (AOP (result), reg, 1);
+ _G.bInUse=0;
+ }
+ else
+ {
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
+ aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
+ }
+ break;
+ default:
+ wassertl(FALSE, "unsupported SWAP operand size");
+ }
+ _endLazyDPSEvaluation ();
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
/*-----------------------------------------------------------------*/
/* AccRol - rotate left accumulator by known count */
/*-----------------------------------------------------------------*/
case ENDCRITICAL:
genEndCritical (ic);
break;
+
+ case SWAP:
+ genSwap (ic);
+ break;
#if 0 // obsolete, and buggy for != xdata
case ARRAYINIT:
return FALSE; // #STUB
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ || op == GETHBIT
+ || (op == SWAP && size <= 2)
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
/** $1 is always the basename.
$2 is always the output file.
NULL,
NULL,
_ds390_nativeMulCheck,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
NULL,
NULL,
NULL,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
NULL,
NULL,
_ds390_nativeMulCheck,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
emitcode ("rola", "");
hc08_dirtyReg (hc08_reg_a, FALSE);
storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+ hc08_freeReg (hc08_reg_a);
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+ operand *left, *result;
+
+ D(emitcode ("; genSwap",""));
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+ switch (AOP_SIZE (left))
+ {
+ case 1: /* swap nibbles in byte */
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ emitcode ("nsa", "");
+ hc08_dirtyReg (hc08_reg_a, FALSE);
+ storeRegToAop (hc08_reg_a, AOP (result), 0);
+ hc08_freeReg (hc08_reg_a);
+ break;
+ case 2: /* swap bytes in a word */
+ if (operandsEqu (left, result))
+ {
+ loadRegFromAop (hc08_reg_a, AOP (left), 0);
+ hc08_useReg (hc08_reg_a);
+ transferAopAop (AOP (left), 1, AOP (result), 0);
+ storeRegToAop (hc08_reg_a, AOP (result), 1);
+ hc08_freeReg (hc08_reg_a);
+ }
+ else
+ {
+ transferAopAop (AOP (left), 0, AOP (result), 1);
+ transferAopAop (AOP (left), 1, AOP (result), 0);
+ }
+ break;
+ default:
+ wassertl(FALSE, "unsupported SWAP operand size");
+ }
+
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
case ENDCRITICAL:
genEndCritical (ic);
break;
+
+ case SWAP:
+ genSwap (ic);
+ break;
default:
ic = ic;
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ || op == GETHBIT
+ || (op == SWAP && size <= 2)
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ /* The hc08's addressing modes allow access to all storage classes */
+ /* inexpensively (<=0) */
+
+ if (IN_DIRSPACE (oclass)) /* direct addressing mode is fastest */
+ return -2;
+ if (IN_FARSPACE (oclass)) /* extended addressing mode is almost at fast */
+ return -1;
+ if (oclass == istack) /* stack is the slowest, but still faster than */
+ return 0; /* trying to copy to a temp location elsewhere */
+
+ return 0; /* anything we missed */
+}
+
+
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
NULL, /* process_pragma */
NULL, /* getMangledFunctionName */
NULL, /* hasNativeMulFor */
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
TRUE, /* use_dw_for_init */
FALSE, /* little endian */
0, /* leave lt */
freeAsmop (result, NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* genSwap - generates code to swap nibbles or bytes */
+/*-----------------------------------------------------------------*/
+static void
+genSwap (iCode * ic)
+{
+ operand *left, *result;
+
+ D(emitcode ("; genSwap",""));
+
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE);
+ aopOp (result, ic, FALSE);
+
+ switch (AOP_SIZE (left))
+ {
+ case 1: /* swap nibbles in byte */
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ emitcode ("swap", "a");
+ aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+ break;
+ case 2: /* swap bytes in word */
+ if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
+ {
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+ 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
+ }
+ else if (operandsEqu (left, result))
+ {
+ char * reg = "a";
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
+ {
+ emitcode ("mov", "b,a");
+ reg = "b";
+ }
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+ 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
+ }
+ else
+ {
+ aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
+ 0, isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
+ 1, isOperandVolatile (result, FALSE));
+ }
+ break;
+ default:
+ wassertl(FALSE, "unsupported SWAP operand size");
+ }
+
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+}
+
+
/*-----------------------------------------------------------------*/
/* AccRol - rotate left accumulator by known count */
/*-----------------------------------------------------------------*/
genEndCritical (ic);
break;
+ case SWAP:
+ genSwap (ic);
+ break;
+
default:
ic = ic;
}
return 1;
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ || op == GETHBIT
+ || (op == SWAP && size <= 2)
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
NULL,
NULL,
NULL,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
*/
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ /* The IN_FARSPACE test is compatible with historical behaviour, */
+ /* but I don't think it is applicable to PIC. If so, please feel */
+ /* free to remove this test -- EEP */
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
_process_pragma, /* process a pragma */
NULL,
_hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
*/
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ /* The IN_FARSPACE test is compatible with historical behaviour, */
+ /* but I don't think it is applicable to PIC. If so, please feel */
+ /* free to remove this test -- EEP */
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
_process_pragma, /* process a pragma */
NULL,
_hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
*/
bool (*hasNativeMulFor) (iCode *ic, sym_link *left, sym_link *right);
+ /** Returns true if the port has implemented certain bit
+ manipulation iCodes (RRC, RLC, SWAP, GETHBIT)
+ */
+ bool (*hasExtBitOp) (int op, int size);
+
+ /** Returns the relative expense of accessing a particular output
+ storage class. Larger values indicate higher expense.
+ */
+ int (*oclsExpense) (struct memmap *oclass);
+
/** If TRUE, then tprintf and !dw will be used for some initalisers
*/
bool use_dw_for_init;
return 1;
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == RRC
+ || op == RLC
+ || op == GETHBIT
+ )
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
NULL, // process_pragma()
NULL, // getMangledFunctionName()
NULL, // hasNativeMulFor()
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
TRUE, // use_dw_for_init
TRUE, /* little endian */
0, /* leave lt */
return FALSE;
}
+/* Indicate which extended bit operations this port supports */
+static bool
+hasExtBitOp (int op, int size)
+{
+ if (op == GETHBIT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Indicate the expense of an access to an output storage class */
+static int
+oclsExpense (struct memmap *oclass)
+{
+ if (IN_FARSPACE(oclass))
+ return 1;
+
+ return 0;
+}
+
#define LINKCMD "link-{port} -nf {dstfilename}"
/*
_process_pragma,
_mangleSupportFunctionName,
_hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
TRUE,
TRUE, /* little endian */
0, /* leave lt */
_process_pragma,
_mangleSupportFunctionName,
_hasNativeMulFor,
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
TRUE,
TRUE, /* little endian */
0, /* leave lt */