Merge pull request #208 from kernigh/kernigh-data8

8-byte long long in ACK C for i386, m68020
This commit is contained in:
David Given 2019-10-07 22:56:13 +02:00 committed by GitHub
commit 9cee18f9d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 2654 additions and 386 deletions

View file

@ -55,6 +55,7 @@
#define SZ_WORD 4
#define SZ_INT 4
#define SZ_LONG 4
#define SZ_LNGLNG -1
#define SZ_FLOAT 4
#define SZ_DOUBLE 8
#define SZ_LNGDBL 8 /* for now */
@ -66,6 +67,7 @@
#define AL_WORD SZ_WORD
#define AL_INT SZ_WORD
#define AL_LONG SZ_WORD
#define AL_LNGLNG SZ_WORD
#define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD
@ -115,11 +117,6 @@
/*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */
!File: spec_arith.h
/* describes internal compiler arithmetics */
#undef SPECIAL_ARITHMETICS /* something different from native long */
!File: static.h
#define GSTATIC /* for large global "static" arrays */

View file

@ -17,6 +17,7 @@
#include "Lpars.h"
#include "class.h"
#include "sizes.h"
#include "type.h" /* no_long_long() */
#include "error.h"
#include "domacro.h"
#include "specials.h" /* registration of special identifiers */
@ -37,7 +38,6 @@ int LexSave = 0; /* last character read by GetChar */
#define FLG_ESEEN 0x01 /* possibly a floating point number */
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */
extern arith full_mask[];
#ifdef LINT
extern int lint_skip_comment;
@ -594,10 +594,12 @@ static void strflt2tok(char fltbuf[], struct token* ptok)
static void strint2tok(char intbuf[], struct token* ptok)
{
register char* cp = intbuf;
int base = 10;
arith val = 0, dig, ubound;
int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
int fund;
int base = 10, dig;
unsigned writh val = 0, ubound;
int uns_flg = 0, lng_flg = 0, lnglng_flg = 0;
int malformed = 0, ovfl = 0;
unsigned writh uint_mask, ulng_mask, ulnglng_mask;
int cut, fund;
assert(*cp != '-');
if (*cp == '0')
@ -611,11 +613,8 @@ static void strint2tok(char intbuf[], struct token* ptok)
else
base = 8;
}
/* The upperbound will be the same as when computed with
* max_unsigned_arith / base (since base is even). The problem here
* is that unsigned arith is not accepted by all compilers.
*/
ubound = max_arith / (base / 2);
/* The upperbound checks if val * base would overflow. */
ubound = ~(unsigned writh)0 / base;
while (is_hex(*cp))
{
@ -626,10 +625,10 @@ static void strint2tok(char intbuf[], struct token* ptok)
}
else
{
if (val < 0 || val > ubound)
if (val > ubound)
ovfl++;
val *= base;
if (val < 0 && val + dig >= 0)
if (val > val + dig)
ovfl++;
val += dig;
}
@ -639,7 +638,16 @@ static void strint2tok(char intbuf[], struct token* ptok)
while (*cp)
{
if (*cp == 'l' || *cp == 'L')
lng_flg++;
{
if (*cp == *(cp + 1))
{
/* 'll' or 'LL' */
lnglng_flg++;
cp++;
}
else
lng_flg++;
}
else if (*cp == 'u' || *cp == 'U')
uns_flg++;
else
@ -658,51 +666,83 @@ static void strint2tok(char intbuf[], struct token* ptok)
}
else
{
if (lng_flg > 1)
if (lng_flg + lnglng_flg > 1)
lexerror("only one long suffix allowed");
if (uns_flg > 1)
lexerror("only one unsigned suffix allowed");
}
/* Get masks like 0XFFFF, 0XFFFFFFFF as unsigned values. */
uint_mask = (unsigned writh)full_mask[(int)int_size];
ulng_mask = (unsigned writh)full_mask[(int)long_size];
if (lnglng_size < 0)
ulnglng_mask = 0;
else
ulnglng_mask = (unsigned writh)full_mask[(int)lnglng_size];
/* If a decimal literal with no suffix is too big for int
and long, then C89 tries unsigned long, but C99 tries
long long (WG14, Rationale for C99, C99RationaleV5.10.pdf,
6.4.4.1 Integer constants).
This compiler follows C89 when the literal has no
long long suffix.
*/
cut = 0;
if (ovfl)
{
lexwarning("overflow in constant");
fund = ULONG;
cut = 1; /* cut the size of the constant */
}
else if (!lng_flg && (val & full_mask[(int)int_size]) == val)
else if (!lng_flg && !lnglng_flg && (val & uint_mask) == val)
{
if (val >= 0 && val <= max_int)
{
if ((val & (uint_mask >> 1)) == val)
fund = INT;
}
else if (int_size == long_size)
{
fund = UNSIGNED;
}
else if (base == 10 && !uns_flg)
fund = LONG;
{
if ((val & (ulng_mask >> 1)) == val)
fund = LONG;
else
fund = ULONG;
}
else
fund = UNSIGNED;
}
else if ((val & full_mask[(int)long_size]) == val)
else if (!lnglng_flg && (val & ulng_mask) == val)
{
if (val >= 0)
if ((val & (ulng_mask >> 1)) == val)
fund = LONG;
else
fund = ULONG;
}
else
{ /* sizeof(arith) is greater than long_size */
assert(arith_size > long_size);
lexwarning("constant too large for target machine");
/* cut the size to prevent further complaints */
val &= full_mask[(int)long_size];
fund = ULONG;
}
if (lng_flg)
else if (lnglng_flg && (val & ulnglng_mask) == val)
{
/* fund can't be INT */
if (fund == UNSIGNED)
if ((val & (ulnglng_mask >> 1)) == val)
fund = LNGLNG;
else
fund = ULNGLNG;
}
else if (lnglng_flg && no_long_long())
fund = ERRONEOUS;
else
{
assert(sizeof(val) > long_size ||
(lnglng_size >= 0 && sizeof(val) > lnglng_size));
lexwarning("constant too large for target machine");
cut = 1;
}
if (cut)
{
/* cut the size to prevent further complaints */
if (lnglng_flg)
{
fund = ULNGLNG;
val &= ulnglng_mask;
}
else
{
fund = ULONG;
val &= ulng_mask;
}
}
if (uns_flg)
{
@ -710,7 +750,9 @@ static void strint2tok(char intbuf[], struct token* ptok)
fund = UNSIGNED;
else if (fund == LONG)
fund = ULONG;
else if (fund == LNGLNG)
fund = ULNGLNG;
}
ptok->tk_fund = fund;
ptok->tk_ival = val;
ptok->tk_ival = (writh)val;
}

View file

@ -26,7 +26,7 @@ struct token {
char *tok_bts; /* row of bytes */
int tok_len; /* length of row of bytes */
} tok_string;
arith tok_ival; /* for INTEGER */
writh tok_ival; /* for INTEGER */
char *tok_fval; /* for FLOATING */
} tok_data;
};

View file

@ -55,6 +55,7 @@
#define SZ_WORD 4
#define SZ_INT 4
#define SZ_LONG 4
#define SZ_LNGLNG -1
#define SZ_FLOAT 4
#define SZ_DOUBLE 8
#define SZ_LNGDBL 8 /* for now */
@ -66,6 +67,7 @@
#define AL_WORD SZ_WORD
#define AL_INT SZ_WORD
#define AL_LONG SZ_WORD
#define AL_LNGLNG SZ_WORD
#define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD
@ -115,11 +117,6 @@
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
!File: spec_arith.h
/* describes internal compiler arithmetics */
#undef SPECIAL_ARITHMETICS /* something different from native long */
!File: static.h
#define GSTATIC /* for large global "static" arrays */

View file

@ -10,6 +10,7 @@
#ifndef NOCROSS
extern int
short_align, word_align, int_align, long_align,
lnglng_align,
float_align, double_align, lngdbl_align,
pointer_align,
struct_align, union_align;
@ -18,6 +19,7 @@ extern int
#define word_align ((int)AL_WORD)
#define int_align ((int)AL_INT)
#define long_align ((int)AL_LONG)
#define lnglng_align ((int)AL_LNGLNG)
#define float_align ((int)AL_FLOAT)
#define double_align ((int)AL_DOUBLE)
#define lngdbl_align ((int)AL_LNGDBL)

View file

