Merge pull request #208 from kernigh/kernigh-data8
8-byte long long in ACK C for i386, m68020
This commit is contained in:
commit
9cee18f9d6
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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')
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (val >= 0 && val <= max_int)
|
||||
else if (!lng_flg && !lnglng_flg && (val & uint_mask) == val)
|
||||
{
|
||||
if ((val & (uint_mask >> 1)) == val)
|
||||
fund = INT;
|
||||
}
|
||||
else if (int_size == long_size)
|
||||
{
|
||||
fund = UNSIGNED;
|
||||
}
|
||||
else if (base == 10 && !uns_flg)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 can't be INT */
|
||||
if (fund == UNSIGNED)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 either operand has type long int, the other operand is con-
|
||||
verted to long int.
|
||||
if (shifting) {
|
||||
/* In shifts like o1 << o2, never convert o1,
|
||||
and let ch3bin() convert o2 to int.
|
||||
*/
|
||||
if (t1 == LONG && t2 != LONG)
|
||||
t2 = int2int(e2p, long_type);
|
||||
} 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
|
||||
if (t2 == LONG && t1 != LONG && !shifting) /* ??? */
|
||||
t1 = int2int(e1p, long_type);
|
||||
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 (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");
|
||||
#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 = ar;
|
||||
ex->VL_VALUE = (writh)ar;
|
||||
cut_size(ex);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -123,10 +123,14 @@ single_decl_specifier /* non_empty */ (register struct decspecs *ds;)
|
|||
}
|
||||
|
|
||||
[ SHORT | LONG ]
|
||||
{ if (ds->ds_size)
|
||||
{ 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 ]
|
||||
{ if (ds->ds_unsigned != 0)
|
||||
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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? */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
#define WORDS_REVERSED
|
||||
#define BYTES_REVERSED
|
||||
*/
|
||||
#undef valu_t
|
||||
#define valu_t long
|
||||
|
||||
#undef ADDR_T
|
||||
#define ADDR_T long
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
35
mach/i386/libem/csa8.s
Normal 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
39
mach/i386/libem/csb8.s
Normal 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
63
mach/i386/libem/divrem8.s
Normal 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
37
mach/i386/libem/dvi8.s
Normal 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
20
mach/i386/libem/dvu8.s
Normal 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
20
mach/i386/libem/mli8.s
Normal 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
36
mach/i386/libem/rmi8.s
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
;
|
||||
|
|
|
@ -2,7 +2,7 @@ for _, plat in ipairs(vars.plats) do
|
|||
acklibrary {
|
||||
name = "lib_"..plat,
|
||||
srcs = {
|
||||
"./*.s",
|
||||
"./*.s", -- csb8.s
|
||||
"./*.c"
|
||||
},
|
||||
vars = { plat = plat },
|
||||
|
|
|
@ -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
39
mach/m68020/libem/csa8.s
Normal 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
39
mach/m68020/libem/csb8.s
Normal 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
|
76
mach/m68020/libem/divrem8.s
Normal file
76
mach/m68020/libem/divrem8.s
Normal 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
34
mach/m68020/libem/dvi8.s
Normal 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
20
mach/m68020/libem/dvu8.s
Normal 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
35
mach/m68020/libem/rmi8.s
Normal 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
22
mach/m68020/libem/rmu8.s
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
#define Xfit(f) if (!(f)) Xnofit();
|
||||
|
||||
#undef valu_t
|
||||
#define valu_t long
|
||||
#undef ADDR_T
|
||||
#define ADDR_T long
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
/*
|
||||
|
|
|
@ -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 *, ...);
|
||||
|
|
|
@ -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,6 +253,7 @@ operation
|
|||
DOTSCT->s_zero += $2;
|
||||
}
|
||||
| DATA datalist
|
||||
| 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;
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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);
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" },
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
},
|
||||
}
|
||||
|
|
|
@ -4,5 +4,7 @@ plat_testsuite {
|
|||
name = "tests",
|
||||
plat = "linuxmips",
|
||||
method = "qemu-mipsel",
|
||||
-- skipsets = {"m2"},
|
||||
skipsets = {
|
||||
"long-long",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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={} },
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
87
tests/plat/long-long/lladdsub_e.c
Normal file
87
tests/plat/long-long/lladdsub_e.c
Normal 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();
|
||||
}
|
40
tests/plat/long-long/llbitset_e.c
Normal file
40
tests/plat/long-long/llbitset_e.c
Normal 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();
|
||||
}
|
||||
|
124
tests/plat/long-long/llcmp_e.c
Normal file
124
tests/plat/long-long/llcmp_e.c
Normal 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();
|
||||
}
|
||||
|
183
tests/plat/long-long/llconvert_e.c
Normal file
183
tests/plat/long-long/llconvert_e.c
Normal 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();
|
||||
}
|
71
tests/plat/long-long/lldivrem_e.c
Normal file
71
tests/plat/long-long/lldivrem_e.c
Normal 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();
|
||||
}
|
23
tests/plat/long-long/llmul_e.c
Normal file
23
tests/plat/long-long/llmul_e.c
Normal 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();
|
||||
}
|
78
tests/plat/long-long/llshift_e.c
Normal file
78
tests/plat/long-long/llshift_e.c
Normal 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();
|
||||
}
|
62
tests/plat/long-long/llswitch_e.c
Normal file
62
tests/plat/long-long/llswitch_e.c
Normal 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();
|
||||
}
|
Loading…
Reference in a new issue