@ -12,6 +12,7 @@
*/
#include <assert.h>
#include <stddef.h>
#include "parameters.h"
#include <alloc.h>
#include <flt_arith.h>
@ -45,7 +46,8 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
have a floating type, in which case the flags shouldn't
travel upward in the expression tree.
*/
register int t1, t2, u1, u2;
struct type *convert1, *convert2;
int t1, t2, u1, u2;
int shifting = (oper == LEFT || oper == RIGHT
|| oper == LEFTAB || oper == RIGHTAB);
int ptrdiff = 0;
@ -56,9 +58,11 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
if (int_size != pointer_size) {
if (ptrdiff = ((*e1p)->ex_flags & EX_PTRDIFF)
|| ((*e2p)->ex_flags & EX_PTRDIFF)) {
if (!((*e1p)->ex_flags & EX_PTRDIFF) && t1 == LONG)
if (!((*e1p)->ex_flags & EX_PTRDIFF)
&& (t1 == LONG || t1 == LNGLNG))
ptrdiff = 0;
if (!((*e2p)->ex_flags & EX_PTRDIFF) && t2 == LONG
if (!((*e2p)->ex_flags & EX_PTRDIFF)
&& (t2 == LONG || t2 == LNGLNG)
&& !shifting)
ptrdiff = 0;
}
@ -67,7 +71,9 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
(*e2p)->ex_flags &= ~EX_PTRDIFF;
}
/* Now t1 and t2 are either INT, LONG, FLOAT, DOUBLE, or LNGDBL */
/* Now t1 and t2 are either INT, LONG, LNGLNG,
FLOAT, DOUBLE, or LNGDBL
*/
/* If any operand has the type long double, the other operand
is converted to long double.
@ -82,11 +88,12 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
}
return;
} else if (t2 == LNGDBL) {
if (t1 != LNGDBL)
if (t1 != LNGDBL) {
if (t1 == DOUBLE || t1 == FLOAT)
float2float(e1p, lngdbl_type);
else
int2float(e1p, lngdbl_type);
}
return;
}
@ -120,38 +127,67 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
return;
}
/* Now they are INT or LONG */
/* Now they are INT, LONG or LNGLNG */
u1 = (*e1p)->ex_type->tp_unsigned;
u2 = (*e2p)->ex_type->tp_unsigned;
convert1 = NULL;
convert2 = NULL;
/* If either operand has type unsigned long int, the other
operand is converted to unsigned long int.
*/
if (t1 == LONG && u1 && (t2 != LONG || !u2))
t2 = int2int(e2p, ulong_type);
else if (t2 == LONG && u2 && (t1 != LONG || !u1)
&& !shifting) /* ??? */
t1 = int2int(e1p, ulong_type);
/* If either operand is a long long, the other operand
is converted to long long; else if either operand is
a long, the other operand is converted to a long.
/* If one operand has type long int and the other has type unsigned
int, if a long int can represent all values of an unsigned int,
the operand of type unsigned int is converted to long int; if
a long int cannot represent all values of an unsigned int,
both operands are converted to unsigned long int.
If one operand is signed and the other operand is
unsigned, if the signed type can represent all values
of the unsigned type, the unsigned operand is
converted to the signed type, else both operands are
converted to an unsigned type.
*/
if (t1 == LONG && t2 == INT && u2)
t2 = int2int(e2p, (int_size<long_size)? long_type : ulong_type);
else if (t2 == LONG && t1 == INT && u1 && !shifting) /* ??? */
t1 = int2int(e1p, (int_size<long_size)? long_type : ulong_type);
if (shifting) {
/* In shifts like o1 << o2, never convert o1,
and let ch3bin() convert o2 to int.
*/
} else if (t1 == LNGLNG && u1 && (t2 != LNGLNG || !u2))
convert2 = ulnglng_type;
else if (t2 == LNGLNG && u2 && (t1 != LNGLNG || !u1))
convert1 = ulnglng_type;
else if (t1 == LNGLNG && t2 != LNGLNG && u2) {
if ((t2 == LONG ? long_size : int_size) < lnglng_size)
convert2 = lnglng_type;
else
convert1 = convert2 = ulnglng_type;
} else if (t2 == LNGLNG && t1 != LNGLNG && u1) {
if ((t1 == LONG ? long_size : int_size) < lnglng_size)
convert1 = lnglng_type;
else
convert1 = convert2 = ulnglng_type;
} else if (t1 == LNGLNG && t2 != LNGLNG)
convert2 = lnglng_type;
else if (t2 == LNGLNG && t1 != LNGLNG)
convert1 = lnglng_type;
else if (t1 == LONG && u1 && (t2 != LONG || !u2))
convert2 = ulong_type;
else if (t2 == LONG && u2 && (t1 != LONG || !u1))
convert1 = ulong_type;
else if (t1 == LONG && t2 == INT && u2) {
if (int_size < long_size)
convert2 = long_type;
else
convert1 = convert2 = ulong_type;
} else if (t2 == LONG && t1 == INT && u1) {
if (int_size < long_size)
convert1 = long_type;
else
convert1 = convert2 = ulong_type;
} else if (t1 == LONG && t2 != LONG)
convert2 = long_type;
else if (t2 == LONG && t1 != LONG)
convert1 = long_type;
/* If either operand has type long int, the other operand is con-
verted to long int.
*/
if (t1 == LONG && t2 != LONG)
t2 = int2int(e2p, long_type);
else
if (t2 == LONG && t1 != LONG && !shifting) /* ??? */
t1 = int2int(e1p, long_type);
if (convert1)
t1 = int2int(e1p, convert1);
if (convert2)
t2 = int2int(e2p, convert2);
u1 = (*e1p)->ex_type->tp_unsigned;
u2 = (*e2p)->ex_type->tp_unsigned;
@ -161,10 +197,10 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
Otherwise, both operands have type int.
*/
if (u1 && !u2 && !shifting)
t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
t2 = int2int(e2p, uint_type);
else
if (!u1 && u2 && !shifting)
t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
t1 = int2int(e1p, uint_type);
if (int_size != pointer_size) {
if (ptrdiff) {
@ -259,6 +295,7 @@ any2arith(register struct expr **expp, register int oper)
break;
case INT:
case LONG:
case LNGLNG:
break;
case ENUM:
#ifndef LINT
@ -338,8 +375,7 @@ int int2int(struct expr **expp, register struct type *tp)
unsigned int x = ~0;
unsigned int y = -1;
*/
extern long full_mask[];
long remainder = exp->VL_VALUE &
writh remainder = exp->VL_VALUE &
~full_mask[(int)(tp->tp_size)];
if (remainder == 0 ||
@ -356,6 +392,16 @@ int int2int(struct expr **expp, register struct type *tp)
return exp->ex_type->tp_fund;
}
static int fit4(writh val, int uns)
{
/* Does this value fit in 4 bytes? */
unsigned writh u = (unsigned writh)val;
if (!uns)
u += 0x80000000UL;
return (u & full_mask[4]) == u;
}
/* With compile-time constants, we don't set fp_used, since this is done
* only when necessary in eval.c.
*/
@ -367,10 +413,10 @@ void int2float(register struct expr **expp, struct type *tp)
register struct expr *exp = *expp;
int uns = exp->ex_type->tp_unsigned;
if (is_cp_cst(exp)) {
if (is_cp_cst(exp) && fit4(exp->VL_VALUE, uns)) {
exp->ex_type = tp;
exp->ex_class = Float;
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns);
flt_arith2flt((arith)exp->VL_VALUE, &(exp->FL_ARITH), uns);
}
else {
fp_used = 1;
@ -387,21 +433,32 @@ void float2int(struct expr **expp, struct type *tp)
if (is_fp_cst(ex)) {
arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned);
#ifdef NOTDEF
/* Historically, we always did the conversion at
compile time. This is now wrong if type arith is
too narrow for an 8-byte integer.
*/
if (flt_status == FLT_OVFL)
expr_warning(ex,"overflow in float to int conversion");
else if (flt_status == FLT_UNFL)
expr_warning(ex,"underflow in float to unsigned conversion");
ex->ex_type = tp;
/* The following lines are copied from fill_int_expr */
ex->ex_class = Value;
ex->VL_CLASS = Const;
ex->VL_VALUE = ar;
cut_size(ex);
} else {
fp_used = 1;
*expp = arith2arith(tp, FLOAT2INT, ex);
#endif /* NOTDEF */
/* Now, we defer the conversion until run time
unless it fits in 4 bytes.
*/
if (flt_status != FLT_OVFL && flt_status != FLT_UNFL &&
fit4((writh)ar, tp->tp_unsigned)) {
ex->ex_type = tp;
/* The following lines are copied from fill_int_expr */
ex->ex_class = Value;
ex->VL_CLASS = Const;
ex->VL_VALUE = (writh)ar;
cut_size(ex);
return;
}
}
fp_used = 1;
*expp = arith2arith(tp, FLOAT2INT, ex);
}
void float2float(register struct expr **expp, struct type *tp)
@ -457,7 +514,7 @@ void opnd2integral(register struct expr **expp, int oper)
{
register int fund = (*expp)->ex_type->tp_fund;
if (fund != INT && fund != LONG) {
if (fund != INT && fund != LONG && fund != LNGLNG) {
expr_error(*expp, "%s operand to %s",
symbol2str(fund), symbol2str(oper));
erroneous2int(expp);
@ -486,6 +543,7 @@ void opnd2logical(register struct expr **expp, int oper)
case SHORT:
case INT:
case LONG:
case LNGLNG:
case ENUM:
case POINTER:
case FLOAT:
@ -606,3 +664,25 @@ void switch_sign_fp(register struct expr *expr)
{
flt_umin(&(expr->FL_ARITH));
}
char *writh2str(writh val, int uns)
{
/* Converts val to a decimal string, like
long2str(val, 10), but allows wider values.
*/
static char buf[NUMSIZE + 1];
char *cp = &buf[NUMSIZE + 1];
int negative = (!uns && val < 0);
unsigned writh u = (unsigned writh)val;
if (negative)
u = -u;
*--cp = '\0';
do {
*--cp = '0' + (u % 10);
u /= 10;
} while (u != 0);
if (negative)
*--cp = '-';
return cp;
}

View file

@ -5,30 +5,25 @@
/* $Id$ */
/* COMPILER ARITHMETIC */
/* Normally the compiler does its internal arithmetics in longs
native to the source machine, which is always good for local
compilations, and generally OK too for cross compilations
downwards and sidewards. For upwards cross compilation and
to save storage on small machines, SPECIAL_ARITHMETICS will
be handy.
/* The compiler uses 2 types, arith and writh, for its internal
arithmetic. Type arith is normally long, and may be too
narrow for long long values. We can't change arith to a wider
type, because both <em_arith.h> (pulled by <em.h>) and
<flt_arith.h> define arith.
Type writh (wide arithmetic) is for values that might not fit
in arith. Normally writh is the long long native to the
source machine, which is always good for local compilations,
and generally OK too for cross compilations downwards and
sidewards.
*/
#ifndef ARITH_H_
#define ARITH_H_
#include "parameters.h"
#ifndef SPECIAL_ARITHMETICS
#include <em_arith.h> /* obtain definition of "arith" */
#include <flt_arith.h>
#else /* SPECIAL_ARITHMETICS */
/* All preprocessor arithmetic should be done in longs.
*/
#define arith long /* dummy */
#endif /* SPECIAL_ARITHMETICS */
#define writh long long
/* The compiler also uses "unsigned writh". */
struct expr;
struct type;
@ -37,6 +32,8 @@ struct type;
#define arith_sign ((arith) 1 << (arith_size * 8 - 1))
#define max_arith (~arith_sign)
extern writh full_mask[]; /* cstoper.c */
void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p);
void relbalance(register struct expr **e1p, int oper, register struct expr **e2p);
void ch3pointer(struct expr **expp, int oper, register struct type *tp);
@ -57,5 +54,6 @@ void any2opnd(register struct expr **expp, int oper);
void any2parameter(register struct expr **expp);
void field2arith(register struct expr **expp);
void switch_sign_fp(register struct expr *expr);
char *writh2str(writh val, int uns);
#endif /* ARITH_H_ */

View file

@ -58,6 +58,7 @@ void ch3sel(struct expr **expp, int oper, struct idf *idf)
break;
case INT:
case LONG:
case LNGLNG:
/* An error is given in idf2sdef() */
ch3cast(expp, CAST, pa_type);
sd = idf2sdef(idf, tp);
@ -82,6 +83,7 @@ void ch3sel(struct expr **expp, int oper, struct idf *idf)
break;
case INT:
case LONG:
case LNGLNG:
/* warning will be given by idf2sdef() */
break;
default:
@ -318,7 +320,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
}
if (oldtp->tp_up->tp_fund == VOID
&& is_cp_cst(exp)
&& exp->VL_VALUE == (arith)0)
&& exp->VL_VALUE == 0)
break; /* switch */
}
/* falltrough */
@ -364,7 +366,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
case NOTEQUAL:
case '=':
case RETURN:
if (is_cp_cst(exp) && exp->VL_VALUE == (arith)0)
if (is_cp_cst(exp) && exp->VL_VALUE == 0)
break;
default:
expr_strict(exp,
@ -679,6 +681,7 @@ int is_integral_type(register struct type *tp)
case SHORT:
case INT:
case LONG:
case LNGLNG:
case ENUM:
return 1;
#ifndef NOBITFIELD
@ -697,6 +700,7 @@ int is_arith_type(register struct type *tp)
case SHORT:
case INT:
case LONG:
case LNGLNG:
case ENUM:
case FLOAT:
case DOUBLE:

View file

@ -206,7 +206,7 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
where o1 == (*expp)->VL_VALUE;
and ((oper == AND) || (oper == OR))
*/
if ((oper == AND) == (ex->VL_VALUE != (arith)0)) {
if ((oper == AND) == (ex->VL_VALUE != 0)) {
*expp = expr;
}
else {
@ -224,13 +224,13 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
where o2 == expr->VL_VALUE
and ((oper == AND) || (oper == OR))
*/
if ((oper == AND) == (expr->VL_VALUE != (arith)0)) {
if ((oper == AND) == (expr->VL_VALUE != 0)) {
(*expp)->ex_flags |= expr->ex_flags | EX_ILVALUE;
free_expression(expr);
}
else {
if (oper == OR)
expr->VL_VALUE = (arith)1;
expr->VL_VALUE = 1;
ch3bin(expp, ',', expr);
}
}

View file

@ -22,7 +22,6 @@
extern char options[];
extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */
char *symbol2str();
void ch3mon(int oper, register struct expr **expp)
@ -122,7 +121,7 @@ void ch3mon(int oper, register struct expr **expp)
case '-':
any2arith(expp, oper);
if (is_cp_cst(*expp)) {
arith o1 = (*expp)->VL_VALUE;
writh o1 = (*expp)->VL_VALUE;
(*expp)->VL_VALUE = (oper == '-') ? -o1 :
((*expp)->ex_type->tp_unsigned ?

View file

@ -101,6 +101,10 @@ void init_code(char *dst_file)
stb_typedef(ushort_type, "unsigned short");
stb_typedef(ulong_type, "unsigned long");
stb_typedef(uint_type, "unsigned int");
if (lnglng_size >= 0) {
stb_typedef(lnglng_type, "long long");
stb_typedef(ulnglng_type, "unsigned long long");
}
stb_typedef(float_type, "float");
stb_typedef(double_type, "double");
stb_typedef(lngdbl_type, "long double");
@ -598,7 +602,7 @@ void loc_init(struct expr *expr, struct idf *id)
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
vl.vl_class = Name;
vl.vl_data.vl_idf = id;
vl.vl_value = (arith)0;
vl.vl_value = 0;
store_val(&vl, tp);
}
#else /* LINT */

View file

@ -112,8 +112,6 @@ void conversion(register struct type *from_type, register struct type *to_type)
if ((int)(to_type->tp_size) < (int)word_size
&& to_cnvtype != T_FLOATING
) {
extern arith full_mask[];
if (to_cnvtype == T_SIGNED) {
C_loc(to_type->tp_size);
C_loc(word_size);
@ -137,6 +135,7 @@ static int convtype(register struct type *tp)
case INT:
case ERRONEOUS:
case LONG:
case LNGLNG:
case ENUM:
return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
case FLOAT:

View file

@ -18,7 +18,7 @@
#include "error.h"
/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
arith full_mask[MAXSIZE + 1];
writh full_mask[MAXSIZE + 1];
#ifndef NOCROSS
arith max_int; /* maximum integer on target machine */
arith max_unsigned; /* maximum unsigned on target machine */
@ -31,8 +31,8 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
expressions *expp(ld) and expr(ct), and the result restored in
*expp.
*/
register arith o1 = (*expp)->VL_VALUE;
register arith o2 = expr->VL_VALUE;
unsigned writh o1 = (unsigned writh)(*expp)->VL_VALUE;
unsigned writh o2 = (unsigned writh)expr->VL_VALUE;
int uns = (*expp)->ex_type->tp_unsigned;
assert(is_ld_cst(*expp) && is_cp_cst(expr));
@ -49,9 +49,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
break;
}
if (uns)
o1 /= (unsigned arith) o2;
else
o1 /= o2;
else
o1 = (unsigned writh)((writh)o1 / (writh)o2);
break;
case '%':
if (o2 == 0) {
@ -62,9 +62,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
break;
}
if (uns)
o1 %= (unsigned arith) o2;
else
o1 %= o2;
else
o1 = (unsigned writh)((writh)o1 % (writh)o2);
break;
case '+':
o1 += o2;
@ -78,15 +78,14 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
case RIGHT:
if (o2 == 0)
break;
if (uns) {
o1 = (o1 >> 1) & ~arith_sign;
o1 >>= (o2 - 1);
}
else o1 >>= o2;
if (uns)
o1 >>= o2;
else
o1 = (unsigned writh)((writh)o1 >> (writh)o2);
break;
case '<':
{
arith tmp = o1;
writh tmp = o1;
o1 = o2;
o2 = tmp;
@ -94,13 +93,13 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
/* Fall through */
case '>':
if (uns)
o1 = (unsigned arith) o1 > (unsigned arith) o2;
else
o1 = o1 > o2;
else
o1 = (writh)o1 > (writh)o2;
break;
case LESSEQ:
{
arith tmp = o1;
writh tmp = o1;
o1 = o2;
o2 = tmp;
@ -108,9 +107,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
/* Fall through */
case GREATEREQ:
if (uns)
o1 = (unsigned arith) o1 >= (unsigned arith) o2;
else
o1 = o1 >= o2;
else
o1 = (writh)o1 >= (writh)o2;
break;
case EQUAL:
o1 = o1 == o2;
@ -128,7 +127,7 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
o1 ^= o2;
break;
}
(*expp)->VL_VALUE = o1;
(*expp)->VL_VALUE = (writh)o1;
cut_size(*expp);
(*expp)->ex_flags |= expr->ex_flags;
(*expp)->ex_flags &= ~EX_PARENS;
@ -140,7 +139,7 @@ void cut_size(register struct expr *expr)
/* The constant value of the expression expr is made to
conform to the size of the type of the expression.
*/
register arith o1 = expr->VL_VALUE;
writh o1 = expr->VL_VALUE;
int uns = expr->ex_type->tp_unsigned;
int size = (int) expr->ex_type->tp_size;
@ -159,8 +158,8 @@ void cut_size(register struct expr *expr)
o1 &= full_mask[size];
}
else {
int nbits = (int) (arith_size - size) * 8;
arith remainder = o1 & ~full_mask[size];
int nbits = (int) (sizeof(o1) - size) * 8;
writh remainder = o1 & ~full_mask[size];
if (remainder != 0 && remainder != ~full_mask[size])
if (!ResultKnown)
@ -173,18 +172,20 @@ void cut_size(register struct expr *expr)
void init_cst(void)
{
register int i = 0;
register arith bt = (arith)0;
unsigned writh bt = 0;
while (!(bt < 0)) {
while (!((writh)bt < 0)) {
bt = (bt << 8) + 0377, i++;
if (i > MAXSIZE)
fatal("array full_mask too small for this machine");
full_mask[i] = bt;
}
if ((int)long_size > arith_size)
fatal("sizeof (arith) insufficient on this machine");
/* signed comparison; lnglng_size might be -1 */
if (long_size > (arith)sizeof(writh) ||
lnglng_size > (arith)sizeof(writh))
fatal("sizeof(writh) insufficient on this machine");
#ifndef NOCROSS
max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1));
max_unsigned = full_mask[(int)int_size];
max_int = (arith)((unsigned writh)full_mask[(int)int_size] >> 1);
max_unsigned = (arith)full_mask[(int)int_size];
#endif /* NOCROSS */
}

View file

@ -123,9 +123,13 @@ single_decl_specifier /* non_empty */ (register struct decspecs *ds;)
}
|
[ SHORT | LONG ]
{ if (ds->ds_size)
error("repeated size specifier");
ds->ds_size = DOT;
{ if (ds->ds_size == LONG && DOT == LONG)
ds->ds_size = LNGLNG;
else {
if (ds->ds_size)
error("repeated size specifier");
ds->ds_size = DOT;
}
}
|
[ SIGNED | UNSIGNED ]
@ -339,7 +343,7 @@ arrayer(arith *sizep;)
constant_expression(&expr)
{
check_array_subscript(expr);
*sizep = expr->VL_VALUE;
*sizep = (arith)expr->VL_VALUE;
free_expression(expr);
}
]?
@ -426,7 +430,7 @@ enumerator(struct type *tp; arith *lp;)
'='
constant_expression(&expr)
{
*lp = expr->VL_VALUE;
*lp = (arith)expr->VL_VALUE;
free_expression(expr);
}
]?
@ -544,7 +548,7 @@ bit_expression(struct field **fd;)
':'
constant_expression(&expr)
{
(*fd)->fd_width = expr->VL_VALUE;
(*fd)->fd_width = (arith)expr->VL_VALUE;
free_expression(expr);
#ifdef NOBITFIELD
error("bitfields are not implemented");

View file

@ -118,11 +118,11 @@ void reject_params(register struct declarator *dc)
void check_array_subscript(register struct expr *expr)
{
arith size = expr->VL_VALUE;
writh size = expr->VL_VALUE;
if (size < 0) {
error("array size is negative");
expr->VL_VALUE = (arith)1;
expr->VL_VALUE = 1;
}
else
if (size == 0) {
@ -131,6 +131,6 @@ void check_array_subscript(register struct expr *expr)
else
if (size & ~max_unsigned) { /* absolutely ridiculous */
expr_error(expr, "overflow in array size");
expr->VL_VALUE = (arith)1;
expr->VL_VALUE = 1;
}
}

View file

@ -69,7 +69,8 @@ void do_decspecs(register struct decspecs *ds)
}
if (ds->ds_size)
{
register int ds_isshort = (ds->ds_size == SHORT);
int ds_isshort = (ds->ds_size == SHORT);
int ds_islong = (ds->ds_size == LONG);
if (ds->ds_typedef)
goto SIZE_ERROR;
@ -78,10 +79,18 @@ void do_decspecs(register struct decspecs *ds)
{
if (ds_isshort)
tp = short_type;
else
else if (ds_islong)
tp = long_type;
else
{
assert(ds->ds_size == LNGLNG);
if (no_long_long())
tp = error_type;
else
tp = lnglng_type;
}
}
else if (tp == double_type && !ds_isshort)
else if (tp == double_type && ds_islong)
{
tp = lngdbl_type;
}
@ -122,6 +131,11 @@ void do_decspecs(register struct decspecs *ds)
if (ds_isunsigned)
tp = ulong_type;
}
else if (tp == lnglng_type)
{
if (ds_isunsigned)
tp = ulnglng_type;
}
else
{
SIGN_ERROR: error("%s with illegal type",

View file

@ -6,8 +6,8 @@
/* DUMP ROUTINES */
#ifdef DEBUG
#include "parameters.h"
#ifdef DEBUG
#include <ack_string.h>
#include <alloc.h>
#include <flt_arith.h>
@ -442,8 +442,8 @@ static void p1_expr(int lvl, register struct expr *expr)
print("(Unknown) ");
break;
}
print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
expr->VL_VALUE);
print("%s\n", writh2str(expr->VL_VALUE,
expr->ex_type->tp_unsigned));
break;
case String:
{

View file

@ -106,7 +106,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
case String: /* a string constant */
if (gencode) {
string2pointer(expr);
C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
C_lae_dlb(expr->VL_LBL, (arith)expr->VL_VALUE);
}
break;
case Float: /* a floating constant */
@ -133,13 +133,15 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
case '+':
/* We have the following possibilities :
int + int, pointer + int, pointer + long,
long + long, double + double
long + long, long long + long long,
double + double
*/
operands(expr, gencode);
if (gencode) {
switch (tp->tp_fund) {
case INT:
case LONG:
case LNGLNG:
if (tp->tp_unsigned)
C_adu(tp->tp_size);
else
@ -165,6 +167,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) {
case INT:
case LONG:
case LNGLNG:
case POINTER:
C_ngi(tp->tp_size);
break;
@ -181,7 +184,8 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
}
/* else binary; we have the following flavours:
int - int, pointer - int, pointer - long,
pointer - pointer, long - long, double - double
pointer - pointer, long - long,
long long - long long, double - double
*/
operands(expr, gencode);
if (!gencode)
@ -189,6 +193,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) {
case INT:
case LONG:
case LNGLNG:
if (tp->tp_unsigned)
C_sbu(tp->tp_size);
else
@ -224,6 +229,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) {
case INT:
case LONG:
case LNGLNG:
case POINTER:
if (tp->tp_unsigned)
C_mlu(tp->tp_size);
@ -246,6 +252,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) {
case INT:
case LONG:
case LNGLNG:
case POINTER:
if (tp->tp_unsigned)
C_dvu(tp->tp_size);
@ -264,7 +271,8 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
break;
case '%':
operands(expr, gencode);
assert(tp->tp_fund==INT || tp->tp_fund==LONG);
assert(tp->tp_fund==INT || tp->tp_fund==LONG ||
tp->tp_fund==LNGLNG);
if (gencode)
if (tp->tp_unsigned)
C_rmu(tp->tp_size);
@ -301,6 +309,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) {
case INT:
case LONG:
case LNGLNG:
if (left->ex_type->tp_unsigned)
C_cmu(size);
else
@ -566,7 +575,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
NO_LABEL, NO_LABEL);
assert(is_cp_cst(right));
if (gencode) {
C_adp(right->VL_VALUE);
C_adp((arith)right->VL_VALUE);
}
break;
case ',':
@ -736,6 +745,7 @@ void assop(register struct type *type, int oper)
case SHORT:
case INT:
case LONG:
case LNGLNG:
case ENUM:
switch (oper) {
case PLUSAB:
@ -848,10 +858,11 @@ void store_val(register struct value *vl, register struct type *tp)
{
register int inword = 0;
register int indword = 0;
arith val = vl->vl_value;
writh wval = vl->vl_value;
arith val = (arith)wval;
if (vl->vl_class == Const) { /* absolute addressing */
load_cst(val, pointer_size);
load_cst(wval, pointer_size);
store_block(tp->tp_size, tp->tp_align);
return;
}
@ -920,7 +931,8 @@ void load_val(register struct expr *expr, int rlval)
register struct type *tp = expr->ex_type;
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
register int inword = 0, indword = 0;
register arith val = expr->VL_VALUE;
writh wval = expr->VL_VALUE;
arith val = (arith)wval;
if (expr->ex_type->tp_fund == FLOAT
|| expr->ex_type->tp_fund == DOUBLE
@ -928,11 +940,11 @@ void load_val(register struct expr *expr, int rlval)
fp_used = 1;
if (expr->VL_CLASS == Const) {
if (rvalue) { /* absolute addressing */
load_cst(val, pointer_size);
load_cst(wval, pointer_size);
load_block(tp->tp_size, tp->tp_align);
}
else /* integer, unsigned, long, enum etc */
load_cst(val, tp->tp_size);
load_cst(wval, tp->tp_size);
return;
}
if (rvalue) {
@ -1012,18 +1024,21 @@ void load_val(register struct expr *expr, int rlval)
}
}
void load_cst(arith val, arith siz)
void load_cst(writh val, arith siz)
{
/* EM can't encode ldc with constant over 4 bytes.
Such a constant must go into rom.
*/
if ((int)siz <= (int)word_size)
C_loc(val);
else
if ((int)siz == (int)dword_size)
if ((int)siz == (int)dword_size && (int)dword_size <= 4)
C_ldc(val);
else {
label datlab;
C_df_dlb(datlab = data_label());
C_rom_icon(long2str((long)val, 10), siz);
C_rom_icon(writh2str(val, 0), siz);
C_lae_dlb(datlab, (arith)0);
C_loi(siz);
}

View file

@ -12,6 +12,7 @@
#include <em.h>
#include "arith.h" /* writh */
struct expr;
struct value;
@ -30,7 +31,7 @@ void assop(register struct type *type, int oper);
*/
void store_val(register struct value *vl, register struct type *tp);
void load_val(register struct expr *expr, int rlval);
void load_cst(arith val, arith siz);
void load_cst(writh val, arith siz);
#endif /* LINT */

View file

@ -184,21 +184,21 @@ void idf2expr(register struct expr *expr)
if (def->df_sc == ENUM)
{
expr->VL_CLASS = Const;
expr->VL_VALUE = def->df_address;
expr->VL_VALUE = (writh)def->df_address;
}
#ifndef LINT
else if (def->df_sc == STATIC && def->df_level >= L_LOCAL)
{
expr->VL_CLASS = Label;
expr->VL_LBL = def->df_address;
expr->VL_VALUE = (arith) 0;
expr->VL_VALUE = 0;
}
#endif /* LINT */
else
{
expr->VL_CLASS = Name;
expr->VL_IDF = idf;
expr->VL_VALUE = (arith) 0;
expr->VL_VALUE = 0;
}
}
@ -270,12 +270,12 @@ arith ivalue, int fund)
expr->ex_file = dot.tk_file;
expr->ex_line = dot.tk_line;
fill_int_expr(expr, ivalue, fund);
fill_int_expr(expr, (writh)ivalue, fund);
return expr;
}
void fill_int_expr(register struct expr *ex,
arith ivalue, int fund)
writh ivalue, int fund)
{
/* Details derived from ivalue and fund are put into the
constant integer expression ex.
@ -294,6 +294,16 @@ arith ivalue, int fund)
case ULONG:
ex->ex_type = ulong_type;
break;
case LNGLNG:
ex->ex_type = lnglng_type;
break;
case ULNGLNG:
ex->ex_type = ulnglng_type;
break;
case ERRONEOUS: /* 123LL when no_long_long() */
ex->ex_type = error_type;
ex->ex_flags |= EX_ERROR;
break;
default:
crash("(fill_int_expr) bad fund %s\n", symbol2str(fund));
/*NOTREACHED*/
@ -406,6 +416,7 @@ void chk_cst_expr(struct expr **expp)
case INT:
case ENUM:
case LONG:
case LNGLNG:
if (is_ld_cst(expr))
{
return;

View file

@ -23,7 +23,7 @@
struct value {
int vl_class; /* Const, Name or Label */
arith vl_value; /* constant value or offset */
writh vl_value; /* constant value or offset */
union {
struct idf *vl_idf; /* external name */
label vl_lbl; /* compiler-generated label */
@ -100,8 +100,6 @@ struct expr {
#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name)
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
extern struct expr *intexpr(), *new_oper();
/* ALLOCDEF "expr" 20 */
@ -113,7 +111,7 @@ void string2expr(register struct expr **expp, char *str, int len);
void int2expr(struct expr *expr);
void float2expr(register struct expr *expr);
struct expr* intexpr(arith ivalue, int fund);
void fill_int_expr(register struct expr *ex,arith ivalue, int fund);
void fill_int_expr(register struct expr *ex, writh ivalue, int fund);
struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
register struct expr *e2);
void chk_cst_expr(struct expr **expp);

View file

@ -28,8 +28,6 @@
#include "eval.h"
extern arith full_mask[]; /* cstoper.c */
/* Eval_field() evaluates expressions involving bit fields.
The various instructions are not yet optimised in the expression
tree and are therefore dealt with in this function.
@ -136,6 +134,8 @@ void store_field(
register struct expr *leftop,
arith tmpvar)
{
arith high_mask;
C_loc(fd->fd_mask);
C_and(word_size);
if (code == TRUE)
@ -145,7 +145,8 @@ void store_field(
C_slu(word_size);
else
C_sli(word_size);
C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[(int)word_size]));
high_mask = (arith)~full_mask[(int)word_size];
C_loc(~((fd->fd_mask << fd->fd_shift) | high_mask));
if (leftop->ex_depth == 0) { /* simple case */
load_val(leftop, RVAL);
C_and(word_size);

View file

@ -518,6 +518,7 @@ void check_ival(struct expr **expp, register struct type *tp)
case SHORT:
case INT:
case LONG:
case LNGLNG:
case ENUM:
case POINTER:
ch3cast(expp, '=', tp);
@ -543,11 +544,11 @@ void check_ival(struct expr **expp, register struct type *tp)
if (idf->id_def->df_type->tp_fund == FUNCTION)
C_con_pnam(idf->id_text);
else /* e.g., int a; int *p = &a; */
C_con_dnam(idf->id_text, expr->VL_VALUE);
C_con_dnam(idf->id_text, (arith)expr->VL_VALUE);
}
else {
assert(expr->VL_CLASS == Label);
C_con_dlb(expr->VL_LBL, expr->VL_VALUE);
C_con_dlb(expr->VL_LBL, (arith)expr->VL_VALUE);
}
break;
case FLOAT:
@ -594,7 +595,7 @@ and also to prevent runtime coercions for compile-time constants.
print_expr("init-expr after cast", expr);
#endif /* DEBUG */
if (is_cp_cst(expr))
put_bf(tp, expr->VL_VALUE);
put_bf(tp, (arith)expr->VL_VALUE);
else
illegal_init_cst(expr);
break;
@ -700,7 +701,7 @@ void put_bf(struct type *tp, arith val)
field |= (val & fd->fd_mask) << fd->fd_shift;
if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
/* the selector was the last stored at this address */
exp.VL_VALUE = field;
exp.VL_VALUE = (writh)field;
con_int(&exp);
field = (arith)0;
offset = (arith)-1;
@ -738,11 +739,11 @@ void con_int(register struct expr *ex)
assert(is_cp_cst(ex));
if (tp->tp_unsigned)
C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size);
C_con_ucon(writh2str(ex->VL_VALUE, 1), tp->tp_size);
else if (tp->tp_size == word_size)
C_con_cst(ex->VL_VALUE);
C_con_cst((arith)ex->VL_VALUE);
else
C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size);
C_con_icon(writh2str(ex->VL_VALUE, 0), tp->tp_size);
}
void illegal_init_cst(struct expr *ex)

View file

@ -57,6 +57,7 @@ arith
dword_size = (2 * SZ_WORD),
int_size = SZ_INT,
long_size = SZ_LONG,
lnglng_size = SZ_LNGLNG,
float_size = SZ_FLOAT,
double_size = SZ_DOUBLE,
lngdbl_size = SZ_LNGDBL,
@ -67,6 +68,7 @@ int
word_align = AL_WORD,
int_align = AL_INT,
long_align = AL_LONG,
lnglng_align = AL_LNGLNG,
float_align = AL_FLOAT,
double_align = AL_DOUBLE,
lngdbl_align = AL_LNGDBL,
@ -227,6 +229,10 @@ static void init(void)
long_type = standard_type(LONG, 0, long_align, long_size);
ulong_type = standard_type(LONG, UNSIGNED, long_align, long_size);
lnglng_type = standard_type(LNGLNG, 0, lnglng_align, lnglng_size);
ulnglng_type = standard_type(LNGLNG, UNSIGNED, lnglng_align,
lnglng_size);
float_type = standard_type(FLOAT, 0, float_align, float_size);
double_type = standard_type(DOUBLE, 0, double_align, double_size);
lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size);

View file

@ -159,6 +159,12 @@ next_option: /* to allow combined one-char options */
if (algn != 0)
long_align = algn;
break;
case 'q': /* long long */
if (sz != (arith)0)
lnglng_size = sz;
if (algn != 0)
lnglng_align = algn;
break;
case 'f': /* float */
if (sz != (arith)0)
float_size = sz;

View file

@ -10,6 +10,7 @@
#ifndef NOCROSS
extern arith
short_size, word_size, dword_size, int_size, long_size,
lnglng_size,
float_size, double_size, lngdbl_size,
pointer_size;
@ -20,6 +21,7 @@ extern arith max_int, max_unsigned; /* cstoper.c */
#define dword_size ((arith)2*SZ_WORD)
#define int_size ((arith)SZ_INT)
#define long_size ((arith)SZ_LONG)
#define lnglng_size ((arith)SZ_LNGLNG)
#define float_size ((arith)SZ_FLOAT)
#define double_size ((arith)SZ_DOUBLE)
#define lngdbl_size ((arith)SZ_LNGDBL)

View file

@ -32,8 +32,6 @@
#include "level.h"
#include "print.h"
extern long full_mask[];
#define INCR_SIZE 64
static struct db_str
@ -74,9 +72,10 @@ static void adds_db_str(char *s)
static void stb_type(register struct type *tp)
{
char buf[128];
char buf[128], *range;
static int stb_count;
long l;
int uns;
if (tp->tp_dbindex > 0)
{
@ -101,18 +100,26 @@ static void stb_type(register struct type *tp)
break;
case INT:
case LONG:
case LNGLNG:
case CHAR:
case SHORT:
l = full_mask[(int) tp->tp_size];
if (tp->tp_unsigned)
switch ((tp->tp_size << 3) + !tp->tp_unsigned)
{
adds_db_str(sprint(buf, "r%d;0;%ld", tp->tp_dbindex, l));
}
else
{
l &= ~(1L << ((int) tp->tp_size * 8 - 1));
adds_db_str(sprint(buf, "r%d;%ld;%ld", tp->tp_dbindex, -l - 1, l));
#define R(s) range = #s; break
case 0010: R(0;255);
case 0011: R(-128;127);
case 0020: R(0;65535);
case 0021: R(-32768;32767);
default: R(0;-1); /* acts as 0;4294967295 */
case 0041: R(-2147483648;2147483647);
/* The stabs reader in gdb(1) needs an octal integer
when its value doesn't fit in type long.
*/
case 0100: R(0;01777777777777777777777);
case 0101: R(01000000000000000000000;0777777777777777777777);
#undef R
}
adds_db_str(sprint(buf, "r%d;%s", tp->tp_dbindex, range));
break;
case FLOAT:
case DOUBLE:

View file

@ -147,7 +147,7 @@ if_statement
/* The comparison has been optimized
to a 0 or 1.
*/
if (expr->VL_VALUE == (arith)0) {
if (expr->VL_VALUE == 0) {
C_bra(l_false);
}
/* else fall through */
@ -210,7 +210,7 @@ while_statement
{
opnd2test(&expr, WHILE);
if (is_cp_cst(expr)) {
if (expr->VL_VALUE == (arith)0) {
if (expr->VL_VALUE == 0) {
C_bra(l_break);
}
}
@ -264,11 +264,11 @@ do_statement
{
opnd2test(&expr, WHILE);
if (is_cp_cst(expr)) {
if (expr->VL_VALUE == (arith)1) {
if (expr->VL_VALUE == 1) {
C_bra(l_body);
}
#ifdef LINT
end_do_stmt(1, expr->VL_VALUE != (arith)0);
end_do_stmt(1, expr->VL_VALUE != 0);
#endif /* LINT */
}
else {
@ -313,7 +313,7 @@ for_statement
{
opnd2test(&e_test, FOR);
if (is_cp_cst(e_test)) {
if (e_test->VL_VALUE == (arith)0) {
if (e_test->VL_VALUE == 0) {
C_bra(l_break);
}
}

View file

@ -360,6 +360,7 @@ add_field(
case SHORT:
case ENUM:
case LONG:
case LNGLNG:
strict("non-portable field type");
case INT:
/* right type; size OK? */

View file

@ -32,13 +32,13 @@ extern char options[];
int density = DENSITY;
static int compact(int nr, arith low, arith up)
static int compact(int nr, writh low, writh up)
{
/* Careful! up - low might not fit in an arith. And then,
the test "up-low < 0" might also not work to detect this
situation! Or is this just a bug in the M68020/M68000?
*/
arith diff = up - low;
writh diff = up - low;
return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1)));
}
@ -61,7 +61,7 @@ void code_startswitch(struct expr **expp)
register label l_break = text_label();
register struct switch_hdr *sh = new_switch_hdr();
int fund = any2arith(expp, SWITCH);
/* INT, LONG, FLOAT, DOUBLE or LNGDBL */
/* INT, LONG, LNGLNG, FLOAT, DOUBLE or LNGDBL */
switch (fund) {
case FLOAT:
@ -117,10 +117,10 @@ void code_endswitch(void)
C_rom_ilb(sh->sh_default);
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
/* CSA */
register arith val;
writh val;
C_rom_icon(long2str((long)sh->sh_lowerbd,10), size);
C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10),
C_rom_icon(writh2str(sh->sh_lowerbd, 0), size);
C_rom_icon(writh2str(sh->sh_upperbd - sh->sh_lowerbd, 0),
size);
ce = sh->sh_entries;
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
@ -136,10 +136,10 @@ void code_endswitch(void)
C_csa(size);
}
else { /* CSB */
C_rom_icon(long2str((long)sh->sh_nrofentries,10),size);
C_rom_icon(writh2str(sh->sh_nrofentries, 0), size);
for (ce = sh->sh_entries; ce; ce = ce->next) {
/* generate the entries: value + prog.label */
C_rom_icon(long2str((long)ce->ce_value,10),size);
C_rom_icon(writh2str(ce->ce_value, 0), size);
C_rom_ilb(ce->ce_label);
}
C_lae_dlb(tablabel, (arith)0); /* perform the switch */
@ -162,7 +162,7 @@ void code_endswitch(void)
void code_case(struct expr *expr)
{
register arith val;
writh val;
register struct case_entry *ce;
register struct switch_hdr *sh = switch_stack;

View file

@ -22,8 +22,8 @@ struct switch_hdr {
int sh_nrofentries;
struct type *sh_type;
struct expr *sh_expr;
arith sh_lowerbd;
arith sh_upperbd;
writh sh_lowerbd;
writh sh_upperbd;
struct case_entry *sh_entries;
};
@ -32,7 +32,7 @@ struct switch_hdr {
struct case_entry {
struct case_entry *next;
label ce_label;
arith ce_value;
writh ce_value;
};
/* ALLOCDEF "case_entry" 20 */

View file

@ -104,8 +104,10 @@ struct tokenname tkidf[] = { /* names of the identifier tokens */
#ifdef ____
struct tokenname tkfunny[] = { /* internal keywords */
{LNGLNG, "long long"},
{LNGDBL, "long double"},
{ULONG, "unsigned long"},
{ULNGLNG, "unsigned long long"},
{ARRAY, "array"},
{FUNCTION, "function"},

View file

@ -25,6 +25,7 @@
*/
struct type *schar_type, *uchar_type, *short_type, *ushort_type, *word_type,
*uword_type, *int_type, *uint_type, *long_type, *ulong_type,
*lnglng_type, *ulnglng_type,
*float_type, *double_type, *lngdbl_type, *void_type, *string_type,
*funint_type, *error_type;
@ -291,3 +292,20 @@ void completed(struct type *tp)
atp = atp->next;
}
}
int no_long_long(void)
{
static int shown = 0;
if (lnglng_size < 0)
{
if (!shown)
{
error("no long long for this machine");
shown = 1;
}
return 1;
}
else
return 0;
}

View file

@ -71,6 +71,7 @@ extern struct type
*word_type, *uword_type,
*int_type, *uint_type,
*long_type, *ulong_type,
*lnglng_type, *ulnglng_type,
*float_type, *double_type, *lngdbl_type,
*void_type,
*string_type, *funint_type, *error_type;
@ -93,6 +94,7 @@ void idf2type(struct idf *idf, struct type **tpp);
arith align(arith pos, int al);
struct type * standard_type(int fund, int sgn, int algn, arith sz);
void completed(struct type *tp);
int no_long_long(void);
/* ALLOCDEF "type" 50 */

View file

@ -27,22 +27,34 @@ typedef unsigned short uint16_t;
#if _EM_WSIZE == 4
typedef signed int int32_t;
typedef unsigned int uint32_t;
#define INT32_MAX 2147483647
#define INT32_MIN (-2147483648)
#define UINT32_MAX 4294967295U
#else
typedef signed long int32_t;
typedef unsigned long uint32_t;
#define INT32_MAX 2147483647L
#define INT32_MIN (-2147483648L)
#define UINT32_MAX 4294967295UL
#endif
#define INT32_MAX 2147483647
#define INT32_MIN (-2147483648)
#define UINT32_MAX 4294967295
/* We only get int64_t if longs are 8 bytes. */
/* We only get int64_t if longs or long longs are 8 bytes. */
#if _EM_LSIZE == 8
typedef signed long int64_t;
typedef unsigned long uint64_t;
#define INT64_MAX 2147483647LL
#define INT64_MIN (-2147483648LL)
#define UINT64_MAX 4294967295ULL
#define INT64_MAX 9223372036854775807L
#define INT64_MIN (-9223372036854775808L)
#define UINT64_MAX 18446744073709551615UL
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
#elif _EM_LLSIZE == 8
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
#define INT64_MAX 9223372036854775807LL
#define INT64_MIN (-9223372036854775808LL)
#define UINT64_MAX 18446744073709551615ULL
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;

View file

@ -8,9 +8,6 @@
#define WORDS_REVERSED
#define BYTES_REVERSED
*/
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long

View file

@ -11,8 +11,6 @@
#define LISTING /* enable listing facilities */
#define RELOCATION /* generate relocation info */
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long

View file

@ -1,7 +1,7 @@
for _, plat in ipairs(vars.plats) do
acklibrary {
name = "lib_"..plat,
srcs = { "./*.s" },
srcs = { "./*.s" }, -- csb8.s
vars = { plat = plat },
}
end

35
mach/i386/libem/csa8.s Normal file
View file

@ -0,0 +1,35 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.define .csa8
.sect .text
.csa8:
! ebx, descriptor address
! edx:eax, index
mov ecx,(ebx) ! default
sub eax,4(ebx)
sbb edx,8(ebx) ! index - lower bound
push edx
push eax
mov eax,12(ebx)
mov edx,16(ebx) ! upper bound - lower bound
sub eax,(esp)
sbb edx,4(esp) ! upper bound - index
pop eax
pop edx
jb 1f ! jump if upper bound < index
! assuming edx:eax < 2**30
mov ebx,20(ebx)(eax*4)
test ebx,ebx
jnz 2f
1:
mov ebx,ecx
test ebx,ebx
jnz 2f
.extern ECASE
.extern .fat
mov eax,ECASE
push eax
jmp .fat
2:
jmp ebx

39
mach/i386/libem/csb8.s Normal file
View file

@ -0,0 +1,39 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.define .csb8
.sect .text
.csb8:
! ebx, descriptor address
! edx:eax, index
push esi
push edi
push (ebx) ! default
mov ecx,4(ebx) ! entry count (assuming < 2**32)
1:
add ebx,12
dec ecx
jl 4f
mov esi,0(ebx)
mov edi,4(ebx) ! descriptor's index
sub esi,eax
sbb edi,edx
or esi,edi
jne 1b
pop edx ! drop default
mov ebx,8(ebx)
2:
pop edi
pop esi
test ebx,ebx
jnz 3f
.extern ECASE
.extern .fat
mov eax,ECASE
push eax
jmp .fat
3:
jmp ebx
4:
pop ebx ! default
jmp 2b

63
mach/i386/libem/divrem8.s Normal file
View file

@ -0,0 +1,63 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .divrem8
yl=12
yh=16
xl=20
xh=24
! This private sub for .dvi8, .dvu8, .rmi8, .rmu8
! does unsigned division of x = xh:xl by y = yh:yl,
! yields ebx:eax = quotient, ecx:edx = remainder.
.divrem8:
! Caller must set eax, edx, flag z like so:
! mov edx,yh(esp)
! test edx,edx
! mov eax,xh(esp)
jnz 1f ! jump if y >= 2**32
! y = yl, so x / y = xh:xl / yl = qh:0 + (xl + rh) / yl
! where qh, rh are quotient, remainder from xh / yl.
mov ecx,yl(esp)
xor edx,edx ! edx:eax = xh
div ecx ! eax = qh, edx = rh
mov ebx,eax
mov eax,xl(esp) ! edx:eax = qh:xl
div ecx ! ebx:eax = qh:ql = quotient
xor ecx,ecx ! ecx:edx = 0:rl = remainder
ret
1: ! Here y >= 2**32. Find y >> cl in [2**31, 2**32).
mov ebx,yl(esp) ! edx:ebx = y
bsr ecx,edx ! scan yh for highest set bit
incb cl ! cl bits from cl-1 to 0
shrd ebx,edx,cl ! ebx = y >> cl
! Estimate x / y as q = (x / (y >> cl)) >> cl.
xor edx,edx ! edx:eax = xh
div ebx ! eax = xh / (y >> cl)
push eax
mov eax,xl+4(esp) ! push moved xl to xl+4
div ebx
pop edx ! edx:eax = x / (y >> cl)
shrd eax,edx,cl ! eax = q
! Calculate the remainder x - y * q. If the subtraction
! overflows, then the correct quotient is q - 1, else it is q.
mov ebx,yh(esp)
imul ebx,eax ! ebx = yh * q
push eax
mul yl+4(esp) ! edx:eax = yl * q
add ebx,edx ! ebx:eax = y * q
mov edx,xl+4(esp)
mov ecx,xh+4(esp)
sub edx,eax
sbb ecx,ebx ! ecx:edx = remainder
pop eax ! eax = q
jnc 1f ! jump unless subtraction overflowed
dec eax ! fix quotient
add edx,yl(esp)
adc ecx,yh(esp) ! fix remainder
1: xor ebx,ebx ! ebx:eax = quotient
ret

37
mach/i386/libem/dvi8.s Normal file
View file

@ -0,0 +1,37 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .dvi8
yl=4
yh=8
xl=12
xh=16
! .dvi8 yields ebx:eax = quotient from x / y
.dvi8:
xorb cl,cl ! cl = 0, non-negative result
mov eax,xh(esp) ! eax for .divrem8
test eax,eax
jge 1f ! jump unless x < 0
incb cl ! cl = 1, negative result
neg eax
neg xl(esp)
sbb eax,0
mov xh(esp),eax ! x = absolute value
1: mov edx,yh(esp) ! edx for .divrem8
test edx,edx ! flag z for .divrem8 when y >= 0
jge 1f ! jump unless y < 0
xorb cl,1 ! flip sign of result
neg edx
neg yl(esp)
sbb edx,0 ! flag z for .divrem8 when y < 0
mov yh(esp),edx ! y = absolute value
1: push ecx
call .divrem8
pop ecx
testb cl,cl
jz 1f ! jump unless result < 0
neg ebx
neg eax
sbb ebx,0 ! negate quotient ebx:eax
1: ret 16

20
mach/i386/libem/dvu8.s Normal file
View file

@ -0,0 +1,20 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .dvu8, .rmu8
yl=4
yh=8
xl=12
xh=16
! .dvu8 yields ebx:eax = quotient from x / y
! .rmu8 yields ecx:edx = remainder from x / y
.dvu8:
.rmu8:
mov edx,yh(esp)
test edx,edx
mov eax,xh(esp) ! prepare for .divrem8
push ebp ! move esp
call .divrem8
pop ebp ! move esp
ret 16

20
mach/i386/libem/mli8.s Normal file
View file

@ -0,0 +1,20 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .mli8
yl=4
yh=8
! xl in eax
! xh in edx
.mli8:
! x * y = (xh + xl) * (yh + yl)
! = xh * yh + xh * yl + xl * yh + xl * yl
! The term xh * yh overflows to zero.
mov ecx,eax
imul ecx,yh(esp) ! ecx = xl * yh
imul edx,yl(esp) ! edx = xh * yl
add ecx,edx
mul yl(esp) ! edx:eax = xl * yl
add edx,ecx ! edx:eax = x * y
ret 8

36
mach/i386/libem/rmi8.s Normal file
View file

@ -0,0 +1,36 @@
.sect .text; .sect .rom; .sect .data; .sect .bss
.sect .text
.define .rmi8
yl=4
yh=8
xl=12
xh=16
! .rmi8 yields ecx:edx = remainder from x / y
.rmi8:
xorb cl,cl ! cl = 0, non-negative result
mov eax,xh(esp) ! eax for .divrem8
test eax,eax
jge 1f ! jump unless x < 0
incb cl ! cl = 1, negative result
neg eax
neg xl(esp)
sbb eax,0
mov xh(esp),eax ! x = absolute value
1: mov edx,yh(esp) ! edx for .divrem8
test edx,edx ! flag z for .divrem8 when y >= 0
jge 1f ! jump unless y < 0
neg edx
neg yl(esp)
sbb edx,0 ! flag z for .divrem8 when y < 0
mov yh(esp),edx ! y = absolute value
1: push ecx
call .divrem8
pop eax
testb al,al
jz 1f ! jump unless result < 0
neg ecx
neg edx
sbb ecx,0 ! negate remainder ecx:edx
1: ret 16

View file

@ -34,13 +34,11 @@ con_part(sz,w) register sz; word w; {
}
void
con_mult(sz) word sz; {
long l;
con_mult(word sz) {
if (sz != 4)
if (sz != 8)
fatal("bad icon/ucon size");
l = atol(str);
fprintf(codefile,"\t.data4 %ld\n", l);
fprintf(codefile,".data8\t%s\n", str);
}
#define CODE_GENERATOR

View file

@ -234,8 +234,12 @@ jmp label cost(1,4).
proccall "call" label+rm cost(1,8).
jxx "syntax error" label cost(1,4).
setxx "syntax error" REG1:rw cost(2,4).
seta REG1:rw cost(2,4).
setb REG1:rw cost(2,4).
setl REG1:rw cost(2,4).
setle REG1:rw cost(2,4).
setg REG1:rw cost(2,4).
setne REG1:rw cost(2,4).
lea anyreg:rw, halfindir:ro.
lea LOCAL:rw, halfindir:ro. /* only for register variables, UNSAFE!!! */
leave cost(1,4).
@ -255,12 +259,14 @@ movzxb anyreg:wo, REG+rm1:ro.
movzx anyreg:wo, REG+rm2:ro.
mul rmorconst:ro kills :cc eax edx cost(2,41).
neg rmorconst:rw:cc.
negb rm1:rw:cc.
not rmorconst:rw.
#ifdef REGVARS
or LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */
#endif
or rm:rw:cc, regorconst:ro.
or anyreg:rw:cc, rmorconst:ro.
orb REG1:rw, REG1:ro.
pop anyreg:wo cost(1,4).
pop rm:wo.
push anyreg:ro cost(1,2).
@ -276,7 +282,9 @@ sar rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
sbb rm:rw:cc, regorconst:ro.
sbb anyreg:rw:cc, rmorconst:ro.
shl rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
shld rm:rw, anyreg:ro, ANYCON+SHIFT_CREG:ro kills :cc cost(2,3).
shr rm:rw, ANYCON+SHIFT_CREG:ro kills :cc.
shrd rm:rw, anyreg:ro, ANYCON+SHIFT_CREG:ro kills :cc cost(2,3).
#ifdef REGVARS
sub LOCAL:rw:cc, rmorconst:ro. /* only for register variables; UNSAFE !!! */
#endif
@ -506,7 +514,10 @@ PATTERNS
pat loc yields {ANYCON,$1}
#if 0
/* wrong because .Xtrp assumes trap < 16 */
pat ldc leaving loc 18 trp
#endif
pat lol yields {LOCAL,$1,4}
@ -961,6 +972,14 @@ with EXACT rmorconst const
uses reusing %1,REG=%1
gen add %a,%2 yields %a
pat adi $1==8
with EXACT REG REG rmorconst rmorconst
gen add %1,%3
adc %2,%4 yields %2 %1
with rmorconst rmorconst REG REG
gen add %3,%1
adc %4,%2 yields %4 %3
/*
pat adi !defined($1)
with CXREG ACC
@ -969,13 +988,17 @@ with CXREG ACC
*/
pat sbi $1==4
with rmorconst REG
gen sub %2,%1 yields %2
with EXACT REG rmorconst
gen sub %1,%2
neg %1 yields %1
pat sbi $1==8
with rmorconst rmorconst REG REG
gen sub %3,%1
sbb %4,%2 yields %4 %3
/*
pat sbi !defined($1)
with CXREG ACC
@ -995,6 +1018,11 @@ with rm const
uses reusing %1,REG
gen imul %a,%1,%2 yields %a
pat mli $1==8
with ACC DXREG
kills ALL
gen proccall {label,".mli8"} yields edx eax
/*
pat mli !defined($1)
with ACC
@ -1008,6 +1036,10 @@ with noacc ACC
gen cdq.
idiv %1 yields eax
pat dvi $1==8
kills ALL
gen proccall {label,".dvi8"} yields ebx eax
/*
pat dvi !defined($1)
with ACC
@ -1021,6 +1053,10 @@ with noacc ACC
gen cdq.
idiv %1 yields edx
pat rmi $1==8
kills ALL
gen proccall {label,".rmi8"} yields ecx edx
/*
pat rmi !defined($1)
with ACC
@ -1032,6 +1068,12 @@ pat ngi $1==4
with REG
gen neg %1 yields %1
pat ngi $1==8
with REG REG
gen neg %2
neg %1
sbb %2,{ANYCON,0} yields %2 %1
/*
pat ngi !defined($1)
with ACC
@ -1045,6 +1087,29 @@ with ANYCON REG
with SHIFT_CREG REG
gen sal %2,cl yields %2
pat sli $1==8
with SHIFT_CREG REG REG
gen testb cl,{ANYCON,32}
jne {label,1f}
shld %3,%2,cl
sal %2,cl
jmp {label,2f}
1:
mov %3,%2
sal %3,cl
xor %2,%2
2: yields %3 %2
pat loc sli ($1&32)==0 && $2==8
with REG REG
gen shld %2,%1,{ANYCON,$1&31}
sal %1,{ANYCON,$1&31} yields %2 %1
pat loc sli ($1&63)==32 && $2==8
with a_word a_word yields %1 {ANYCON,0}
pat loc sli ($1&32)!=0 && $2==8
with REG a_word
gen sal %1,{ANYCON,$1&31} yields %1 {ANYCON,0}
/*
pat sli !defined($1)
with ACC
@ -1058,6 +1123,31 @@ with SHIFT_CREG REG
with ANYCON REG
gen sar %2,%1 yields %2
pat sri $1==8
with SHIFT_CREG REG REG
gen testb cl,{ANYCON,32}
jne {label,1f}
shrd %2,%3,cl
sar %3,cl
jmp {label,2f}
1:
mov %2,%3
sar %2,cl
sar %3,{ANYCON,31}
2: yields %3 %2
pat loc sri ($1&32)==0 && $2==8
with REG REG
gen shrd %1,%2,{ANYCON,$1&31}
sar %2,{ANYCON,$1&31} yields %2 %1
pat loc sri ($1&63)==32
with a_word ACC
gen cdq. yields edx eax
pat loc sri ($1&32)!=0 && $2==8
with a_word ACC
gen sar eax,{ANYCON,$1&31}
cdq. yields edx eax
/*
pat sri !defined($1)
with ACC
@ -1114,6 +1204,10 @@ with noacc ACC
uses DXREG={ANYCON,0}
gen div %1 yields eax
pat dvu $1==8
kills ALL
gen proccall {label,".dvu8"} yields ebx eax
/*
pat dvu !defined($1)
with ACC STACK
@ -1126,6 +1220,10 @@ with noacc ACC
uses DXREG={ANYCON,0}
gen div %1 yields edx
pat rmu $1==8
kills ALL
gen proccall {label,".rmu8"} yields ecx edx
/*
pat rmu !defined($1)
with ACC STACK
@ -1142,6 +1240,29 @@ gen shr %2,cl yields %2
with ANYCON REG
gen shr %2,%1 yields %2
pat sru $1==8
with SHIFT_CREG REG REG
gen testb cl,{ANYCON,32}
jne {label,1f}
shrd %2,%3,cl
shr %3,cl
jmp {label,2f}
1:
mov %2,%3
shr %2,cl
xor %3,%3
2: yields %3 %2
pat loc sru ($1&32)==0 && $2==8
with REG REG
gen shrd %2,%1,{ANYCON,$1&31}
shr %1,{ANYCON,$1&31} yields %2 %1
pat loc sru ($1&63)==32 && $2==8
with a_word a_word yields {ANYCON,0} %2
pat loc sru ($1&32)!=0 && $2==8
with a_word REG
gen shr %2,{ANYCON,$1&31} yields {ANYCON,0} %2
/*
pat sru !defined($1)
with ACC STACK
@ -2046,10 +2167,13 @@ with CXREG DXREG ACC
kills ALL
gen proccall {label,".cii"} yields %3
#if 0
/* wrong when integer size > 4 */
pat ciu leaving cuu
pat cui leaving cuu
pat cuu
#endif
pat loc loc cii zeq $1==1
with GENREG STACK
@ -2084,11 +2208,26 @@ with exact rm2
uses reusing %1,GENREG
gen movsx %a,%1 yields %a
pat loc loc cii $1==4 && $2==8
with ACC
gen cdq. yields edx eax
pat loc loc cii $1<4 && $2==8 leaving loc $1 loc 4 cii loc 4 loc $2 cii
pat loc loc cii $1==8 && $2==4
with a_word a_word yields %1
pat loc loc ciu leaving loc $1 loc $2 cuu
pat loc loc cui leaving loc $1 loc $2 cuu
pat loc loc cuu $1==$2
pat loc loc cuu $1==4 && $2==8
with a_word yields {ANYCON,0} %1
pat loc loc cuu $1==8 && $2==4
with a_word a_word yields %1
pat loc loc cif $1==4 && $2==4 leaving loc 4 cal ".cif4" asp 4
pat loc loc cif $1==4 && $2==8 leaving loc 4 cal ".cif8"
pat loc loc cuf $1==4 && $2==4 leaving loc 4 cal ".cuf4" asp 4
@ -2206,12 +2345,56 @@ with SHIFT_CREG REG
with ANYCON REG
gen rol %2,%1 yields %2
pat rol $1==8
with SHIFT_CREG REG REG
uses REG
gen testb cl,{ANYCON,32}
je {label,1f}
xchg %2,%3
1:
mov %a,%3
shld %3,%2,cl
shld %2,%a,cl yields %3 %2
pat loc rol ($1&32)==0 && $2==8
with REG REG
uses REG
gen mov %a,%2
shld %2,%1,{ANYCON,$1&31}
shld %1,%a,{ANYCON,$1&31} yields %2 %1
pat loc rol ($1&63)==32 && $2==8
leaving exg 4
pat loc rol ($1&32)!=0 && $2==8
leaving loc (0-$1)&31 ror 8
pat ror $1==4
with SHIFT_CREG REG
gen ror %2,cl yields %2
with ANYCON REG
gen ror %2,%1 yields %2
pat ror $1==8
with SHIFT_CREG REG REG
uses REG
gen testb cl,{ANYCON,32}
je {label,1f}
xchg %2,%3
1:
mov %a,%2
shrd %2,%3,cl
shrd %3,%a,cl yields %3 %2
pat loc ror ($1&32)==0 && $2==8
with REG REG
uses REG
gen mov %a,%1
shrd %1,%2,{ANYCON,$1&31}
shrd %2,%a,{ANYCON,$1&31} yields %2 %1
pat loc ror ($1&63)==32 && $2==8
leaving exg 4
pat loc ror ($1&32)!=0 && $2==8
leaving loc (0-$1)&31 rol 8
/*******************************************************************
* Group 10 : Set Instructions *
*******************************************************************/
@ -2393,8 +2576,31 @@ with rmorconst register
dec %a
2: yields %a
pat cmi $1==8
with rmorconst rmorconst GENREG GENREG
/* Let dx = 0x100 or 0x101 if a < b, 0 if a == b, 1 if a > b.
Shift left so 0x100 becomes the sign bit of edx. */
/* can't use 5th REG */
gen sub %3,%1
setne %3.1
sbb %4,%2
setl %4.2
setg %4.1
orb %4.1,%3.1
shl %4,{ANYCON,23} yields %4
pat cmu $1==4 leaving cmp
pat cmu $1==8
with rmorconst rmorconst GENREG GENREG
gen sub %3,%1
setne %3.1
sbb %4,%2
setb %4.2
seta %4.1
orb %4.1,%3.1
shl %4,{ANYCON,23} yields %4
pat cms $1==4
with REG rmorconst
gen sub %1,%2 yields %1
@ -2555,6 +2761,49 @@ pat cmp zgt call cmxzxx("ja","jb")
pat cms zeq $1==4 call cmxzxx("je","je")
pat cms zne $1==4 call cmxzxx("jne","jne")
proc cmx8txxn example cmi tgt
with GENREG REG rmorconst rmorconst
/* can't use 5th REG */
gen sub %1,%3
sbb %2,%4
setxx* %2.1
movzxb %2,%2.1 yields %2
proc cmx8txxy example cmi tlt
with rmorconst rmorconst GENREG REG
gen sub %3,%1
sbb %4,%2
setxx* %4.1
movzxb %4,%4.1 yields %4
pat cmi tlt $1==8 call cmx8txxy("setl")
pat cmi tle $1==8 call cmx8txxn("setge")
pat cmi tge $1==8 call cmx8txxy("setge")
pat cmi tgt $1==8 call cmx8txxn("setl")
pat cmu tlt $1==8 call cmx8txxy("setb")
pat cmu tle $1==8 call cmx8txxn("setae")
pat cmu tge $1==8 call cmx8txxy("setae")
pat cmu tgt $1==8 call cmx8txxn("setb")
proc cmx8zxxn example cmi zgt
with REG REG rmorconst rmorconst STACK
gen sub %1,%3
sbb %2,%4
jxx* {label,$2}
proc cmx8zxxy example cmi zlt
with rmorconst rmorconst REG REG STACK
gen sub %3,%1
sbb %4,%2
jxx* {label,$2}
pat cmi zlt $1==8 call cmx8zxxy("jl")
pat cmi zle $1==8 call cmx8zxxn("jge")
pat cmi zge $1==8 call cmx8zxxy("jge")
pat cmi zgt $1==8 call cmx8zxxn("jl")
pat cmu zlt $1==8 call cmx8zxxy("jb")
pat cmu zle $1==8 call cmx8zxxn("jae")
pat cmu zge $1==8 call cmx8zxxy("jae")
pat cmu zgt $1==8 call cmx8zxxn("jb")
pat cms zne $1==8
with regorconst regorconst rm rm STACK
gen cmp %3,%1
@ -2825,6 +3074,11 @@ with BXREG ACC
kills ALL
gen jmp {label, ".csa4"}
pat csa $1==8
with BXREG ACC DXREG
kills ALL
gen jmp {label, ".csa8"}
pat csa !defined($1)
with rm-BXREG-ACC BXREG ACC
kills ALL
@ -2837,6 +3091,11 @@ with BXREG ACC
kills ALL
gen jmp {label, ".csb4"}
pat csb $1==8
with BXREG ACC DXREG
kills ALL
gen jmp {label, ".csb8"}
pat csb !defined($1)
with rm-BXREG-ACC BXREG ACC
gen cmp %1,{ANYCON,4}

View file

@ -32,12 +32,12 @@ void con_part(int sz, word w)
part_size += sz;
}
void con_mult(sz) word sz;
{
void
con_mult(word sz) {
if (argval != 4)
if (sz != 4 && sz != 8)
fatal("bad icon/ucon size");
fprintf(codefile, ".data4\t%ld\n", atol(str));
fprintf(codefile,".data%d\t%s\n", (int)sz, str);
}
#define CODE_GENERATOR

View file

@ -12,9 +12,6 @@
#define RELOCATION /* generate relocation info */
#define DEBUG 0
#undef valu_t
#define valu_t long
#undef ALIGNWORD
#define ALIGNWORD 2
#undef ALIGNSECT

View file

@ -33,14 +33,11 @@ con_part(sz,w) register sz; word w; {
}
void
con_mult(sz) word sz; {
long l;
con_mult(word sz) {
if (sz != 4)
if (sz != 4 && sz != 8)
fatal("bad icon/ucon size");
l = atol(str);
fprintf(codefile,"\t.data2 %d,%d\n",
(int)l&0xFFFF,(int)(l>>16)&0xFFFF);
fprintf(codefile,".data%d\t%s\n", (int)sz, str);
}
#define CODE_GENERATOR

View file

@ -14,8 +14,6 @@
#define RELOCATION /* generate relocatable code */
#define DEBUG 0
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long

View file

@ -83,6 +83,6 @@
%type <y_word> bcdx op_ea regs rrange
%type <y_word> reg sizedef sizenon creg
%type <y_word> off_width abs31 bd_areg_index
%type <y_word> off_width off31 wid31 bd_areg_index
%type <y_word> areg_index areg scale cp_cond fc mask
%type <y_word> fsize fregs fcregs frlist frrange

View file

@ -68,8 +68,8 @@
{0, BITFIELD, 0166300, "bfclr"},
{0, BITFIELD, 0167300, "bfset"},
{0, BF_TO_D, 0164700, "bfextu"},
{0, BF_TO_D, 0164700, "bfexts"},
{0, BF_TO_D, 0164700, "bfffo"},
{0, BF_TO_D, 0165700, "bfexts"},
{0, BF_TO_D, 0166700, "bfffo"}, /* not 0164700 */
{0, BFINS, 0167700, "bfins"},
{0, SHIFT, 0160340, "asr"},

View file

@ -225,12 +225,17 @@ creg : CREG
off_width /* note: these should be curly brackets, but that would
* leave us without brackets for expressions.
*/
: '[' abs31 ':' abs31 ']'
: '[' off31 ':' wid31 ']'
{ $$ = ($2<<6) | $4;
}
;
abs31 : DREG { $$ = 040 | $1;}
| absexp { fit(fit5($1));
off31 : DREG { $$ = 040 | $1;}
| absexp { fit(fit5($1)); /* 0 to 31 */
$$ = low5($1);
}
;
wid31 : DREG { $$ = 040 | $1;}
| absexp { fit(fit5($1) - 1); /* 1 to 32 */
$$ = low5($1);
}
;

View file

@ -2,7 +2,7 @@ for _, plat in ipairs(vars.plats) do
acklibrary {
name = "lib_"..plat,
srcs = {
"./*.s",
"./*.s", -- csb8.s
"./*.c"
},
vars = { plat = plat },

View file

@ -13,12 +13,19 @@
sub.l d0, sp ! pop extra bytes
jmp (a0)
1:
clr.l d1
tst.l (sp)
bne 4f
not.l d1 ! d1 contains sign of source
4:
asr.l #2, d0
move.l (sp), d1
lsr.l #1, d0
bcs 1f ! branch if source size == 1
lsr.l #1, d0
bcs 2f ! branch if source size == 2
tst.l d1
bra 4f
1: lsr.l #1, d0 ! size difference / 4
ext.w d1
2: ext.l d1
move.l d1, (sp)
4: slt d1
extb.l d1 ! d1 contains sign of source
sub.l #1, d0
2:
move.l d1, -(sp)

39
mach/m68020/libem/csa8.s Normal file
View file

@ -0,0 +1,39 @@
.define .csa8
.sect .text
.sect .rom
.sect .data
.sect .bss
ECASE=20
.sect .text
.csa8:
! jump table address in a0
! index in (sp)
move.l (a0)+, a1 ! default address
move.l (sp)+, d0
move.l (sp)+, d1 ! index
move.l (a0)+, d2
sub.l (a0)+, d1
subx.l d2, d0 ! index - lower bound in d0:d1
move.l d1, a2
move.l (a0)+, d2
move.l (a0)+, d1 ! upper - lower bound
sub.l a2, d1
subx.l d0, d2 ! upper - index
bcs 1f
move.l a2, d1
! assuming d0:d1 < 65536
move.l (a0,d1.l*4), d1 ! jump address
beq 1f
move.l d1,a1
jmp (a1)
1:
move.l a1, d0
beq 2f
jmp (a1) ! jump to specified address
2:
move.l #ECASE, -(sp)
jmp (.fatal)
.align 2

39
mach/m68020/libem/csb8.s Normal file
View file

@ -0,0 +1,39 @@
.define .csb8
.sect .text
.sect .rom
.sect .data
.sect .bss
ECASE=20
.sect .text
.csb8:
! case descriptor in a0
! index in (sp)
move.l (a0)+, a1 ! default jump address
move.l (sp)+, d2
move.l (sp), a2 ! index in d2:a2
move.l d7, (sp)
add.l #4, a0
move.l (a0)+, d1 ! # entries (assuming <= 65536)
beq 3f
sub.l #1, d1
1:
move.l (a0)+, d0
move.l (a0)+, d7 ! descriptor's index in d0:d7
add.l #4, a0
sub.l a2, d7
subx.l d2, d0 ! descriptor's index - our index
dbeq d1, 1b
bne 3f
move.l (-4,a0), a1 ! jump address
3:
move.l (sp)+, d7 ! caller's d7
move.l a1, d0
beq 4f
jmp (a1)
4:
move.l #ECASE, -(sp)
jmp (.fatal)
.align 2

View file

@ -0,0 +1,76 @@
.define .divrem8
.sect .text
.sect .rom
.sect .data
.sect .bss
yh=16
yl=20
xh=24
xl=28
! This private sub for .dvi8, .dvu8, .rmi8, .rmu8
! does unsigned division of x = xh:xl by y = yh:yl,
! yields d0:d1 = quotient, d2:d3 = remainder.
.sect .text
.divrem8:
! Caller must set d0, d1 like so:
! mov.l (xh, sp), d0
! mov.l (yh, sp), d1
tst.l d1
bne 1f ! branch if y >= 2**32
! y = yl, so x / y = xh:xl / yl = qh:0 + rh:xl / yl
! where qh, rh are quotient, remainder from xh / yl.
move.l (xl, sp), d1
move.l (yl, sp), d2
clr.l d3 ! d3:d0 = xh
divu.l d2, d3:d0 ! d0 = 0:xh / yl, d3 = rh
divu.l d2, d3:d1 ! d1 = rh:xl / yl, so d0:d1 = x / y
clr.l d2 ! remainder in d2:d3
rts
1: ! Here y >= 2**32.
move.l d0, a0 ! save xh
move.l d1, a1 ! save yh
move.l d7, a2 ! save caller's d7
! Find y >> right in [2**31, 2**32).
move.l (yl, sp), d2
bfffo d1[0:32], d3 ! find highest set bit in yh
lsl.l d3, d1 ! shift yh left
bset #5, d3
neg.l d3 ! right = (32 - left) modulo 64
lsr.l d3, d2 ! shift yl right
or.l d1, d2 ! d2 = y >> right
! Estimate x / y as q = (x / (y >> right)) >> right.
move.l (xl, sp), d1
clr.l d7
divu.l d2, d7:d0
divu.l d2, d7:d1 ! d0:d1 = x / (y >> right)
lsr.l d3, d1
bset #5, d3
neg.l d3
lsl.l d3, d0
or.l d0, d1 ! d1 = q
! Calculate the remainder x - y * q. If the subtraction
! overflows, then the correct quotient is q - 1, else it is q.
move.l a1, d3 ! yh
mulu.l d1, d3 ! yh * q
move.l (yl, sp), d7
mulu.l d1, d0:d7 ! yl * q
add.l d3, d0 ! d0:d7 = y * q
move.l (xl, sp), d3
move.l a0, d2 ! d2:d3 = x
sub.l d7, d3
subx.l d0, d2 ! d2:d3 = x - y * q
bcc 1f ! branch unless subtraction overflowed
sub.l #1, d1 ! fix quotient
move.l a1, d7 ! yh
add.l (yl, sp), d3
addx.l d7, d2 ! fix remainder
1: clr.l d0 ! d0:d1 = quotient
move.l a2, d7 ! restore caller's d7
rts

34
mach/m68020/libem/dvi8.s Normal file
View file

@ -0,0 +1,34 @@
.define .dvi8
.sect .text
.sect .rom
.sect .data
.sect .bss
yh=8
yl=12
xh=16
xl=20
! .dvi8 yields d0:d1 = quotient from x / y
.sect .text
.dvi8:
move.l d3, -(sp) ! preserve caller's d3
clr.l d2 ! d2 = 0, non-negative result
move.l (xh, sp), d0 ! d0 for .divrem8
bge 1f
move.l #1, d2 ! d2 = 1, negative result
neg.l (xl, sp)
negx.l d0 ! x = absolute value
1: move.l (yh, sp), d1 ! d1 for .divrem8
bge 1f
bchg #0, d2 ! flip sign of result
neg.l (yl, sp)
negx.l d1 ! y = absolute value
1: move.l d2, -(sp)
jsr (.divrem8)
move.l (sp)+, d2
beq 1f ! branch unless result < 0
neg.l d1
negx.l d0 ! negate quotient d0:d1
1: move.l (sp)+, d3
rtd #16

20
mach/m68020/libem/dvu8.s Normal file
View file

@ -0,0 +1,20 @@
.define .dvu8
.sect .text
.sect .rom
.sect .data
.sect .bss
yh=8
xh=16
! .dvu8 yields d0:d1 = quotient from x / y
.sect .text
.dvu8:
move.l d3, -(sp) ! preserve caller's d3
move.l (xh, sp), d0
move.l (yh, sp), d1
sub.l #4, sp
jsr (.divrem8)
add.l #4, sp
move.l (sp)+, d3
rtd #16

35
mach/m68020/libem/rmi8.s Normal file
View file

@ -0,0 +1,35 @@
.define .rmi8
.sect .text
.sect .rom
.sect .data
.sect .bss
yh=8
yl=12
xh=16
xl=20
! .rmi8 yields d0:d1 = remainder from x / y
.sect .text
.rmi8:
move.l d3, -(sp) ! preserve caller's d3
clr.l d2 ! d2 = 0, non-negative result
move.l (xh, sp), d0 ! d0 for .divrem8
bge 1f
move.l #1, d2 ! d2 = 1, negative result
neg.l (xl, sp)
negx.l d0 ! x = absolute value
1: move.l (yh, sp), d1 ! d1 for .divrem8
bge 1f
neg.l (yl, sp)
negx.l d1 ! y = absolute value
1: move.l d2, -(sp)
jsr (.divrem8)
move.l (sp)+, d0
beq 1f ! branch unless result < 0
neg.l d3
negx.l d2 ! negate quotient d3:d2
1: move.l d3, d1
move.l d2, d0
move.l (sp)+, d3
rtd #16

22
mach/m68020/libem/rmu8.s Normal file
View file

@ -0,0 +1,22 @@
.define .rmu8
.sect .text
.sect .rom
.sect .data
.sect .bss
yh=8
xh=16
! .rmu8 yields d0:d1 = remainder from x / y
.sect .text
.rmu8:
move.l d3, -(sp) ! preserve caller's d3
move.l (xh, sp), d0
move.l (yh, sp), d1
sub.l #4, sp
jsr (.divrem8)
add.l #4, sp
move.l d3, d1
move.l d2, d0
move.l (sp)+, d3
rtd #16

View file

@ -45,11 +45,11 @@ con_part(sz,w) register sz; word w; {
}
void
con_mult(sz) word sz; {
con_mult(word sz) {
if (sz != 4)
if (sz != 8)
fatal("bad icon/ucon size");
fprintf(codefile,".data4 %s\n",str);
fprintf(codefile,".data8\t%s\n", str);
}
#define IEEEFLOAT

View file

@ -612,6 +612,7 @@ add_l "add.l" conreg4:ro, alterable4:rw:cc cost(2,6).
add_w "add.w" any2:ro, D_REG+LOCAL:rw:cc cost(2,3).
add_w "add.w" conreg2:ro, alterable2:rw:cc cost(2,6).
#endif
addx_l "addx.l" D_REG4:ro, D_REG4:rw kills :cc cost(2,3).
and_l "and.l" data4:ro, D_REG4:rw:cc cost(2,3).
and_l "and.l" D_REG4:ro, memalt4:rw:cc cost(2,6).
and_l "and.l" consts4:ro, datalt4:rw:cc cost(2,6).
@ -628,6 +629,7 @@ asr "asr #1," memalt2:rw:cc cost(2,4).
asl_w "asl.w" shconreg:ro, D_REG:rw:cc cost(2,5).
asr_w "asr.w" shconreg:ro, D_REG:rw:cc cost(2,4).
#endif
bchg const:ro, D_REG:rw kills:cc cost(2,4).
bclr const:ro, D_REG:rw kills:cc cost(2,4).
bra label cost(2,5).
bcc label cost(2,5).
@ -671,14 +673,15 @@ eor_l "eor.l" conreg4:ro, datalt4:rw:cc cost(2,6).
#if WORD_SIZE==2
eor_w "eor.w" conreg2:ro, datalt2:rw:cc cost(2,4).
#endif
exg genreg4:rw, genreg4:rw cost(2,3).
/* in the next two instructions: LOCAL only allowed if register var */
ext_l "ext.l" D_REG+LOCAL+D_REG4:rw:cc cost(2,2).
ext_w "ext.w" D_REG+LOCAL+D_REG4:rw:cc cost(2,2).
jmp address+control4 cost(2,0).
jsr address+control4 kills :cc d0 d1 d2 a0 a1 cost(2,3).
lea address+control4:ro, A_REG+areg:wo cost(2,0).
lsl_l "lsl.l" shconreg:ro, D_REG4:rw:cc cost(2,4).
/*
lsl_l "lsl.l" shconreg:ro, D_REG:rw:cc cost(2,4).
lsl "lsl #1," memalt2:rw:cc cost(2,4).
*/
lsr_l "lsr.l" shconreg:ro, D_REG4:rw:cc cost(2,4).
@ -709,6 +712,8 @@ neg_l "neg.l" memory4:rw:cc cost(2,6).
#if WORD_SIZE==2
neg_w "neg.w" memory2:rw:cc cost(2,6).
#endif
negx_l "negx.l" D_REG4:rw:cc cost(2,3).
negx_l "negx.l" memory4:rw:cc cost(2,6).
not_l "not.l" D_REG4:rw:cc cost(2,3).
not_l "not.l" memory4:rw:cc cost(2,6).
#if WORD_SIZE==2
@ -733,6 +738,7 @@ ror_w "ror.w" shconreg:ro, D_REG:rw:cc cost(2,4).
#endif
roxl "roxl #1," memalt2:rw:cc cost(2,4).
roxr "roxr #1," memalt2:rw:cc cost(2,4).
slt datalt1:rw cost(2,3).
sne datalt1:rw cost(2,3).
sub_l "sub.l" any4:ro, D_REG4:rw:cc cost(2,3).
sub_l "sub.l" any4+areg:ro, A_REG+areg:rw cost(2,3).
@ -740,6 +746,9 @@ sub_l "sub.l" conreg4:ro, alterable4:rw:cc cost(2,6).
#if WORD_SIZE==2
sub_w "sub.w" any2:ro, D_REG+LOCAL:rw:cc cost(2,3).
sub_w "sub.w" conreg2:ro, alterable2:rw:cc cost(2,6).
#endif
subx_l "subx.l" D_REG4:ro, D_REG4:rw kills :cc cost(2,3).
#if WORD_SIZE==2
/* On a swap, we only want the lower part of D_REG, so don't set cc */
swap D_REG:rw kills :cc cost(2,2).
#endif
@ -773,6 +782,7 @@ divs_l "divs.l" data4:ro, D_REG4:rw:cc cost(2,90).
divu_l "divu.l" data4:ro, D_REG4:rw:cc cost(2,78).
divsl_l "divsl.l" data4:ro, DREG_pair:rw kills :cc cost(2,90).
divul_l "divul.l" data4:ro, DREG_pair:rw kills :cc cost(2,78).
mulu_l "mulu.l" data4:ro, DREG_pair:rw kills :cc cost(2,44).
pea address+control4+regX cost(2,4).
#if WORD_SIZE==2
cmp2_w "cmp2.w" address+control2:ro, genreg2:ro kills :cc cost(2,18).
@ -3796,6 +3806,18 @@ with exact any4 STACK
gen add_l {post_inc4, sp}, %a
yields %a
pat adi $1==8
with exact any4 any4 DD_REG4 DD_REG4
uses reusing %1, DD_REG4 = %1
gen add_l %2, %4
addx_l %a, %3 yields %4 %3
with DD_REG4 DD_REG4 D_REG4 any4
gen add_l %4, %2
addx_l %3, %1 yields %2 %1
with DD_REG4 DD_REG4 D_REG4 STACK
gen add_l {post_inc4, sp}, %2
addx_l %3, %1 yields %2 %1
#if WORD_SIZE==2
pat sbi $1==2
with any2-bconst DD_REG
@ -3822,6 +3844,12 @@ with exact any4 STACK
with any4-bconst4 AA_REG
gen sub_l %1, %2 yields %2
pat sbi $1==8
with D_REG4 any4-D_REG4 DD_REG4 DD_REG4
/* only 3 of DD_REG4; may unstack %2 into AA_REG */
gen sub_l %2, %4
subx_l %1, %3 yields %4 %3
#if WORD_SIZE==2
pat loc loc cii ldc mli $1==2 && $2==4 && highw($4)==0 && loww($4)>0 && $5==4
with any2-pre_post
@ -3847,6 +3875,34 @@ with STACK
yields dl1
#endif
#ifdef TBL68020
pat mli $1==8
with exact data4 data4 DD_REG4 DD_REG4 /* yh yl xh xl */
uses DD_REG4 = %4
gen mulu_l %1, %a /* xl * yh */
mulu_l %2, %3 /* xh * yl */
add_l %3, %a
mulu_l %2, {DREG_pair, %3, %4} /* xl * yl */
add_l %a, %3
yields %4 %3
with DD_REG4 DD_REG4 data4 data4 /* yh yl xh xl */
uses DD_REG = %2
gen mulu_l %3, %a /* yl * xh */
mulu_l %4, %1 /* yh * xl */
add_l %1, %a
mulu_l %4, {DREG_pair, %1, %2} /* yl * xl */
add_l %a, %1
yields %2 %1
with DD_REG4 DD_REG4 STACK /* yh yl xh xl */
uses DD_REG4 = %2
gen mulu_l {post_inc4, sp}, %a /* yl * xh */
mulu_l {indirect4, sp}, %1 /* yh * xl */
add_l %1, %a
mulu_l {post_inc4, sp}, {DREG_pair, %1, %2} /* yl * xl */
add_l %a, %1
yields %2 %1
#endif /* TBL68020 */
#if WORD_SIZE==2
pat dvi $1==2
with data2-sconsts DD_REG
@ -3866,6 +3922,14 @@ with STACK
yields dl1
#endif /* TBL68020 */
#ifdef TBL68020
pat dvi $1==8
with STACK
kills ALL
gen jsr {absolute4, ".dvi8"}
yields dl1 dl0
#endif /* TBL68020 */
#if WORD_SIZE==2
pat rmi $1==2
with data2-sconsts DD_REG
@ -3891,6 +3955,14 @@ with STACK
yields dl2
#endif /* TBL68020 */
#ifdef TBL68020
pat rmi $1==8
with STACK
kills ALL
gen jsr {absolute4, ".rmi8"}
yields dl1 dl0
#endif /* TBL68020 */
#if WORD_SIZE==2
pat ngi $1==2
with DD_REG
@ -3901,6 +3973,11 @@ pat ngi $1==4
with DD_REG4
gen neg_l %1 yields %1
pat ngi $1==8
with DD_REG4 DD_REG4
gen neg_l %2
negx_l %1 yields %2 %1
#if WORD_SIZE==2
pat sli $1==2
with shconreg DD_REG
@ -3911,6 +3988,43 @@ pat sli $1==4
with shconreg DD_REG4
gen asl_l %1, %2 yields %2
pat sli $1==8
with DD_REG4 DD_REG4 DD_REG4
uses AA_REG = %3 /* no 4th DD_REG */
gen lsl_l %1, %3
lsl_l %1, %2 /* shift by %1 modulo 64 */
bchg {const, 5}, %1
bne {slabel, 1f} /* jump if shift >= 32 */
neg_l %1
exg %a, %3
lsr_l %1, %3 /* (32 - shift) modulo 64 */
or_l %3, %2 /* shift bits from %3 to %2 */
move %a, %3
bra {slabel, 2f}
1:
move %a, %2
lsl_l %1, %2 /* (shift - 32) modulo 64 */
2: yields %3 %2
pat loc sli ($1&32)==0 && $2==8
with DD_REG4 DD_REG4
uses AA_REG = %2, DD_REG = {bconst, $1&31}
gen lsl_l %b, %2
lsl_l %b, %1
bset {const, 5}, %b
neg_l %b
exg %a, %2
lsr_l %b, %2
or_l %2, %1
move %a, %2
yields %2 %1
pat loc sli ($1&63)==32 && $2==8
with any4 any4 yields {zero_const, 0} %2
pat loc sli ($1&32)!=0 && $2==8
with any4 DD_REG4
uses reusing %1, DD_REG = {bconst, $1&31}
gen lsl_l %a, %2 yields {zero_const, 0} %2
#if WORD_SIZE==2
pat sri $1==2
with shconreg DD_REG
@ -3921,6 +4035,43 @@ pat sri $1==4
with shconreg DD_REG4
gen asr_l %1, %2 yields %2
pat sri $1==8
with DD_REG4 DD_REG4 DD_REG4
uses AA_REG = %2 /* no 4th DD_REG */
gen asr_l %1, %2
lsr_l %1, %3 /* shift by %1 modulo 64 */
bchg {const, 5}, %1
bne {slabel, 1f} /* jump if shift >= 32 */
neg_l %1
exg %a, %2
lsl_l %1, %2 /* (32 - shift) modulo 64 */
or_l %2, %3 /* shift bits from %2 to %3 */
move %a, %2
bra {slabel, 2f}
1:
move %a, %3
asr_l %1, %3 /* (shift - 32) modulo 64 */
2: yields %3 %2
pat loc sri ($1&32)==0 && $2==8
with DD_REG4 DD_REG4
uses AA_REG = %1, DD_REG = {bconst, $1&31}
gen asr_l %b, %1
lsr_l %b, %2
bset {const, 5}, %b
neg_l %b
exg %a, %1
lsl_l %b, %1
or_l %1, %2
move %a, %1
yields %2 %1
pat loc sri ($1&63)==32 && $2==8
with DD_REG4 any4 yields %1 leaving loc 4 loc 8 cii
pat loc sri ($1&32)!=0 && $2==8
with DD_REG4 any4
uses reusing %2, DD_REG = {bconst, $1&31}
gen asr_l %a, %1 yields %1 leaving loc 4 loc 8 cii
/************************************************
* Group 4: unsigned arithmetic. *
************************************************/
@ -3947,6 +4098,8 @@ with STACK
yields dl1
#endif /* TBL68020 */
pat mlu $1==8 leaving mli 8
#if WORD_SIZE==2
pat dvu $1==2
with data2-sconsts data2
@ -3966,6 +4119,14 @@ with STACK
yields dl1
#endif /* TBL68020 */
#ifdef TBL68020
pat dvu $1==8
with STACK
kills ALL
gen jsr {absolute4, ".dvu8"}
yields dl1 dl0
#endif /* TBL68020 */
#if WORD_SIZE==2
pat rmu $1==2
with data2-sconsts data2
@ -3992,8 +4153,18 @@ with STACK
yields dl2
#endif /* TBL68020 */
#ifdef TBL68020
pat rmu $1==8
with STACK
kills ALL
gen jsr {absolute4, ".rmu8"}
yields dl1 dl0
#endif /* TBL68020 */
pat slu leaving sli $1
pat loc slu $2==8 leaving loc $1 sli 8
#if WORD_SIZE==2
pat sru $1==2
with shconreg DD_REG
@ -4004,6 +4175,43 @@ pat sru $1==4
with shconreg DD_REG4
gen lsr_l %1, %2 yields %2
pat sru $1==8
with DD_REG4 DD_REG4 DD_REG4
uses AA_REG = %2 /* no 4th DD_REG */
gen lsr_l %1, %2
lsr_l %1, %3 /* shift by %1 modulo 64 */
bchg {const, 5}, %1
bne {slabel, 1f} /* jump if shift >= 32 */
neg_l %1
exg %a, %2
lsl_l %1, %2 /* (32 - shift) modulo 64 */
or_l %2, %3 /* shift bits from %2 to %3 */
move %a, %2
bra {slabel, 2f}
1:
move %a, %3
lsr_l %1, %3 /* (shift - 32) modulo 64 */
2: yields %3 %2
pat loc sru ($1&32)==0 && $2==8
with DD_REG4 DD_REG4
uses AA_REG = %2, DD_REG = {bconst, $1&31}
gen lsr_l %b, %1
lsr_l %b, %2
bset {const, 5}, %b
neg_l %b
exg %a, %1
lsl_l %b, %1
or_l %1, %2
move %a, %1
yields %2 %1
pat loc sru ($1&63)==32 && $2==8
with any4 any4 yields %1 {zero_const, 0}
pat loc sru ($1&32)!=0 && $2==8
with DD_REG4 any4
uses reusing %2, DD_REG = {bconst, $1&31}
gen lsr_l %a, %1 yields %1 {zero_const, 0}
/************************************************
* Group 5: floating point arithmetic *
************************************************/
@ -4753,6 +4961,17 @@ with exact any_int STACK
uses reusing %1,DD_REG=%1
gen xxx* {post_inc_int, sp}, %a yields %a
proc log8 example and
with exact data4 data4 DD_REG4 DD_REG4
gen xxx* %1, %3
xxx* %2, %4 yields %4 %3
with DD_REG4 DD_REG4 data4 data4
gen xxx* %3, %1
xxx* %4, %2 yields %2 %1
with DD_REG4 DD_REG4 STACK
gen xxx* {post_inc4, sp}, %1
xxx* {post_inc4, sp}, %2 yields %2 %1
proc logdef example and
with STACK
uses DD_REG4 = {const, $1/WORD_SIZE -1},
@ -4813,6 +5032,7 @@ pat and $1==WORD_SIZE call logw(AND_I)
#if WORD_SIZE==2
pat and $1==2*WORD_SIZE call log2w("and.l")
#endif
pat and $1==8 call log8("and.l")
pat and $1>4 && $1/WORD_SIZE<=65536 call logdef(AND_I)
pat and defined($1) call logbdef(AND_I)
pat and !defined($1) call logndef(AND_I)
@ -4821,6 +5041,7 @@ pat ior $1==WORD_SIZE call logw(OR_I)
#if WORD_SIZE==2
pat ior $1==2*WORD_SIZE call log2w("or.l")
#endif
pat ior $1==8 call log8("or.l")
pat ior $1>2 && $1/WORD_SIZE<=65536 call logdef(OR_I)
pat ior defined($1) call logbdef(OR_I)
pat ior !defined($1) call logndef(OR_I)
@ -4835,6 +5056,21 @@ pat xor $1==4
with DD_REG4 conreg4-bconst4
gen eor_l %2, %1 yields %1
pat xor $1==8
with exact any4 any4 DD_REG4 DD_REG4
uses reusing %1, DD_REG4 = %1
gen eor_l %a, %3
move %2, %a
eor_l %a, %4 yields %4 %3
with DD_REG4 DD_REG4 D_REG4 any4
gen eor_l %3, %1
move %4, %3
eor_l %3, %2 yields %2 %1
with DD_REG4 DD_REG4 DD_REG4 STACK
gen eor_l %3, %1
move_l {post_inc4, sp}, %3
eor_l %3, %2 yields %2 %1
pat xor $1>4 && $1/WORD_SIZE<=65536 call logdef(EOR_I)
pat xor defined($1) call logbdef(EOR_I)
pat xor !defined($1) call logndef(EOR_I)
@ -4907,6 +5143,50 @@ pat rol $1==4
with shconreg DD_REG4
gen rol_l %1, %2 yields %2
pat rol $1==8
with DD_REG4 DD_REG4 DD_REG4
uses AA_REG, AA_REG /* no 4th DD_REG */
gen bclr {const, 5}, %1
beq {slabel, 1f}
exg %2, %3 /* rotate left 32 */
1:
move %2, %a
move %3, %b
lsl_l %1, %2
lsl_l %1, %3
bset {const, 5}, %1
neg_l %1 /* (32 - shift) modulo 64 */
exg %a, %2
lsr_l %1, %2
or_l %2, %3 /* rotate bits from %2 to %3 */
move %a, %2
exg %b, %3
lsr_l %1, %3
or_l %3, %2 /* rotate bits from %3 to %2 */
move %b, %3
yields %3 %2
pat loc rol ($1&32)==0 && $2==8
with DD_REG4 DD_REG4
uses AA_REG, AA_REG, DD_REG = {bconst, $1&31}
gen move %1, %a
move %2, %b
lsl_l %c, %1
lsl_l %c, %2
bset {const, 5}, %c
neg_l %c
exg %a, %1
lsr_l %c, %1
or_l %1, %2
move %a, %1
exg %b, %2
lsr_l %c, %2
or_l %2, %1
move %b, %2
yields %2 %1
pat loc rol ($1&63)==32 && $2==8 leaving exg 4
pat loc rol ($1&32)!=0 && $2==8 leaving loc (0-$1)&31 ror 8
#if WORD_SIZE==2
pat ror $1==2
with shconreg DD_REG
@ -4917,6 +5197,50 @@ pat ror $1==4
with shconreg DD_REG4
gen ror_l %1, %2 yields %2
pat ror $1==8
with DD_REG4 DD_REG4 DD_REG4
uses AA_REG, AA_REG /* no 4th DD_REG */
gen bclr {const, 5}, %1
beq {slabel, 1f}
exg %2, %3 /* rotate right 32 */
1:
move %2, %a
move %3, %b
lsr_l %1, %2
lsr_l %1, %3
bset {const, 5}, %1
neg_l %1 /* (32 - shift) modulo 64 */
exg %a, %2
lsl_l %1, %2
or_l %2, %3 /* rotate bits from %2 to %3 */
move %a, %2
exg %b, %3
lsl_l %1, %3
or_l %3, %2 /* rotate bits from %3 to %2 */
move %b, %3
yields %3 %2
pat loc ror ($1&32)==0 && $2==8
with DD_REG4 DD_REG4
uses AA_REG, AA_REG, DD_REG = {bconst, $1&31}
gen move %1, %a
move %2, %b
lsr_l %c, %1
lsr_l %c, %2
bset {const, 5}, %c
neg_l %c
exg %a, %1
lsl_l %c, %1
or_l %1, %2
move %a, %1
exg %b, %2
lsl_l %c, %2
or_l %2, %1
move %b, %2
yields %2 %1
pat loc ror ($1&63)==32 && $2==8 leaving exg 4
pat loc ror ($1&32)!=0 && $2==8 leaving loc (0-$1)&31 rol 8
@ -5733,6 +6057,11 @@ with any4 D_REG4+DLOCAL+const4+absolute4 STACK
move %2,dl0
jmp {absolute4, ".csa4"}
pat csa $1==8
with any4 STACK
gen move %1,a0
jmp {absolute4, ".csa8"}
#if WORD_SIZE==2
pat csb $1==2
#if TBL68020
@ -5755,6 +6084,11 @@ with any4 D_REG4+DLOCAL+const4+absolute4 STACK
move %2,dl0
jmp {absolute4, ".csb4"}
pat csb $1==8
with any4 STACK
gen move %1,a0
jmp {absolute4, ".csb8"}
pat dch leaving loi 4
#if WORD_SIZE==2
@ -6391,6 +6725,55 @@ pat cmu zge $1==WORD_SIZE call cmuzxx("bcc","bls")
pat cmu zgt $1==WORD_SIZE call cmuzxx("bhi","bcs")
proc cmx8txx example cmi tlt
with exact DD_REG4 DD_REG4 any4 any4
uses reusing %3, DD_REG4 = %3
gen sub_l %4, %2
subx_l %a, %1 /* keep overflow flag */
sxx[2] %1
neg_b %1 yields {dreg1, %1}
with D_REG4 any4-D_REG4 DD_REG4 DD_REG4
/* only 3 of DD_REG4; may unstack %2 into AA_REG */
gen sub_l %2, %4
subx_l %1, %3
sxx[1] %3
neg_b %3 yields {dreg1, %3}
pat cmi tlt $1==8 call cmx8txx("slt","sgt")
pat cmi tle $1==8 call cmx8txx("sle","sge")
pat cmi tge $1==8 call cmx8txx("sge","sle")
pat cmi tgt $1==8 call cmx8txx("sgt","slt")
pat cms teq $1==8 call cmx8txx("seq","seq")
pat cms tne $1==8 call cmx8txx("sne","sne")
pat cmu tlt $1==8 call cmx8txx("scs","shi")
pat cmu tle $1==8 call cmx8txx("sls","scc")
pat cmu tge $1==8 call cmx8txx("scc","sls")
pat cmu tgt $1==8 call cmx8txx("shi","scs")
proc cmx8zxx example cmi zlt
with exact DD_REG4 DD_REG4 any4 any4
kills ALL
uses reusing %3, DD_REG4 = %3
gen sub_l %4, %2
subx_l %a, %1
bxx[2] {llabel, $2}
with D_REG4 any4-D_REG4 DD_REG4 DD_REG4 STACK
gen sub_l %2, %4
subx_l %1, %3
bxx[1] {llabel, $2}
pat cmi zlt $1==8 call cmx8zxx("blt","bgt")
pat cmi zle $1==8 call cmx8zxx("ble","bge")
pat cmi zge $1==8 call cmx8zxx("bge","ble")
pat cmi zgt $1==8 call cmx8zxx("bgt","blt")
pat cms zeq $1==8 call cmx8zxx("beq","beq")
pat cms zne $1==8 call cmx8zxx("bne","bne")
pat cmu zlt $1==8 call cmx8zxx("bcs","bhi")
pat cmu zle $1==8 call cmx8zxx("bls","bcc")
pat cmu zge $1==8 call cmx8zxx("bcc","bls")
pat cmu zgt $1==8 call cmx8zxx("bhi","bcs")
#if TBL68881
proc cmf4zxx example cmf zlt
with FS_REG FS_REG
@ -6630,6 +7013,33 @@ uses reusing %1,DD_REG4
pat loc loc ciu $1==$2 /* skip this */
pat loc loc cui $1==$2 /* skip this */
pat loc loc cii $1==4 && $2==8
with exact test_set1+test_set2
yields %1 {zero_const, 0}
with test_set4
uses DD_REG4
gen test %1
slt {dreg1, %a}
#ifdef TBL68020
extb_l %a
#else
ext_w %a
ext_l %a
#endif
yields %1 %a
pat loc loc cii $1<4 && $2==8
leaving loc $1 loc 4 cii loc 4 loc 8 cii
pat loc loc ciu $1==4 && $2==8 yields {zero_const, 0}
pat loc loc cui $1==4 && $2==8 yields {zero_const, 0}
pat loc loc cuu $1==4 && $2==8 yields {zero_const, 0}
pat loc loc cii $1==8 && $2==4 leaving asp 4
pat loc loc ciu $1==8 && $2==4 leaving asp 4
pat loc loc cui $1==8 && $2==4 leaving asp 4
pat loc loc cuu $1==8 && $2==4 leaving asp 4
/* The following rules should be handled by the peephole optimizer, I think */

View file

@ -17,8 +17,6 @@
#define Xfit(f) if (!(f)) Xnofit();
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long

View file

@ -8,9 +8,6 @@
#define RELOCATION /* generate relocatable code */
#define DEBUG 0
#undef valu_t
#define valu_t int32_t
#undef ADDR_T
#define ADDR_T uint32_t

View file

@ -10,8 +10,6 @@
#define THREE_PASS /* branch and offset optimization */
#define LISTING /* enable listing facilities */
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long
#undef ALIGNSECT

View file

@ -10,9 +10,6 @@
#define RELOCATION /* generate relocatable code */
#define DEBUG 0
#undef valu_t
#define valu_t int32_t
#undef ADDR_T
#define ADDR_T uint32_t

View file

@ -41,12 +41,11 @@ con_part(int sz, word w)
}
void
con_mult(word sz)
{
con_mult(word sz) {
if (argval != 4)
if (sz != 8)
fatal("bad icon/ucon size");
fprintf(codefile,".data4 %s\n", str);
fprintf(codefile,".data8\t%s\n", str);
}
#define CODE_GENERATOR

View file

@ -58,7 +58,8 @@ _include <string.h>
#define GENLAB "I" /* compiler generated labels */
#define valu_t long /* type of expression values */
#define valu_t int64_t /* type of expression values */
#define uvalu_t uint64_t /* unsigned valu_t */
#define ADDR_T unsigned short /* type of dot */
#define word_t short /* type of keyword value */
/*

View file

@ -151,8 +151,9 @@ void emit1(int);
void emit2(int);
void emit4(long);
void emitx(valu_t, int);
void emitf(int size, int negative);
void emit8(int64_t);
void emitstr(int);
void emitf(int size, int negative);
void yyerror(const char *);
void nosect(void);
void fatal(const char *, ...);

View file

@ -38,15 +38,17 @@ static item_t *last_it, *o_it;
%token <y_valu> CODE1
%token <y_valu> CODE2
%token <y_valu> CODE4
%token NUMBER0 /* keep NUMBER* in this order */
%token NUMBER0 /* keep NUMBER[0-4] in this order */
%token NUMBER1
%token NUMBER2
%token NUMBER3
%token <y_valu> NUMBER
%token NUMBER4
%token <y_valu> NUMBER8
%token NUMBERF
%token DOT
%token EXTERN
%token <y_word> DATA
%token DATA8
%token <y_word> DATAF
%token <y_word> ASCII
%token SECTION
@ -105,7 +107,7 @@ program : /* empty */
#endif
| program IDENT ':'
{ newident($2, DOTTYP); newlabel($2);}
| program NUMBER ':'
| program NUMBER8 ':'
{ if ($2 < 0 || $2 > 9) {
serror("bad f/b label");
$2 = 0;
@ -121,8 +123,8 @@ program : /* empty */
| program operation ';'
| program operation '\n'
{ lineno++; LISTLINE(1); RELODONE;}
| program '#' NUMBER STRING '\n'
{ lineno = $3;
| program '#' NUMBER8 STRING '\n'
{ lineno = $3; /* long = int64_t */
if (modulename) strncpy(modulename, stringbuf, STRINGMAX-1);
LISTLINE(1); RELODONE;
}
@ -251,7 +253,8 @@ operation
DOTSCT->s_zero += $2;
}
| DATA datalist
| DATAF dataflist
| DATA8 data8list
| DATAF dataflist
| ASCII STRING
{ emitstr($1);}
;
@ -280,6 +283,13 @@ datalist
}
;
data8list
: absexp
{ emit8($1);}
| data8list ',' absexp
{ emit8($3);}
;
numberf
: NUMBERF
{
@ -300,8 +310,10 @@ expr : error
{ serror("expr syntax err");
$$.val = 0; $$.typ = S_UND;
}
| NUMBER
{ $$.val = $1; $$.typ = S_ABS;}
| NUMBER8
{ $$.val = $1; /* valu_t = int64_t */
$$.typ = S_ABS;
}
| id_fb
{ $$.val = load($1);
last_it = $1;

View file

@ -29,6 +29,7 @@ item_t keytab[] = {
{0, DATA, RELO1, ".data1"},
{0, DATA, RELO2, ".data2"},
{0, DATA, RELO4, ".data4"},
{0, DATA8, 0, ".data8"},
{0, DATAF, 4, ".dataf4"},
{0, DATAF, 8, ".dataf8"},
{0, ASCII, 0, ".ascii"},

View file

@ -101,7 +101,7 @@ int yylex(void)
void putval(int c)
{
valu_t v;
int64_t v;
int n = 0;
char* p = 0;
@ -110,14 +110,17 @@ void putval(int c)
{
case CODE1:
n = 1;
v = yylval.y_valu;
goto putnum;
case CODE2:
n = 2;
v = yylval.y_valu;
goto putnum;
case CODE4:
n = 4;
v = yylval.y_valu;
goto putnum;
case NUMBER:
case NUMBER8:
v = yylval.y_valu;
for (n = 0; n < sizeof(v); n++)
{
@ -125,12 +128,14 @@ void putval(int c)
break;
v >>= 8;
}
assert(n <= 4);
c = NUMBER0 + n;
if (n <= 4)
c = NUMBER0 + n;
else
n = 8;
v = yylval.y_valu;
putnum:
putc(c, tempfile);
putc(c >> 8, tempfile);
v = yylval.y_valu;
while (--n >= 0)
putc((int)(v >> (n * 8)), tempfile);
return;
@ -188,8 +193,8 @@ void putval(int c)
int getval(int c)
{
int64_t v;
int n = 0;
valu_t v;
char* p = 0;
switch (c)
@ -204,22 +209,26 @@ int getval(int c)
n = 4;
goto getnum;
case NUMBER0:
c = NUMBER;
c = NUMBER8;
goto getnum;
case NUMBER1:
n = 1;
c = NUMBER;
c = NUMBER8;
goto getnum;
case NUMBER2:
n = 2;
c = NUMBER;
c = NUMBER8;
goto getnum;
case NUMBER3:
n = 3;
c = NUMBER;
c = NUMBER8;
goto getnum;
case NUMBER:
case NUMBER4:
n = 4;
c = NUMBER8;
goto getnum;
case NUMBER8:
n = 8;
getnum:
v = 0;
while (--n >= 0)
@ -409,6 +418,7 @@ static void need_stringbuf()
static int innumber(int c)
{
uvalu_t uv;
char* p;
int radix;
static char num[40 + 1];
@ -450,7 +460,7 @@ static int innumber(int c)
}
if (radix != 16 && (c == 'f' || c == 'b'))
return (infbsym(num));
yylval.y_valu = 0;
uv = 0;
while ((c = *p++))
{
if (c > '9')
@ -458,9 +468,10 @@ static int innumber(int c)
c -= '0';
if ((unsigned)c >= radix)
serror("digit exceeds radix");
yylval.y_valu = yylval.y_valu * radix + c;
uv = uv * radix + c;
}
return (NUMBER);
yylval.y_valu = uv; /* signed = unsigned */
return (NUMBER8);
floatconstant:
do

View file

@ -336,6 +336,21 @@ void emitx(valu_t val, int n)
}
}
void emit8(int64_t arg)
{
#ifdef WORDS_REVERSED
emit2((int)(arg >> 48));
emit2((int)(arg >> 32));
emit2((int)(arg >> 16));
emit2((int)(arg));
#else
emit2((int)(arg));
emit2((int)(arg >> 16));
emit2((int)(arg >> 32));
emit2((int)(arg >> 48));
#endif
}
void emitstr(int zero)
{
int i;

View file

@ -12,8 +12,6 @@
#define LISTING
#define RELOCATION
#undef valu_t
#define valu_t long
#undef word_t
#define word_t long
#undef ADDR_T

View file

@ -10,9 +10,6 @@
#define RELOCATION /* generate relocatable code */
#define DEBUG 0
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long

View file

@ -29,11 +29,12 @@ void con_part(int sz, word w)
part_size += sz;
}
void con_mult(word sz)
{
if (argval != 4)
void
con_mult(word sz) {
if (sz != 8)
fatal("bad icon/ucon size");
fprintf(codefile,".data4 %s\n", str);
fprintf(codefile,".data8\t%s\n", str);
}
#define CODE_GENERATOR

View file

@ -14,7 +14,5 @@
#define ASLD
#undef ALIGNSECT
#define ALIGNSECT 2
#undef valu_t
#define valu_t long
#undef ADDR_T
#define ADDR_T long

View file

@ -154,9 +154,8 @@ if the number starts with '0x' it is hexadecimal else
if the number starts with '0' it is octal else
it's decimal.
.fi
The range of numbers depends on the machine.
A rule of the thumb is that the width of the machine's registers
the same is as the number of bits allowed in numbers.
The width of numbers is at least 64 bits, so the .data8 pseudo may
accept the full range of 8-byte values.
.IP comment
The character '!' denotes the start of comment, every character
up to the next newline is skipped.
@ -185,10 +184,10 @@ machine.
\&\\$1
.sp 1
..
.Pu ".extern \fIidentifier [, identifier]*\fP"
.Pu ".extern \fIidentifier\fP [, \fIidentifier\fP]*"
The identifiers mentioned in the list are exported and can be
used in other modules.
.Pu ".define \fIidentifier [, identifier]*\fP"
.Pu ".define \fIidentifier\fP [, \fIidentifier\fP]*"
Used for modules that are to be part of a libary.
The .define pseudo's should be the first in such modules.
When scanning a module in a library the assembler\-loader
@ -197,21 +196,25 @@ mentioned in a .define list. If so, it includes that module in
the program.
The identifiers mentioned in the list are exported and can be
used in other modules.
.Pu ".data1 \fIexpression [, expression]*\fP"
.Pu ".data1 \fIexpression\fP [, \fIexpression\fP]*"
Initialize a sequence of bytes.
This is not followed by automatic alignment.
.Pu ".data2 \fIexpression [, expression]*\fP"
.Pu ".data2 \fIexpression\fP [, \fIexpression\fP]*"
Initialize a sequence of shorts (2-byte values).
This is not followed by automatic alignment.
.Pu ".data4 \fIexpression [, expression]*\fP"
.Pu ".data4 \fIexpression\fP [, \fIexpression\fP]*"
Initialize a sequence of longs (4-byte values).
This is not followed by automatic alignment.
.Pu ".dataf4 \fIliteralfloat [, literalfloat]*\fP"
.Pu ".data8 \fIexpression\fP [, \fIexpression\fP]*"
Initialize a sequence of long longs (8-byte values).
The expressions must be absolute.
This is not followed by automatic alignment.
.Pu ".dataf4 \fIliteralfloat\fP [, \fIliteralfloat\fP]*"
Initialize a sequence of floats (4-byte values).
The values must be literal floating point constants containing
a dot character.
This is not followed by automatic alignment.
.Pu ".dataf8 \fIliteralfloat [, literalfloat]*\fP"
.Pu ".dataf8 \fIliteralfloat\fP [, \fIliteralfloat\fP]*"
Initialize a sequence of doubles (8-byte values).
The values must be literal floating point constants containing
a dot character.

View file

@ -6,7 +6,8 @@ plat_testsuite {
method = "plat/cpm/emu+emu",
skipsets = {
"b", -- B is broken on i80
"floats" -- floats aren't supported
"floats", -- floats aren't supported
"long-long",
},
tests = { "./*.c" },
}

View file

@ -10,6 +10,8 @@ var s=2
var sa={s}
var l={w}
var la={w}
var q=8
var qa=4
var f={w}
var fa={w}
var d=8
@ -19,11 +21,12 @@ var xa={x}
var ARCH=i386
var PLATFORM=linux386
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
var CPP_F=-D__unix
var CPP_F=-D__unix -D_EM_LLSIZE={q}
var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x08048054
var C_LIB={PLATFORMDIR}/libc-ansi.a
# bitfields reversed for compatibility with (g)cc.
var CC_ALIGN=-Vr
# long long enabled.
var CC_ALIGN=-Vrq{q}.{qa}
var OLD_C_LIB={C_LIB}
var MACHOPT_F=-m10
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr

View file

@ -10,6 +10,8 @@ var s=2
var sa={s}
var l={w}
var la={w}
var q=8
var qa=4
var f={w}
var fa={w}
var d=8
@ -19,11 +21,12 @@ var xa={x}
var ARCH=m68020
var PLATFORM=linux68k
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
var CPP_F=-D__unix -D__mc68020 -D__m68k -D__mc68000 -D__M68020
var CPP_F=-D__unix -D__mc68020 -D__m68k -D__mc68000 -D__M68020 -D_EM_LLSIZE={q}
var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x08000054
var C_LIB={PLATFORMDIR}/libc-ansi.a
# bitfields reversed for compatibility with (g)cc.
var CC_ALIGN=-Vr
# long long enabled.
var CC_ALIGN=-Vrq{q}.{qa}
var OLD_C_LIB={C_LIB}
var MACHOPT_F=-ml10
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr

View file

@ -4,5 +4,7 @@ plat_testsuite {
name = "tests",
plat = "linux68k",
method = "plat/linux68k/emu+emu68k",
skipsets = {"floats"}, -- FPU instructions not supported by emulator
skipsets = {
"floats", -- FPU instructions not supported by emulator
},
}

View file

@ -4,5 +4,7 @@ plat_testsuite {
name = "tests",
plat = "linuxmips",
method = "qemu-mipsel",
-- skipsets = {"m2"},
skipsets = {
"long-long",
},
}

View file

@ -3,5 +3,8 @@ include("tests/plat/build.lua")
plat_testsuite {
name = "tests",
plat = "linuxppc",
method = "plat/linuxppc/emu+emuppc"
method = "plat/linuxppc/emu+emuppc",
skipsets = {
"long-long",
},
}

View file

@ -8,6 +8,8 @@ var s=2
var sa={s}
var l={w}
var la={w}
var q=8
var qa=4
var f={w}
var fa={w}
var d=8
@ -17,11 +19,12 @@ var xa={x}
var ARCH=i386
var PLATFORM=osx386
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
var CPP_F=-D__unix
var CPP_F=-D__unix -D_EM_LLSIZE={q}
var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x123c
var C_LIB={PLATFORMDIR}/libc-ansi.a
# bitfields reversed for compatibility with (g)cc.
var CC_ALIGN=-Vr
# long long enabled.
var CC_ALIGN=-Vrq{q}.{qa}
var OLD_C_LIB={C_LIB}
var MACHOPT_F=-m10
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr

View file

@ -4,5 +4,8 @@ plat_testsuite {
name = "tests",
plat = "pc86",
method = "plat/pc86/emu+pc86emu",
skipsets = {"floats"}, -- FPU instructions not supported by emulator
skipsets = {
"floats", -- FPU instructions not supported by emulator
"long-long",
},
}

View file

@ -1,10 +1,12 @@
include("plat/build.lua")
definerule("plat_testsuite",
{
plat = { type="string" },
method = { type="string" },
sets = { type="table", default={"core", "b", "bugs", "m2", "floats"}},
-- added long-long/llswitch_e.c
sets = { type="table", default={"core", "b", "bugs", "m2", "floats", "long-long"}},
skipsets = { type="table", default={}},
tests = { type="targets", default={} },
},

View file

@ -1,5 +1,5 @@
#
mes 2, EM_WSIZE, EM_PSIZE
mes 2, _EM_WSIZE, _EM_PSIZE
/*
* Tests _rol_ (rotate left) and _ror_ (rotate right). Several back
@ -10,11 +10,12 @@
* word size, or longer than 4 bytes.
* - If word size is 2, then try rotating 2-byte and 4-byte values.
* - If word size is 4, then try rotating 4-byte values.
* - If long long size is 8, then also try 8-byte rotations.
*
* You can cheat this test if _cmu_ always pushes zero.
*/
#if EM_WSIZE == 2
#if _EM_WSIZE == 2
#define LEN2 4
exa table2
exa left2
@ -54,11 +55,40 @@ val4left7
val4right11
con 2298473143U4
exp $_m_a_i_n
pro $_m_a_i_n, EM_WSIZE
#define i -EM_WSIZE
#if _EM_LLSIZE == 8
#define LEN8 4
exa table8
exa left8
exa right8
table8 /* left, right */
con 14079773792309488728U8 /* 0, 0 */
con 9712803510909425841U8 /* 1, 63 */
con 10409556348460427178U8 /* 32, 32 */
con 7039886896154744364U8 /* 63, 1 */
left8
con 0I2, 1I2, 32I2, 63I2
right8
con 0I2, 63I2, 32I2, 1I2
#if EM_WSIZE == 2
exa val8
exa val8left13
exa val8right20
exa val8right32
val8
con 15129222862059184558U8
val8left13
con 13366998808072149566U8
val8right20
con 1881076513336495948U8
val8right32
con 17636555387978501128U8
#endif
exp $_m_a_i_n
pro $_m_a_i_n, _EM_WSIZE
#define i -_EM_WSIZE
#if _EM_WSIZE == 2
/*
* Loop for LEN2 items in table2.
*/
@ -70,20 +100,20 @@ val4right11
lae left2
lol i
loc 1
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* left distance */
rol 2 /* rotate left */
lae table2
lol i
loc 1
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* expected result */
cmu 2
zeq *2
loc __LINE__
loc EM_WSIZE
loc _EM_WSIZE
loc 4
cuu
cal $fail
@ -94,20 +124,20 @@ val4right11
lae right2
lol i
loc 1
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* right distance */
ror 2 /* rotate right */
lae table2
lol i
loc 1
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* expected result */
cmu 2
zeq *3
loc __LINE__
loc EM_WSIZE
loc _EM_WSIZE
loc 4
cuu
cal $fail
@ -117,7 +147,7 @@ val4right11
lol i
loc LEN2
blt *1
#endif /* EM_WSIZE == 2 */
#endif /* _EM_WSIZE == 2 */
/*
* Loop for LEN4 items in table4.
@ -130,23 +160,23 @@ val4right11
lae left4
lol i
loc 1
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* left distance */
loc 2
loc EM_WSIZE
loc _EM_WSIZE
cii
rol 4 /* rotate left */
lae table4
lol i
loc 2
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 4 /* expected result */
cmu 4
zeq *5
loc __LINE__
loc EM_WSIZE
loc _EM_WSIZE
loc 4
cuu
cal $fail
@ -157,23 +187,23 @@ val4right11
lae right4
lol i
loc 1
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* right distance */
loc 2
loc EM_WSIZE
loc _EM_WSIZE
cii
ror 4 /* rotate right */
lae table4
lol i
loc 2
sli EM_WSIZE
ads EM_WSIZE
sli _EM_WSIZE
ads _EM_WSIZE
loi 4 /* expected result */
cmu 4
zeq *6
loc __LINE__
loc EM_WSIZE
loc _EM_WSIZE
loc 4
cuu
cal $fail
@ -197,7 +227,7 @@ val4right11
cmu 4
zeq *7
loc __LINE__
loc EM_WSIZE
loc _EM_WSIZE
loc 4
cuu
cal $fail
@ -212,12 +242,128 @@ val4right11
cmu 4
zeq *8
loc __LINE__
loc EM_WSIZE
loc _EM_WSIZE
loc 4
cuu
cal $fail
asp 4
8
#if _EM_LLSIZE == 8
/*
* Loop for LEN8 items in table8.
*/
loc 0
stl i
9
lae table8
loi 8 /* value to rotate */
lae left8
lol i
loc 1
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* left distance */
loc 2
loc _EM_WSIZE
cii
rol 8 /* rotate left */
lae table8
lol i
loc 3
sli _EM_WSIZE
ads _EM_WSIZE
loi 8 /* expected result */
cmu 8
zeq *10
loc __LINE__
loc _EM_WSIZE
loc 4
cuu
cal $fail
asp 4
10
lae table8
loi 8 /* value to rotate */
lae right8
lol i
loc 1
sli _EM_WSIZE
ads _EM_WSIZE
loi 2 /* right distance */
loc 2
loc _EM_WSIZE
cii
ror 8 /* rotate right */
lae table8
lol i
loc 3
sli _EM_WSIZE
ads _EM_WSIZE
loi 8 /* expected result */
cmu 8
zeq *11
loc __LINE__
loc _EM_WSIZE
loc 4
cuu
cal $fail
asp 4
11
inl i /* loop LEN8 times */
lol i
loc LEN8
blt *9
/*
* Rotate 8-byte value by constant distance.
*/
lae val8
loi 8
loc 13
rol 8 /* rotate left by 13 bits */
lae val8left13
loi 8
cmu 8
zeq *12
loc __LINE__
loc _EM_WSIZE
loc 4
cuu
cal $fail
asp 4
12
lae val8
loi 8
loc 20
ror 8 /* rotate right by 20 bits */
lae val8right20
loi 8
cmu 8
zeq *13
loc __LINE__
loc _EM_WSIZE
loc 4
cuu
cal $fail
asp 4
13
lae val8
loi 8
loc 32
ror 8 /* rotate right by 32 bits */
lae val8right32
loi 8
cmu 8
zeq *14
loc __LINE__
loc _EM_WSIZE
loc 4
cuu
cal $fail
asp 4
14
#endif /* _EM_LLSIZE == 8 */
cal $finished
end

View file

@ -0,0 +1,87 @@
#include "test.h"
/*
* Failure code will look like
* - 0x3e = id 0x3, 'e' or 'f' for negation
* - 0x43a = id 0x43, 'a' for addition
* - 0x43b = id 0x43, 'b' for subtraction
*/
struct neg {
unsigned int id;
long long a;
long long neg_a; /* -a */
} negations[] = {
{0x1, 0LL, 0LL},
{0x2, 2LL, -2LL},
{0x3, -446020022096LL, 446020022096LL},
};
struct s_addsub {
unsigned int id;
long long a;
long long b;
long long a_add_b; /* a + b */
long long a_sub_b; /* a - b */
} s_cases[] = {
{0x41, 2LL, 1LL, 3LL, 1LL},
{0x42, 2LL, -1LL, 1LL, 3LL},
{0x43, 1LL, 2LL, 3LL, -1LL},
/* a + b overflows 32 bits */
{0x44, 0xa0000000LL, 0x60000000LL, 0x100000000LL, 0x40000000LL},
{0x45, 1930610480LL, 842500503LL, 2773110983LL, 1088109977LL},
/* a + b doesn't carry to bit 32; a - b does borrow from bit 32 */
{0x51, 0x100000000LL, 0x50000000LL, 0x150000000LL, 0xb0000000LL},
{0x52, -446020022096LL, 1037107331549LL,
591087309453LL, -1483127353645LL},
/* a + b does carry to bit 32; a - b doesn't borrow from bit 32 */
{0x53, 0x3e0000000LL, 0x20000000LL, 0x400000000LL, 0x3c0000000LL},
{0x54, -180587215220LL, 249361198573LL,
68773983353LL, -429948413793LL},
/* a + b does carry to bit 32; a - b does borrow from bit 32 */
{0x55, 0x370000000LL, 0x90000000LL, 0x400000000LL, 0x2e0000000LL},
{0x56, -737537585551LL, -847060446507LL,
-1584598032058LL, 109522860956LL},
};
struct u_addsub {
unsigned int id;
unsigned long long a;
unsigned long long b;
unsigned long long a_add_b;
unsigned long long a_sub_b;
} u_cases[] = {
{0x81, 2ULL, 1ULL, 3ULL, 1ULL},
/* a + b overflows 63 bits */
{0x82, 6092994517831567942ULL, 3716888886436146324ULL,
9809883404267714266ULL, 2376105631395421618ULL},
};
#define LEN(ary) (sizeof(ary) / sizeof(ary[0]))
void _m_a_i_n(void) {
int i;
for (i = 0; i < LEN(negations); i++) {
struct neg *n = &negations[i];
if (n->a != -n->neg_a)
fail((n->id << 4) | 0xe);
if (-n->a != n->neg_a)
fail((n->id << 4) | 0xf);
}
for (i = 0; i < LEN(s_cases); i++) {
struct s_addsub *s = &s_cases[i];
if (s->a + s->b != s->a_add_b)
fail((s->id << 4) | 0xa);
if (s->a - s->b != s->a_sub_b)
fail((s->id << 4) | 0xb);
}
for (i = 0; i < LEN(u_cases); i++) {
struct u_addsub *u = &u_cases[i];
if (u->a + u->b != u->a_add_b)
fail((u->id << 4) | 0xa);
if (u->a - u->b != u->a_sub_b)
fail((u->id << 4) | 0xb);
}
finished();
}

View file

@ -0,0 +1,40 @@
#include "test.h"
typedef unsigned long long set;
set a = 0xfaab001bd86b595aLL;
set b = 0x3abe6373562dec1cLL;
set not_a = 0x0554ffe42794a6a5LL;
set a_and_b = 0x3aaa001350294818LL;
set a_or_b = 0xfabf637bde6ffd5eLL;
set a_xor_b = 0xc01563688e46b546LL;
/* ACK C evaluates H(constant) at compile time. */
#define H(x) ((set)x << 32)
void _m_a_i_n(void) {
ASSERT((~a & 0xffffffffffffffffLL) == not_a);
ASSERT((a & b) == a_and_b);
ASSERT((a | b) == a_or_b);
ASSERT((a ^ b) == a_xor_b);
ASSERT((a & 1) == 0);
ASSERT((2 & a) == 2);
ASSERT((a & ~8) == 0xfaab001bd86b5952LL);
ASSERT((a & H(1)) == H(1));
ASSERT((H(4) & a) == 0);
ASSERT((a & ~H(2)) == 0xfaab0019d86b595aLL);
ASSERT((a | 1) == 0xfaab001bd86b595bLL);
ASSERT((2 | a) == a);
ASSERT((a | H(4)) == 0xfaab001fd86b595aLL);
ASSERT((H(8) | a) == a);
ASSERT((a ^ 1) == 0xfaab001bd86b595bLL);
ASSERT((2 ^ a) == 0xfaab001bd86b5958LL);
ASSERT((a ^ H(4)) == 0xfaab001fd86b595aLL);
ASSERT((H(8) ^ a) == 0xfaab0013d86b595aLL);
finished();
}

View file

@ -0,0 +1,124 @@
#include "test.h"
struct s_cmp {
long long a;
long long b;
int a_cmp_b; /* -1 if a < b, 0 if a == b, 1 if a > b */
} s_cases[] = {
{-1LL, -1LL, 0},
{-1LL, 0LL, -1},
{-1LL, 1LL, -1},
{ 0LL, -1LL, 1},
{ 0LL, 0LL, 0},
{ 0LL, 1LL, -1},
{ 1LL, -1LL, 1},
{ 1LL, 0LL, 1},
{ 1LL, 1LL, 0},
};
struct u_cmp {
unsigned long long a;
unsigned long long b;
int a_cmp_b;
} u_cases[] = {
{ 0ULL, 0ULL, 0},
{ 0ULL, 1ULL, -1},
{ 1ULL, 0ULL, 1},
{ 1ULL, 1ULL, 0},
};
#define LEN(ary) (sizeof(ary) / sizeof(ary[0]))
/* Compiler should not optimize !t[a < b] as a > b. */
int t[] = {0, 1};
void _m_a_i_n(void) {
int i;
#define A c->a
#define B c->b
for (i = 0; i < LEN(s_cases); i++) {
struct s_cmp *c = &s_cases[i];
switch (c->a_cmp_b) {
case -1:
ASSERT(A < B);
ASSERT(A <= B);
ASSERT(A != B);
ASSERT(t[A < B]);
ASSERT(t[A <= B]);
ASSERT(!t[A == B]);
ASSERT(t[A != B]);
ASSERT(!t[A >= B]);
ASSERT(!t[A > B]);
break;
case 0:
ASSERT(A <= B);
ASSERT(A == B);
ASSERT(A >= B);
ASSERT(!t[A < B]);
ASSERT(t[A <= B]);
ASSERT(t[A == B]);
ASSERT(!t[A != B]);
ASSERT(t[A >= B]);
ASSERT(!t[A > B]);
break;
case 1:
ASSERT(A != B);
ASSERT(A >= B);
ASSERT(A > B);
ASSERT(!t[A < B]);
ASSERT(!t[A <= B]);
ASSERT(!t[A == B]);
ASSERT(t[A != B]);
ASSERT(t[A >= B]);
ASSERT(t[A > B]);
break;
default:
ASSERT(0);
break;
}
}
for (i = 0; i < LEN(u_cases); i++) {
struct u_cmp *c = &u_cases[i];
switch (c->a_cmp_b) {
case -1:
ASSERT(A < B);
ASSERT(A <= B);
ASSERT(A != B);
ASSERT(t[A < B]);
ASSERT(t[A <= B]);
ASSERT(!t[A == B]);
ASSERT(t[A != B]);
ASSERT(!t[A >= B]);
ASSERT(!t[A > B]);
break;
case 0:
ASSERT(A <= B);
ASSERT(A == B);
ASSERT(A >= B);
ASSERT(!t[A < B]);
ASSERT(t[A <= B]);
ASSERT(t[A == B]);
ASSERT(!t[A != B]);
ASSERT(t[A >= B]);
ASSERT(!t[A > B]);
break;
case 1:
ASSERT(A != B);
ASSERT(A >= B);
ASSERT(A > B);
ASSERT(!t[A < B]);
ASSERT(!t[A <= B]);
ASSERT(!t[A == B]);
ASSERT(t[A != B]);
ASSERT(t[A >= B]);
ASSERT(t[A > B]);
break;
default:
ASSERT(0);
break;
}
}
finished();
}

View file

@ -0,0 +1,183 @@
#include <unistd.h>
#include "test.h"
char coal = 12;
short stop = 3456;
int erest = 7890;
long way = 123456789L;
signed char ter = -1;
short sale = -9876;
int ern = -5432;
long itude = -1000000L;
unsigned char ming = 200;
unsigned short age = 40000U;
unsigned int othe = 50000U;
unsigned long shore = 3000000000UL;
long long ago;
unsigned long long ull;
/*
* BAR may modify global variables (though it really doesn't). The
* compiler should not assume that "ago" has the same value before and
* after BAR, but should generate code to read "ago" again.
*/
#define BAR write(1, "", 0)
void _m_a_i_n(void) {
ago = coal;
BAR;
ASSERT(ago == coal);
ASSERT(ago == 12LL);
ago = stop;
BAR;
ASSERT(ago == stop);
ASSERT(ago == 3456LL);
ago = erest;
BAR;
ASSERT(ago == erest);
ASSERT(ago == 7890LL);
ago = way;
BAR;
ASSERT(ago == way);
ASSERT(ago == 123456789LL);
ull = coal;
BAR;
ASSERT(ull == coal);
ASSERT(ull == 12ULL);
ull = stop;
BAR;
ASSERT(ull == stop);
ASSERT(ull == 3456ULL);
ull = erest;
BAR;
ASSERT(ull == erest);
ASSERT(ull == 7890ULL);
ull = way;
BAR;
ASSERT(ull == way);
ASSERT(ull == 123456789ULL);
ago = ter;
BAR;
ASSERT(ago == ter);
ASSERT(ago == -1LL);
ago = sale;
BAR;
ASSERT(ago == sale);
ASSERT(ago == -9876LL);
ago = ern;
BAR;
ASSERT(ago == ern);
ASSERT(ago == -5432LL);
ago = itude;
BAR;
ASSERT(ago == itude);
ASSERT(ago == -1000000LL);
ago = ming;
BAR;
ASSERT(ago == ming);
ASSERT(ago == 200LL);
ago = age;
BAR;
ASSERT(ago == age);
ASSERT(ago == 40000LL);
ago = othe;
BAR;
ASSERT(ago == othe);
ASSERT(ago == 50000LL);
ago = shore;
BAR;
ASSERT(ago == shore);
ASSERT(ago == 3000000000LL);
ull = ming;
BAR;
ASSERT(ull == ming);
ASSERT(ull == 200ULL);
ull = age;
BAR;
ASSERT(ull == age);
ASSERT(ull == 40000ULL);
ull = othe;
BAR;
ASSERT(ull == othe);
ASSERT(ull == 50000ULL);
ull = shore;
BAR;
ASSERT(ull == shore);
ASSERT(ull == 3000000000ULL);
ago = 95;
BAR;
ter = ago;
sale = ago;
ern = ago;
itude = ago;
ming = ago;
age = ago;
othe = ago;
shore = ago;
BAR;
ASSERT(ter == 95);
ASSERT(sale == 95);
ASSERT(ern == 95);
ASSERT(itude == 95L);
ASSERT(ming == 95);
ASSERT(age == 95U);
ASSERT(othe == 95U);
ASSERT(shore == 95UL);
ago = -59;
BAR;
ter = ago;
sale = ago;
ern = ago;
itude = ago;
BAR;
ASSERT(ter == -59);
ASSERT(sale == -59);
ASSERT(ern == -59);
ASSERT(itude == -59L);
ull = 42;
BAR;
ter = ull;
sale = ull;
ern = ull;
itude = ull;
ming = ull;
age = ull;
othe = ull;
shore = ull;
BAR;
ASSERT(ter == 42);
ASSERT(sale == 42);
ASSERT(ern == 42);
ASSERT(itude == 42L);
ASSERT(ming == 42);
ASSERT(age == 42U);
ASSERT(othe == 42U);
ASSERT(shore == 42UL);
finished();
}

View file

@ -0,0 +1,71 @@
#include "test.h"
/*
* Test division and remainder. Failure code will look like
* - 0x3d = id 0x3, 'd' for division
* - 0x3e = id 0x3, 'e' for remainder
*/
struct s_divrem {
unsigned int id;
long long a;
long long b;
long long a_div_b; /* a / b */
long long a_rem_b; /* a % b */
} s_cases[] = {
{0x1, 310LL, 100LL, 3LL, 10LL},
{0x2, 310LL, -100LL, -3LL, 10LL},
{0x3, -310LL, 100LL, -3LL, -10LL},
{0x4, -310LL, -100LL, 3LL, -10LL},
{0x5, 3000000000000010LL, 100LL, 30000000000000LL, 10LL},
{0x6, 3000000000000010LL, -100LL, -30000000000000LL, 10LL},
{0x7, -3000000000000010LL, 100LL, -30000000000000LL, -10LL},
{0x8, -3000000000000010LL, -100LL, 30000000000000LL, -10LL},
{0x9, 3000000000000010LL, 1000000000000LL, 3000LL, 10LL},
{0xa, 3000000000000010LL, -1000000000000LL, -3000LL, 10LL},
{0xb, -3000000000000010LL, 1000000000000LL, -3000LL, -10LL},
{0xc, -3000000000000010LL, -1000000000000LL, 3000LL, -10LL},
/*
* In next 3 cases, i386 tries (a / (b >> 13)) >> 13 = 8,
* may need to correct the quotient from 8 to 7.
*/
{0x11, 0x864200000000LL, 0x10c840000000LL, 8LL, 0LL},
{0x12, 0x864200000000LL, 0x10c840000001LL, 7LL, 0x10c83ffffff9LL},
{0x13, 0x864200000000LL, 0x10c840001fffLL, 7LL, 0x10c83fff2007LL},
};
struct u_divrem {
unsigned int id;
unsigned long long a;
unsigned long long b;
unsigned long long a_div_b;
unsigned long long a_rem_b;
} u_cases[] = {
{0x81, 310ULL, 100ULL, 3ULL, 10ULL},
{0x82, 3000000000000010ULL, 100ULL, 30000000000000ULL, 10ULL},
{0x83, 3000000000000010ULL, 1000000000000ULL, 3000ULL, 10ULL},
{0x91, 0x8000000000000000ULL, 3ULL, 0x2aaaaaaaaaaaaaaaULL, 2ULL},
{0x92, 0xffffffffffffffffULL, 3ULL, 0x5555555555555555ULL, 0ULL},
};
#define LEN(ary) (sizeof(ary) / sizeof(ary[0]))
void _m_a_i_n(void) {
int i;
for (i = 0; i < LEN(s_cases); i++) {
struct s_divrem *s = &s_cases[i];
if (s->a / s->b != s->a_div_b)
fail((s->id << 4) | 0xd);
if (s->a % s->b != s->a_rem_b)
fail((s->id << 4) | 0xe);
}
for (i = 0; i < LEN(u_cases); i++) {
struct u_divrem *u = &u_cases[i];
if (u->a / u->b != u->a_div_b)
fail((u->id << 4) | 0xd);
if (u->a % u->b != u->a_rem_b)
fail((u->id << 4) | 0xe);
}
finished();
}

View file

@ -0,0 +1,23 @@
#include "test.h"
long long a = 40000LL;
long long b = 3000000000LL;
long long c = 200000000000000LL;
unsigned long long d = 60000ULL;
/* products a * b, a * c, c * d */
long long ab = 120000000000000LL;
long long ac = 8000000000000000000LL;
unsigned long long cd = 12000000000000000000ULL;
void _m_a_i_n(void) {
ASSERT(a * b == ab);
ASSERT(-b * a == -ab);
ASSERT(b * -40000LL == -ab);
ASSERT(c * a == ac);
ASSERT(a * -c == -ac);
ASSERT(40000LL * -c == -ac);
ASSERT(c * d == cd);
ASSERT(d * c == cd);
finished();
}

View file

@ -0,0 +1,78 @@
#include "test.h"
/*
* i << 1 is a constant shift. i << (1 + zero) is a variable shift,
* and may use a different rule in some code generators.
*/
int zero = 0;
long long i = 121LL;
long long j = 224690292230LL;
unsigned long long u = 12022195707510591570ULL;
void _m_a_i_n(void) {
ASSERT(i << 0 == 121LL);
ASSERT(i << (0 + zero) == 121LL);
ASSERT(i << 1 == 242LL);
ASSERT(i << (1 + zero) == 242LL);
ASSERT(i << 26 == 8120172544LL);
ASSERT(i << (26 + zero) == 8120172544LL);
ASSERT(i << 32 == 519691042816LL);
ASSERT(i << (32 + zero) == 519691042816LL);
ASSERT(i << 56 == 8718968878589280256LL);
ASSERT(i << (56 + zero) == 8718968878589280256LL);
ASSERT(i >> 0 == 121LL);
ASSERT(i >> (0 + zero) == 121LL);
ASSERT(i >> 1 == 60LL);
ASSERT(i >> (1 + zero) == 60LL);
ASSERT(i >> 7 == 0LL);
ASSERT(i >> (7 + zero) == 0LL);
ASSERT(i >> 37 == 0LL);
ASSERT(i >> (37 + zero) == 0LL);
ASSERT(-i >> 0 == -121LL);
ASSERT(-i >> (0 + zero) == -121LL);
ASSERT(-i >> 1 == -61LL);
ASSERT(-i >> (1 + zero) == -61LL);
ASSERT(-i >> 7 == -1LL);
ASSERT(-i >> (7 + zero) == -1LL);
ASSERT(-i >> 37 == -1LL);
ASSERT(-i >> (37 + zero) == -1LL);
ASSERT(j << 0 == 224690292230LL);
ASSERT(j << (0 + zero) == 224690292230LL);
ASSERT(j << 10 == 230082859243520LL);
ASSERT(j << (10 + zero) == 230082859243520LL);
ASSERT(j << 25 == 7539355131691663360LL);
ASSERT(j << (25 + zero) == 7539355131691663360LL);
ASSERT(j >> 0 == 224690292230LL);
ASSERT(j >> (0 + zero) == 224690292230LL);
ASSERT(j >> 6 == 3510785816LL);
ASSERT(j >> (6 + zero) == 3510785816LL);
ASSERT(j >> 32 == 52LL);
ASSERT(j >> (32 + zero) == 52LL);
ASSERT(j >> 38 == 0LL);
ASSERT(j >> (38 + zero) == 0LL);
ASSERT(-j >> 0 == -224690292230LL);
ASSERT(-j >> (0 + zero) == -224690292230LL);
ASSERT(-j >> 6 == -3510785817LL);
ASSERT(-j >> (6 + zero) == -3510785817LL);
ASSERT(-j >> 32 == -53LL);
ASSERT(-j >> (32 + zero) == -53LL);
ASSERT(-j >> 38 == -1LL);
ASSERT(-j >> (38 + zero) == -1LL);
ASSERT(u >> 0 == 12022195707510591570ULL);
ASSERT(u >> (0 + zero) == 12022195707510591570ULL);
ASSERT(u >> 1 == 6011097853755295785ULL);
ASSERT(u >> (1 + zero) == 6011097853755295785ULL);
ASSERT(u >> 32 == 2799135564ULL);
ASSERT(u >> (32 + zero) == 2799135564ULL);
ASSERT(u >> 41 == 5467061ULL);
ASSERT(u >> (41 + zero) == 5467061ULL);
finished();
}

View file

@ -0,0 +1,62 @@
#include "test.h"
long long a = -719560752603LL;
long long b = -319239774717LL;
long long c = 100200300401LL;
long long d = 100200300402LL;
long long e = 100200300403LL;
long long f = 100200300404LL;
long long g = 100200300405LL;
long long h = 100200300406LL;
long long i = 541934347449LL;
long long j = 727503252688LL;
int compact(long long x) {
/* probably _csa_ */
switch (x) {
case 100200300401LL: return 23;
case 100200300402LL: return 29;
case 100200300403LL: return 31;
case 100200300405LL: return 37;
case 100200300406LL: return 41;
default: return 43;
}
}
int sparse(long long x) {
/* probably _csb_ */
switch (x) {
case -719560752603LL: return 47;
case -319239774717LL: return 53;
case 100200300403LL: return 59;
case 541934347449LL: return 61;
case 727503252688LL: return 67;
default: return 71;
}
}
void _m_a_i_n(void) {
ASSERT(compact(a) == 43);
ASSERT(compact(b) == 43);
ASSERT(compact(c) == 23);
ASSERT(compact(d) == 29);
ASSERT(compact(e) == 31);
ASSERT(compact(f) == 43);
ASSERT(compact(g) == 37);
ASSERT(compact(h) == 41);
ASSERT(compact(i) == 43);
ASSERT(compact(j) == 43);
ASSERT(sparse(a) == 47);
ASSERT(sparse(b) == 53);
ASSERT(sparse(c) == 71);
ASSERT(sparse(d) == 71);
ASSERT(sparse(e) == 59);
ASSERT(sparse(f) == 71);
ASSERT(sparse(g) == 71);
ASSERT(sparse(h) == 71);
ASSERT(sparse(i) == 61);
ASSERT(sparse(j) == 67);
finished();
}