Import PCRE 8.35
Change-Id: I03923fd8ad634857963521502febfb494a072c7d Reviewed-by: Lars Knoll <lars.knoll@digia.com>bb10
parent
bee0f1832b
commit
7d2565b4bc
|
|
@ -8,7 +8,7 @@ Email domain: cam.ac.uk
|
|||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
All rights reserved
|
||||
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2013 Zoltan Herczeg
|
||||
Copyright(c) 2010-2014 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2013 Zoltan Herczeg
|
||||
Copyright(c) 2009-2014 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ Email domain: cam.ac.uk
|
|||
University of Cambridge Computing Service,
|
||||
Cambridge, England.
|
||||
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2010-2013 Zoltan Herczeg
|
||||
Copyright(c) 2010-2014 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ Written by: Zoltan Herczeg
|
|||
Email local part: hzmester
|
||||
Emain domain: freemail.hu
|
||||
|
||||
Copyright(c) 2009-2013 Zoltan Herczeg
|
||||
Copyright(c) 2009-2014 Zoltan Herczeg
|
||||
All rights reserved.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
/* This is the public header file for the PCRE library, to be #included by
|
||||
applications that call the PCRE functions.
|
||||
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
/* The current PCRE version information. */
|
||||
|
||||
#define PCRE_MAJOR 8
|
||||
#define PCRE_MINOR 34
|
||||
#define PCRE_MINOR 35
|
||||
#define PCRE_PRERELEASE
|
||||
#define PCRE_DATE 2013-12-15
|
||||
#define PCRE_DATE 2014-04-04
|
||||
|
||||
/* When an application links to a PCRE DLL in Windows, the symbols that are
|
||||
imported have to be identified as such. When building PCRE, the appropriate
|
||||
|
|
@ -491,36 +491,42 @@ PCRE_EXP_DECL void (*pcre_free)(void *);
|
|||
PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre_stack_free)(void *);
|
||||
PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
|
||||
PCRE_EXP_DECL int (*pcre_stack_guard)(void);
|
||||
|
||||
PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre16_free)(void *);
|
||||
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
|
||||
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
|
||||
PCRE_EXP_DECL int (*pcre16_stack_guard)(void);
|
||||
|
||||
PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre32_free)(void *);
|
||||
PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
|
||||
PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
|
||||
PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
|
||||
PCRE_EXP_DECL int (*pcre32_stack_guard)(void);
|
||||
#else /* VPCOMPAT */
|
||||
PCRE_EXP_DECL void *pcre_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre_free(void *);
|
||||
PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre_stack_free(void *);
|
||||
PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
|
||||
PCRE_EXP_DECL int pcre_stack_guard(void);
|
||||
|
||||
PCRE_EXP_DECL void *pcre16_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre16_free(void *);
|
||||
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre16_stack_free(void *);
|
||||
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
|
||||
PCRE_EXP_DECL int pcre16_stack_guard(void);
|
||||
|
||||
PCRE_EXP_DECL void *pcre32_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre32_free(void *);
|
||||
PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
|
||||
PCRE_EXP_DECL void pcre32_stack_free(void *);
|
||||
PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
|
||||
PCRE_EXP_DECL int pcre32_stack_guard(void);
|
||||
#endif /* VPCOMPAT */
|
||||
|
||||
/* User defined callback which provides a stack just before the match starts. */
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -311,9 +311,9 @@ while(TRUE)
|
|||
ptr++;
|
||||
}
|
||||
/* Control should never reach here in 16/32 bit mode. */
|
||||
#endif /* !COMPILE_PCRE8 */
|
||||
|
||||
#else /* In 8-bit mode, the pattern does not need to be processed. */
|
||||
return 0;
|
||||
#endif /* !COMPILE_PCRE8 */
|
||||
}
|
||||
|
||||
/* End of pcre_byte_order.c */
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -547,6 +547,8 @@ static const char error_texts[] =
|
|||
"parentheses are too deeply nested\0"
|
||||
"invalid range in character class\0"
|
||||
"group name must start with a non-digit\0"
|
||||
/* 85 */
|
||||
"parentheses are too deeply nested (stack check)\0"
|
||||
;
|
||||
|
||||
/* Table to identify digits and hex digits. This is used when compiling
|
||||
|
|
@ -3070,8 +3072,11 @@ const pcre_uint32 *chr_ptr;
|
|||
const pcre_uint32 *ochr_ptr;
|
||||
const pcre_uint32 *list_ptr;
|
||||
const pcre_uchar *next_code;
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
const pcre_uchar *xclass_flags;
|
||||
#endif
|
||||
const pcre_uint8 *class_bitset;
|
||||
const pcre_uint32 *set1, *set2, *set_end;
|
||||
const pcre_uint8 *set1, *set2, *set_end;
|
||||
pcre_uint32 chr;
|
||||
BOOL accepted, invert_bits;
|
||||
|
||||
|
|
@ -3202,12 +3207,12 @@ for(;;)
|
|||
if (base_list[0] == OP_CLASS)
|
||||
#endif
|
||||
{
|
||||
set1 = (pcre_uint32 *)(base_end - base_list[2]);
|
||||
set1 = (pcre_uint8 *)(base_end - base_list[2]);
|
||||
list_ptr = list;
|
||||
}
|
||||
else
|
||||
{
|
||||
set1 = (pcre_uint32 *)(code - list[2]);
|
||||
set1 = (pcre_uint8 *)(code - list[2]);
|
||||
list_ptr = base_list;
|
||||
}
|
||||
|
||||
|
|
@ -3216,41 +3221,53 @@ for(;;)
|
|||
{
|
||||
case OP_CLASS:
|
||||
case OP_NCLASS:
|
||||
set2 = (pcre_uint32 *)
|
||||
set2 = (pcre_uint8 *)
|
||||
((list_ptr == list ? code : base_end) - list_ptr[2]);
|
||||
break;
|
||||
|
||||
/* OP_XCLASS cannot be supported here, because its bitset
|
||||
is not necessarily complete. E.g: [a-\0x{200}] is stored
|
||||
as a character range, and the appropriate bits are not set. */
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
case OP_XCLASS:
|
||||
xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;
|
||||
if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;
|
||||
if ((*xclass_flags & XCL_MAP) == 0)
|
||||
{
|
||||
/* No bits are set for characters < 256. */
|
||||
if (list[1] == 0) return TRUE;
|
||||
/* Might be an empty repeat. */
|
||||
continue;
|
||||
}
|
||||
set2 = (pcre_uint8 *)(xclass_flags + 1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case OP_NOT_DIGIT:
|
||||
invert_bits = TRUE;
|
||||
/* Fall through */
|
||||
invert_bits = TRUE;
|
||||
/* Fall through */
|
||||
case OP_DIGIT:
|
||||
set2 = (pcre_uint32 *)(cd->cbits + cbit_digit);
|
||||
break;
|
||||
set2 = (pcre_uint8 *)(cd->cbits + cbit_digit);
|
||||
break;
|
||||
|
||||
case OP_NOT_WHITESPACE:
|
||||
invert_bits = TRUE;
|
||||
/* Fall through */
|
||||
invert_bits = TRUE;
|
||||
/* Fall through */
|
||||
case OP_WHITESPACE:
|
||||
set2 = (pcre_uint32 *)(cd->cbits + cbit_space);
|
||||
break;
|
||||
set2 = (pcre_uint8 *)(cd->cbits + cbit_space);
|
||||
break;
|
||||
|
||||
case OP_NOT_WORDCHAR:
|
||||
invert_bits = TRUE;
|
||||
/* Fall through */
|
||||
invert_bits = TRUE;
|
||||
/* Fall through */
|
||||
case OP_WORDCHAR:
|
||||
set2 = (pcre_uint32 *)(cd->cbits + cbit_word);
|
||||
break;
|
||||
set2 = (pcre_uint8 *)(cd->cbits + cbit_word);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compare 4 bytes to improve speed. */
|
||||
set_end = set1 + (32 / 4);
|
||||
/* Because the sets are unaligned, we need
|
||||
to perform byte comparison here. */
|
||||
set_end = set1 + 32;
|
||||
if (invert_bits)
|
||||
{
|
||||
do
|
||||
|
|
@ -3551,7 +3568,9 @@ for(;;)
|
|||
if (list[1] == 0) return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
/* Control never reaches here. There used to be a fail-save return FALSE; here,
|
||||
but some compilers complain about an unreachable statement. */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3623,7 +3642,7 @@ for (;;)
|
|||
break;
|
||||
|
||||
case OP_MINUPTO:
|
||||
*code += OP_MINUPTO - OP_UPTO;
|
||||
*code += OP_POSUPTO - OP_MINUPTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -4062,12 +4081,16 @@ for (c = *cptr; c <= d; c++)
|
|||
|
||||
if (c > d) return -1; /* Reached end of range */
|
||||
|
||||
/* Found a character that has a single other case. Search for the end of the
|
||||
range, which is either the end of the input range, or a character that has zero
|
||||
or more than one other cases. */
|
||||
|
||||
*ocptr = othercase;
|
||||
next = othercase + 1;
|
||||
|
||||
for (++c; c <= d; c++)
|
||||
{
|
||||
if (UCD_OTHERCASE(c) != next) break;
|
||||
if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;
|
||||
next++;
|
||||
}
|
||||
|
||||
|
|
@ -4105,6 +4128,7 @@ add_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options,
|
|||
compile_data *cd, pcre_uint32 start, pcre_uint32 end)
|
||||
{
|
||||
pcre_uint32 c;
|
||||
pcre_uint32 classbits_end = (end <= 0xff ? end : 0xff);
|
||||
int n8 = 0;
|
||||
|
||||
/* If caseless matching is required, scan the range and process alternate
|
||||
|
|
@ -4148,7 +4172,7 @@ if ((options & PCRE_CASELESS) != 0)
|
|||
|
||||
/* Not UTF-mode, or no UCP */
|
||||
|
||||
for (c = start; c <= end && c < 256; c++)
|
||||
for (c = start; c <= classbits_end; c++)
|
||||
{
|
||||
SETBIT(classbits, cd->fcc[c]);
|
||||
n8++;
|
||||
|
|
@ -4173,22 +4197,21 @@ in all cases. */
|
|||
|
||||
#endif /* COMPILE_PCRE[8|16] */
|
||||
|
||||
/* If all characters are less than 256, use the bit map. Otherwise use extra
|
||||
data. */
|
||||
/* Use the bitmap for characters < 256. Otherwise use extra data.*/
|
||||
|
||||
if (end < 0x100)
|
||||
for (c = start; c <= classbits_end; c++)
|
||||
{
|
||||
for (c = start; c <= end; c++)
|
||||
{
|
||||
n8++;
|
||||
SETBIT(classbits, c);
|
||||
}
|
||||
/* Regardless of start, c will always be <= 255. */
|
||||
SETBIT(classbits, c);
|
||||
n8++;
|
||||
}
|
||||
|
||||
else
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
if (start <= 0xff) start = 0xff + 1;
|
||||
|
||||
if (end >= start)
|
||||
{
|
||||
pcre_uchar *uchardata = *uchardptr;
|
||||
|
||||
#ifdef SUPPORT_UTF
|
||||
if ((options & PCRE_UTF8) != 0) /* All UTFs use the same flag bit */
|
||||
{
|
||||
|
|
@ -4228,6 +4251,7 @@ else
|
|||
|
||||
*uchardptr = uchardata; /* Updata extra data pointer */
|
||||
}
|
||||
#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
|
||||
|
||||
return n8; /* Number of 8-bit characters */
|
||||
}
|
||||
|
|
@ -4449,6 +4473,9 @@ for (;; ptr++)
|
|||
BOOL reset_bracount;
|
||||
int class_has_8bitchar;
|
||||
int class_one_char;
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
BOOL xclass_has_prop;
|
||||
#endif
|
||||
int newoptions;
|
||||
int recno;
|
||||
int refsign;
|
||||
|
|
@ -4783,13 +4810,26 @@ for (;; ptr++)
|
|||
|
||||
should_flip_negation = FALSE;
|
||||
|
||||
/* Extended class (xclass) will be used when characters > 255
|
||||
might match. */
|
||||
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
xclass = FALSE;
|
||||
class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */
|
||||
class_uchardata_base = class_uchardata; /* Save the start */
|
||||
#endif
|
||||
|
||||
/* For optimization purposes, we track some properties of the class:
|
||||
class_has_8bitchar will be non-zero if the class contains at least one <
|
||||
256 character; class_one_char will be 1 if the class contains just one
|
||||
character. */
|
||||
character; xclass_has_prop will be TRUE if unicode property checks
|
||||
are present in the class. */
|
||||
|
||||
class_has_8bitchar = 0;
|
||||
class_one_char = 0;
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
xclass_has_prop = FALSE;
|
||||
#endif
|
||||
|
||||
/* Initialize the 32-char bit map to all zeros. We build the map in a
|
||||
temporary bit of memory, in case the class contains fewer than two
|
||||
|
|
@ -4798,12 +4838,6 @@ for (;; ptr++)
|
|||
|
||||
memset(classbits, 0, 32 * sizeof(pcre_uint8));
|
||||
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
xclass = FALSE;
|
||||
class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */
|
||||
class_uchardata_base = class_uchardata; /* Save the start */
|
||||
#endif
|
||||
|
||||
/* Process characters until ] is reached. By writing this as a "do" it
|
||||
means that an initial ] is taken as a data character. At the start of the
|
||||
loop, c contains the first byte of the character. */
|
||||
|
|
@ -4927,6 +4961,7 @@ for (;; ptr++)
|
|||
*class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;
|
||||
*class_uchardata++ = ptype;
|
||||
*class_uchardata++ = 0;
|
||||
xclass_has_prop = TRUE;
|
||||
ptr = tempptr + 1;
|
||||
continue;
|
||||
|
||||
|
|
@ -5109,6 +5144,7 @@ for (;; ptr++)
|
|||
XCL_PROP : XCL_NOTPROP;
|
||||
*class_uchardata++ = ptype;
|
||||
*class_uchardata++ = pdata;
|
||||
xclass_has_prop = TRUE;
|
||||
class_has_8bitchar--; /* Undo! */
|
||||
continue;
|
||||
}
|
||||
|
|
@ -5403,6 +5439,7 @@ for (;; ptr++)
|
|||
*code++ = OP_XCLASS;
|
||||
code += LINK_SIZE;
|
||||
*code = negate_class? XCL_NOT:0;
|
||||
if (xclass_has_prop) *code |= XCL_HASPROP;
|
||||
|
||||
/* If the map is required, move up the extra data to make room for it;
|
||||
otherwise just move the code pointer to the end of the extra data. */
|
||||
|
|
@ -5412,6 +5449,8 @@ for (;; ptr++)
|
|||
*code++ |= XCL_MAP;
|
||||
memmove(code + (32 / sizeof(pcre_uchar)), code,
|
||||
IN_UCHARS(class_uchardata - code));
|
||||
if (negate_class && !xclass_has_prop)
|
||||
for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
|
||||
memcpy(code, classbits, 32);
|
||||
code = class_uchardata + (32 / sizeof(pcre_uchar));
|
||||
}
|
||||
|
|
@ -6580,7 +6619,10 @@ for (;; ptr++)
|
|||
|
||||
code[1+LINK_SIZE] = OP_CREF;
|
||||
skipbytes = 1+IMM2_SIZE;
|
||||
refsign = -1;
|
||||
refsign = -1; /* => not a number */
|
||||
namelen = -1; /* => not a name; must set to avoid warning */
|
||||
name = NULL; /* Always set to avoid warning */
|
||||
recno = 0; /* Always set to avoid warning */
|
||||
|
||||
/* Check for a test for recursion in a named group. */
|
||||
|
||||
|
|
@ -6617,7 +6659,6 @@ for (;; ptr++)
|
|||
|
||||
if (refsign >= 0)
|
||||
{
|
||||
recno = 0;
|
||||
while (IS_DIGIT(*ptr))
|
||||
{
|
||||
recno = recno * 10 + (int)(*ptr - CHAR_0);
|
||||
|
|
@ -7994,6 +8035,16 @@ unsigned int orig_bracount;
|
|||
unsigned int max_bracount;
|
||||
branch_chain bc;
|
||||
|
||||
/* If set, call the external function that checks for stack availability. */
|
||||
|
||||
if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
|
||||
{
|
||||
*errorcodeptr= ERR85;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Miscellaneous initialization */
|
||||
|
||||
bc.outer = bcptr;
|
||||
bc.current_branch = code;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language (but see
|
|||
below for why this module is different).
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -1473,7 +1473,7 @@ for (;;)
|
|||
goto ANYNL01;
|
||||
|
||||
case CHAR_CR:
|
||||
if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
|
||||
if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
|
||||
/* Fall through */
|
||||
|
||||
ANYNL01:
|
||||
|
|
@ -1742,7 +1742,7 @@ for (;;)
|
|||
goto ANYNL02;
|
||||
|
||||
case CHAR_CR:
|
||||
if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
|
||||
if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
|
||||
/* Fall through */
|
||||
|
||||
ANYNL02:
|
||||
|
|
@ -2012,7 +2012,7 @@ for (;;)
|
|||
goto ANYNL03;
|
||||
|
||||
case CHAR_CR:
|
||||
if (ptr + 1 < end_subject && RAWUCHARTEST(ptr + 1) == CHAR_LF) ncount = 1;
|
||||
if (ptr + 1 < end_subject && UCHAR21TEST(ptr + 1) == CHAR_LF) ncount = 1;
|
||||
/* Fall through */
|
||||
|
||||
ANYNL03:
|
||||
|
|
@ -2210,7 +2210,7 @@ for (;;)
|
|||
if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
|
||||
reset_could_continue = TRUE;
|
||||
}
|
||||
else if (RAWUCHARTEST(ptr + 1) == CHAR_LF)
|
||||
else if (UCHAR21TEST(ptr + 1) == CHAR_LF)
|
||||
{
|
||||
ADD_NEW_DATA(-(state_offset + 1), 0, 1);
|
||||
}
|
||||
|
|
@ -3466,7 +3466,7 @@ for (;;)
|
|||
|
||||
if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
|
||||
{
|
||||
/* Advance to a known first char. */
|
||||
/* Advance to a known first pcre_uchar (i.e. data item) */
|
||||
|
||||
if (has_first_char)
|
||||
{
|
||||
|
|
@ -3474,12 +3474,12 @@ for (;;)
|
|||
{
|
||||
pcre_uchar csc;
|
||||
while (current_subject < end_subject &&
|
||||
(csc = RAWUCHARTEST(current_subject)) != first_char && csc != first_char2)
|
||||
(csc = UCHAR21TEST(current_subject)) != first_char && csc != first_char2)
|
||||
current_subject++;
|
||||
}
|
||||
else
|
||||
while (current_subject < end_subject &&
|
||||
RAWUCHARTEST(current_subject) != first_char)
|
||||
UCHAR21TEST(current_subject) != first_char)
|
||||
current_subject++;
|
||||
}
|
||||
|
||||
|
|
@ -3509,36 +3509,26 @@ for (;;)
|
|||
ANYCRLF, and we are now at a LF, advance the match position by one
|
||||
more character. */
|
||||
|
||||
if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
|
||||
if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
|
||||
(md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
|
||||
current_subject < end_subject &&
|
||||
RAWUCHARTEST(current_subject) == CHAR_NL)
|
||||
UCHAR21TEST(current_subject) == CHAR_NL)
|
||||
current_subject++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Or to a non-unique first char after study */
|
||||
/* Advance to a non-unique first pcre_uchar after study */
|
||||
|
||||
else if (start_bits != NULL)
|
||||
{
|
||||
while (current_subject < end_subject)
|
||||
{
|
||||
register pcre_uint32 c = RAWUCHARTEST(current_subject);
|
||||
register pcre_uint32 c = UCHAR21TEST(current_subject);
|
||||
#ifndef COMPILE_PCRE8
|
||||
if (c > 255) c = 255;
|
||||
#endif
|
||||
if ((start_bits[c/8] & (1 << (c&7))) == 0)
|
||||
{
|
||||
current_subject++;
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
/* In non 8-bit mode, the iteration will stop for
|
||||
characters > 255 at the beginning or not stop at all. */
|
||||
if (utf)
|
||||
ACROSSCHAR(current_subject < end_subject, *current_subject,
|
||||
current_subject++);
|
||||
#endif
|
||||
}
|
||||
else break;
|
||||
if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
|
||||
current_subject++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3557,19 +3547,20 @@ for (;;)
|
|||
/* If the pattern was studied, a minimum subject length may be set. This
|
||||
is a lower bound; no actual string of that length may actually match the
|
||||
pattern. Although the value is, strictly, in characters, we treat it as
|
||||
bytes to avoid spending too much time in this optimization. */
|
||||
in pcre_uchar units to avoid spending too much time in this optimization.
|
||||
*/
|
||||
|
||||
if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
|
||||
(pcre_uint32)(end_subject - current_subject) < study->minlength)
|
||||
return PCRE_ERROR_NOMATCH;
|
||||
|
||||
/* If req_char is set, we know that that character must appear in the
|
||||
subject for the match to succeed. If the first character is set, req_char
|
||||
must be later in the subject; otherwise the test starts at the match
|
||||
point. This optimization can save a huge amount of work in patterns with
|
||||
nested unlimited repeats that aren't going to match. Writing separate
|
||||
code for cased/caseless versions makes it go faster, as does using an
|
||||
autoincrement and backing off on a match.
|
||||
/* If req_char is set, we know that that pcre_uchar must appear in the
|
||||
subject for the match to succeed. If the first pcre_uchar is set,
|
||||
req_char must be later in the subject; otherwise the test starts at the
|
||||
match point. This optimization can save a huge amount of work in patterns
|
||||
with nested unlimited repeats that aren't going to match. Writing
|
||||
separate code for cased/caseless versions makes it go faster, as does
|
||||
using an autoincrement and backing off on a match.
|
||||
|
||||
HOWEVER: when the subject string is very, very long, searching to its end
|
||||
can take a long time, and give bad performance on quite ordinary
|
||||
|
|
@ -3589,7 +3580,7 @@ for (;;)
|
|||
{
|
||||
while (p < end_subject)
|
||||
{
|
||||
register pcre_uint32 pp = RAWUCHARINCTEST(p);
|
||||
register pcre_uint32 pp = UCHAR21INCTEST(p);
|
||||
if (pp == req_char || pp == req_char2) { p--; break; }
|
||||
}
|
||||
}
|
||||
|
|
@ -3597,18 +3588,18 @@ for (;;)
|
|||
{
|
||||
while (p < end_subject)
|
||||
{
|
||||
if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
|
||||
if (UCHAR21INCTEST(p) == req_char) { p--; break; }
|
||||
}
|
||||
}
|
||||
|
||||
/* If we can't find the required character, break the matching loop,
|
||||
/* If we can't find the required pcre_uchar, break the matching loop,
|
||||
which will cause a return or PCRE_ERROR_NOMATCH. */
|
||||
|
||||
if (p >= end_subject) break;
|
||||
|
||||
/* If we have found the required character, save the point where we
|
||||
/* If we have found the required pcre_uchar, save the point where we
|
||||
found it, so that we don't search again next time round the loop if
|
||||
the start hasn't passed this character yet. */
|
||||
the start hasn't passed this point yet. */
|
||||
|
||||
req_char_ptr = p;
|
||||
}
|
||||
|
|
@ -3665,9 +3656,9 @@ for (;;)
|
|||
not contain any explicit matches for \r or \n, and the newline option is CRLF
|
||||
or ANY or ANYCRLF, advance the match position by one more character. */
|
||||
|
||||
if (RAWUCHARTEST(current_subject - 1) == CHAR_CR &&
|
||||
if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
|
||||
current_subject < end_subject &&
|
||||
RAWUCHARTEST(current_subject) == CHAR_NL &&
|
||||
UCHAR21TEST(current_subject) == CHAR_NL &&
|
||||
(re->flags & PCRE_HASCRORLF) == 0 &&
|
||||
(md->nltype == NLTYPE_ANY ||
|
||||
md->nltype == NLTYPE_ANYCRLF ||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -134,7 +134,7 @@ pcre_uint32 c;
|
|||
BOOL utf = md->utf;
|
||||
if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
|
||||
while (length-- > 0)
|
||||
if (isprint(c = RAWUCHARINCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
|
||||
if (isprint(c = UCHAR21INCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -237,8 +237,8 @@ if (caseless)
|
|||
{
|
||||
pcre_uint32 cc, cp;
|
||||
if (eptr >= md->end_subject) return -2; /* Partial match */
|
||||
cc = RAWUCHARTEST(eptr);
|
||||
cp = RAWUCHARTEST(p);
|
||||
cc = UCHAR21TEST(eptr);
|
||||
cp = UCHAR21TEST(p);
|
||||
if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1;
|
||||
p++;
|
||||
eptr++;
|
||||
|
|
@ -254,7 +254,7 @@ else
|
|||
while (length-- > 0)
|
||||
{
|
||||
if (eptr >= md->end_subject) return -2; /* Partial match */
|
||||
if (RAWUCHARINCTEST(p) != RAWUCHARINCTEST(eptr)) return -1;
|
||||
if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2103,7 +2103,7 @@ for (;;)
|
|||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
|
||||
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
|
|
@ -2147,7 +2147,7 @@ for (;;)
|
|||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
|
||||
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
|
|
@ -2290,7 +2290,7 @@ for (;;)
|
|||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
RAWUCHARTEST(eptr) == NLBLOCK->nl[0])
|
||||
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
|
|
@ -2444,7 +2444,7 @@ for (;;)
|
|||
{
|
||||
SCHECK_PARTIAL();
|
||||
}
|
||||
else if (RAWUCHARTEST(eptr) == CHAR_LF) eptr++;
|
||||
else if (UCHAR21TEST(eptr) == CHAR_LF) eptr++;
|
||||
break;
|
||||
|
||||
case CHAR_LF:
|
||||
|
|
@ -2691,16 +2691,22 @@ for (;;)
|
|||
pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
|
||||
ecode += 1 + 2*IMM2_SIZE;
|
||||
|
||||
/* Setting the default length first and initializing 'offset' avoids
|
||||
compiler warnings in the REF_REPEAT code. */
|
||||
|
||||
length = (md->jscript_compat)? 0 : -1;
|
||||
offset = 0;
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
offset = GET2(slot, 0) << 1;
|
||||
if (offset < offset_top && md->offset_vector[offset] >= 0) break;
|
||||
if (offset < offset_top && md->offset_vector[offset] >= 0)
|
||||
{
|
||||
length = md->offset_vector[offset+1] - md->offset_vector[offset];
|
||||
break;
|
||||
}
|
||||
slot += md->name_entry_size;
|
||||
}
|
||||
if (count < 0)
|
||||
length = (md->jscript_compat)? 0 : -1;
|
||||
else
|
||||
length = md->offset_vector[offset+1] - md->offset_vector[offset];
|
||||
}
|
||||
goto REF_REPEAT;
|
||||
|
||||
|
|
@ -3212,7 +3218,7 @@ for (;;)
|
|||
CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
while (length-- > 0) if (*ecode++ != RAWUCHARINC(eptr)) RRETURN(MATCH_NOMATCH);
|
||||
while (length-- > 0) if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
@ -3252,7 +3258,7 @@ for (;;)
|
|||
|
||||
if (fc < 128)
|
||||
{
|
||||
pcre_uint32 cc = RAWUCHAR(eptr);
|
||||
pcre_uint32 cc = UCHAR21(eptr);
|
||||
if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH);
|
||||
ecode++;
|
||||
eptr++;
|
||||
|
|
@ -3521,7 +3527,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHARTEST(eptr);
|
||||
cc = UCHAR21TEST(eptr);
|
||||
if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
}
|
||||
|
|
@ -3539,7 +3545,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHARTEST(eptr);
|
||||
cc = UCHAR21TEST(eptr);
|
||||
if (fc != cc && foc != cc) RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
}
|
||||
|
|
@ -3556,7 +3562,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
break;
|
||||
}
|
||||
cc = RAWUCHARTEST(eptr);
|
||||
cc = UCHAR21TEST(eptr);
|
||||
if (fc != cc && foc != cc) break;
|
||||
eptr++;
|
||||
}
|
||||
|
|
@ -3583,7 +3589,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
if (fc != RAWUCHARINCTEST(eptr)) RRETURN(MATCH_NOMATCH);
|
||||
if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
|
||||
if (min == max) continue;
|
||||
|
|
@ -3600,7 +3606,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
if (fc != RAWUCHARINCTEST(eptr)) RRETURN(MATCH_NOMATCH);
|
||||
if (fc != UCHAR21INCTEST(eptr)) RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
/* Control never gets here */
|
||||
}
|
||||
|
|
@ -3614,7 +3620,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
break;
|
||||
}
|
||||
if (fc != RAWUCHARTEST(eptr)) break;
|
||||
if (fc != UCHAR21TEST(eptr)) break;
|
||||
eptr++;
|
||||
}
|
||||
if (possessive) continue; /* No backtracking */
|
||||
|
|
@ -4369,7 +4375,7 @@ for (;;)
|
|||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
RAWUCHAR(eptr) == NLBLOCK->nl[0])
|
||||
UCHAR21(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
|
|
@ -4411,7 +4417,7 @@ for (;;)
|
|||
default: RRETURN(MATCH_NOMATCH);
|
||||
|
||||
case CHAR_CR:
|
||||
if (eptr < md->end_subject && RAWUCHAR(eptr) == CHAR_LF) eptr++;
|
||||
if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
|
||||
break;
|
||||
|
||||
case CHAR_LF:
|
||||
|
|
@ -4521,7 +4527,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHAR(eptr);
|
||||
cc = UCHAR21(eptr);
|
||||
if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
|
|
@ -4538,7 +4544,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHAR(eptr);
|
||||
cc = UCHAR21(eptr);
|
||||
if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
|
|
@ -4555,7 +4561,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHAR(eptr);
|
||||
cc = UCHAR21(eptr);
|
||||
if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
|
|
@ -4572,7 +4578,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHAR(eptr);
|
||||
cc = UCHAR21(eptr);
|
||||
if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
|
|
@ -4589,7 +4595,7 @@ for (;;)
|
|||
SCHECK_PARTIAL();
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
}
|
||||
cc = RAWUCHAR(eptr);
|
||||
cc = UCHAR21(eptr);
|
||||
if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0)
|
||||
RRETURN(MATCH_NOMATCH);
|
||||
eptr++;
|
||||
|
|
@ -5150,7 +5156,7 @@ for (;;)
|
|||
{
|
||||
default: RRETURN(MATCH_NOMATCH);
|
||||
case CHAR_CR:
|
||||
if (eptr < md->end_subject && RAWUCHAR(eptr) == CHAR_LF) eptr++;
|
||||
if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
|
||||
break;
|
||||
|
||||
case CHAR_LF:
|
||||
|
|
@ -5689,7 +5695,7 @@ for (;;)
|
|||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
RAWUCHAR(eptr) == NLBLOCK->nl[0])
|
||||
UCHAR21(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
|
|
@ -5715,7 +5721,7 @@ for (;;)
|
|||
eptr + 1 >= md->end_subject &&
|
||||
NLBLOCK->nltype == NLTYPE_FIXED &&
|
||||
NLBLOCK->nllen == 2 &&
|
||||
RAWUCHAR(eptr) == NLBLOCK->nl[0])
|
||||
UCHAR21(eptr) == NLBLOCK->nl[0])
|
||||
{
|
||||
md->hitend = TRUE;
|
||||
if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
|
||||
|
|
@ -5772,7 +5778,7 @@ for (;;)
|
|||
if (c == CHAR_CR)
|
||||
{
|
||||
if (++eptr >= md->end_subject) break;
|
||||
if (RAWUCHAR(eptr) == CHAR_LF) eptr++;
|
||||
if (UCHAR21(eptr) == CHAR_LF) eptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5935,8 +5941,8 @@ for (;;)
|
|||
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
|
||||
eptr--;
|
||||
BACKCHAR(eptr);
|
||||
if (ctype == OP_ANYNL && eptr > pp && RAWUCHAR(eptr) == CHAR_NL &&
|
||||
RAWUCHAR(eptr - 1) == CHAR_CR) eptr--;
|
||||
if (ctype == OP_ANYNL && eptr > pp && UCHAR21(eptr) == CHAR_NL &&
|
||||
UCHAR21(eptr - 1) == CHAR_CR) eptr--;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -6783,10 +6789,10 @@ for(;;)
|
|||
|
||||
if (first_char != first_char2)
|
||||
while (start_match < end_subject &&
|
||||
(smc = RAWUCHARTEST(start_match)) != first_char && smc != first_char2)
|
||||
(smc = UCHAR21TEST(start_match)) != first_char && smc != first_char2)
|
||||
start_match++;
|
||||
else
|
||||
while (start_match < end_subject && RAWUCHARTEST(start_match) != first_char)
|
||||
while (start_match < end_subject && UCHAR21TEST(start_match) != first_char)
|
||||
start_match++;
|
||||
}
|
||||
|
||||
|
|
@ -6818,7 +6824,7 @@ for(;;)
|
|||
if (start_match[-1] == CHAR_CR &&
|
||||
(md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
|
||||
start_match < end_subject &&
|
||||
RAWUCHARTEST(start_match) == CHAR_NL)
|
||||
UCHAR21TEST(start_match) == CHAR_NL)
|
||||
start_match++;
|
||||
}
|
||||
}
|
||||
|
|
@ -6829,22 +6835,12 @@ for(;;)
|
|||
{
|
||||
while (start_match < end_subject)
|
||||
{
|
||||
register pcre_uint32 c = RAWUCHARTEST(start_match);
|
||||
register pcre_uint32 c = UCHAR21TEST(start_match);
|
||||
#ifndef COMPILE_PCRE8
|
||||
if (c > 255) c = 255;
|
||||
#endif
|
||||
if ((start_bits[c/8] & (1 << (c&7))) == 0)
|
||||
{
|
||||
start_match++;
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
/* In non 8-bit mode, the iteration will stop for
|
||||
characters > 255 at the beginning or not stop at all. */
|
||||
if (utf)
|
||||
ACROSSCHAR(start_match < end_subject, *start_match,
|
||||
start_match++);
|
||||
#endif
|
||||
}
|
||||
else break;
|
||||
if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
|
||||
start_match++;
|
||||
}
|
||||
}
|
||||
} /* Starting optimizations */
|
||||
|
|
@ -6897,7 +6893,7 @@ for(;;)
|
|||
{
|
||||
while (p < end_subject)
|
||||
{
|
||||
register pcre_uint32 pp = RAWUCHARINCTEST(p);
|
||||
register pcre_uint32 pp = UCHAR21INCTEST(p);
|
||||
if (pp == req_char || pp == req_char2) { p--; break; }
|
||||
}
|
||||
}
|
||||
|
|
@ -6905,7 +6901,7 @@ for(;;)
|
|||
{
|
||||
while (p < end_subject)
|
||||
{
|
||||
if (RAWUCHARINCTEST(p) == req_char) { p--; break; }
|
||||
if (UCHAR21INCTEST(p) == req_char) { p--; break; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2012 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -72,6 +72,7 @@ PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree;
|
|||
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc;
|
||||
PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree;
|
||||
PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
|
||||
PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
|
||||
|
||||
#elif !defined VPCOMPAT
|
||||
PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc;
|
||||
|
|
@ -79,6 +80,7 @@ PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free;
|
|||
PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc;
|
||||
PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free;
|
||||
PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL;
|
||||
PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
|
||||
#endif
|
||||
|
||||
/* End of pcre_globals.c */
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -316,8 +316,8 @@ start/end of string field names are. */
|
|||
&(NLBLOCK->nllen), utf)) \
|
||||
: \
|
||||
((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \
|
||||
RAWUCHARTEST(p) == NLBLOCK->nl[0] && \
|
||||
(NLBLOCK->nllen == 1 || RAWUCHARTEST(p+1) == NLBLOCK->nl[1]) \
|
||||
UCHAR21TEST(p) == NLBLOCK->nl[0] && \
|
||||
(NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \
|
||||
) \
|
||||
)
|
||||
|
||||
|
|
@ -330,8 +330,8 @@ start/end of string field names are. */
|
|||
&(NLBLOCK->nllen), utf)) \
|
||||
: \
|
||||
((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
|
||||
RAWUCHARTEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
|
||||
(NLBLOCK->nllen == 1 || RAWUCHARTEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
|
||||
UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
|
||||
(NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
|
||||
) \
|
||||
)
|
||||
|
||||
|
|
@ -582,12 +582,27 @@ changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */
|
|||
#define MAX_MARK ((1u << 8) - 1)
|
||||
#endif
|
||||
|
||||
/* There is a proposed future special "UTF-21" mode, in which only the lowest
|
||||
21 bits of a 32-bit character are interpreted as UTF, with the remaining 11
|
||||
high-order bits available to the application for other uses. In preparation for
|
||||
the future implementation of this mode, there are macros that load a data item
|
||||
and, if in this special mode, mask it to 21 bits. These macros all have names
|
||||
starting with UCHAR21. In all other modes, including the normal 32-bit
|
||||
library, the macros all have the same simple definitions. When the new mode is
|
||||
implemented, it is expected that these definitions will be varied appropriately
|
||||
using #ifdef when compiling the library that supports the special mode. */
|
||||
|
||||
#define UCHAR21(eptr) (*(eptr))
|
||||
#define UCHAR21TEST(eptr) (*(eptr))
|
||||
#define UCHAR21INC(eptr) (*(eptr)++)
|
||||
#define UCHAR21INCTEST(eptr) (*(eptr)++)
|
||||
|
||||
/* When UTF encoding is being used, a character is no longer just a single
|
||||
byte. The macros for character handling generate simple sequences when used in
|
||||
character-mode, and more complicated ones for UTF characters. GETCHARLENTEST
|
||||
and other macros are not used when UTF is not supported, so they are not
|
||||
defined. To make sure they can never even appear when UTF support is omitted,
|
||||
we don't even define them. */
|
||||
byte in 8-bit mode or a single short in 16-bit mode. The macros for character
|
||||
handling generate simple sequences when used in the basic mode, and more
|
||||
complicated ones for UTF characters. GETCHARLENTEST and other macros are not
|
||||
used when UTF is not supported. To make sure they can never even appear when
|
||||
UTF support is omitted, we don't even define them. */
|
||||
|
||||
#ifndef SUPPORT_UTF
|
||||
|
||||
|
|
@ -600,10 +615,6 @@ we don't even define them. */
|
|||
#define GETCHARINC(c, eptr) c = *eptr++;
|
||||
#define GETCHARINCTEST(c, eptr) c = *eptr++;
|
||||
#define GETCHARLEN(c, eptr, len) c = *eptr;
|
||||
#define RAWUCHAR(eptr) (*(eptr))
|
||||
#define RAWUCHARINC(eptr) (*(eptr)++)
|
||||
#define RAWUCHARTEST(eptr) (*(eptr))
|
||||
#define RAWUCHARINCTEST(eptr) (*(eptr)++)
|
||||
/* #define GETCHARLENTEST(c, eptr, len) */
|
||||
/* #define BACKCHAR(eptr) */
|
||||
/* #define FORWARDCHAR(eptr) */
|
||||
|
|
@ -776,30 +787,6 @@ do not know if we are in UTF-8 mode. */
|
|||
c = *eptr; \
|
||||
if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len);
|
||||
|
||||
/* Returns the next uchar, not advancing the pointer. This is called when
|
||||
we know we are in UTF mode. */
|
||||
|
||||
#define RAWUCHAR(eptr) \
|
||||
(*(eptr))
|
||||
|
||||
/* Returns the next uchar, advancing the pointer. This is called when
|
||||
we know we are in UTF mode. */
|
||||
|
||||
#define RAWUCHARINC(eptr) \
|
||||
(*((eptr)++))
|
||||
|
||||
/* Returns the next uchar, testing for UTF mode, and not advancing the
|
||||
pointer. */
|
||||
|
||||
#define RAWUCHARTEST(eptr) \
|
||||
(*(eptr))
|
||||
|
||||
/* Returns the next uchar, testing for UTF mode, advancing the
|
||||
pointer. */
|
||||
|
||||
#define RAWUCHARINCTEST(eptr) \
|
||||
(*((eptr)++))
|
||||
|
||||
/* If the pointer is not at the start of a character, move it back until
|
||||
it is. This is called only in UTF-8 mode - we don't put a test within the macro
|
||||
because almost all calls are already within a block of UTF-8 only code. */
|
||||
|
|
@ -895,30 +882,6 @@ we do not know if we are in UTF-16 mode. */
|
|||
c = *eptr; \
|
||||
if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len);
|
||||
|
||||
/* Returns the next uchar, not advancing the pointer. This is called when
|
||||
we know we are in UTF mode. */
|
||||
|
||||
#define RAWUCHAR(eptr) \
|
||||
(*(eptr))
|
||||
|
||||
/* Returns the next uchar, advancing the pointer. This is called when
|
||||
we know we are in UTF mode. */
|
||||
|
||||
#define RAWUCHARINC(eptr) \
|
||||
(*((eptr)++))
|
||||
|
||||
/* Returns the next uchar, testing for UTF mode, and not advancing the
|
||||
pointer. */
|
||||
|
||||
#define RAWUCHARTEST(eptr) \
|
||||
(*(eptr))
|
||||
|
||||
/* Returns the next uchar, testing for UTF mode, advancing the
|
||||
pointer. */
|
||||
|
||||
#define RAWUCHARINCTEST(eptr) \
|
||||
(*((eptr)++))
|
||||
|
||||
/* If the pointer is not at the start of a character, move it back until
|
||||
it is. This is called only in UTF-16 mode - we don't put a test within the
|
||||
macro because almost all calls are already within a block of UTF-16 only
|
||||
|
|
@ -980,30 +943,6 @@ This is called when we do not know if we are in UTF-32 mode. */
|
|||
#define GETCHARLENTEST(c, eptr, len) \
|
||||
GETCHARTEST(c, eptr)
|
||||
|
||||
/* Returns the next uchar, not advancing the pointer. This is called when
|
||||
we know we are in UTF mode. */
|
||||
|
||||
#define RAWUCHAR(eptr) \
|
||||
(*(eptr))
|
||||
|
||||
/* Returns the next uchar, advancing the pointer. This is called when
|
||||
we know we are in UTF mode. */
|
||||
|
||||
#define RAWUCHARINC(eptr) \
|
||||
(*((eptr)++))
|
||||
|
||||
/* Returns the next uchar, testing for UTF mode, and not advancing the
|
||||
pointer. */
|
||||
|
||||
#define RAWUCHARTEST(eptr) \
|
||||
(*(eptr))
|
||||
|
||||
/* Returns the next uchar, testing for UTF mode, advancing the
|
||||
pointer. */
|
||||
|
||||
#define RAWUCHARINCTEST(eptr) \
|
||||
(*((eptr)++))
|
||||
|
||||
/* If the pointer is not at the start of a character, move it back until
|
||||
it is. This is called only in UTF-32 mode - we don't put a test within the
|
||||
macro because almost all calls are already within a block of UTF-32 only
|
||||
|
|
@ -1874,8 +1813,9 @@ table. */
|
|||
/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
|
||||
contain characters with values greater than 255. */
|
||||
|
||||
#define XCL_NOT 0x01 /* Flag: this is a negative class */
|
||||
#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
|
||||
#define XCL_NOT 0x01 /* Flag: this is a negative class */
|
||||
#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
|
||||
#define XCL_HASPROP 0x04 /* Flag: property checks are present. */
|
||||
|
||||
#define XCL_END 0 /* Marks end of individual items */
|
||||
#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
|
||||
|
|
@ -2341,7 +2281,7 @@ enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
|
|||
ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59,
|
||||
ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69,
|
||||
ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79,
|
||||
ERR80, ERR81, ERR82, ERR83, ERR84, ERRCOUNT };
|
||||
ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERRCOUNT };
|
||||
|
||||
/* JIT compiling modes. The function list is indexed by them. */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,7 +6,7 @@
|
|||
and semantics are as close as possible to those of the Perl 5 language.
|
||||
|
||||
Written by Philip Hazel
|
||||
Copyright (c) 1997-2013 University of Cambridge
|
||||
Copyright (c) 1997-2014 University of Cambridge
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -91,8 +91,8 @@ pcre_uchar c2;
|
|||
|
||||
while (*str1 != '\0' || *str2 != '\0')
|
||||
{
|
||||
c1 = RAWUCHARINC(str1);
|
||||
c2 = RAWUCHARINC(str2);
|
||||
c1 = UCHAR21INC(str1);
|
||||
c2 = UCHAR21INC(str2);
|
||||
if (c1 != c2)
|
||||
return ((c1 > c2) << 1) - 1;
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ pcre_uchar c2;
|
|||
|
||||
while (*str1 != '\0' || *ustr2 != '\0')
|
||||
{
|
||||
c1 = RAWUCHARINC(str1);
|
||||
c1 = UCHAR21INC(str1);
|
||||
c2 = (pcre_uchar)*ustr2++;
|
||||
if (c1 != c2)
|
||||
return ((c1 > c2) << 1) - 1;
|
||||
|
|
|
|||
|
|
@ -879,9 +879,6 @@ do
|
|||
case OP_SOM:
|
||||
case OP_THEN:
|
||||
case OP_THEN_ARG:
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
case OP_XCLASS:
|
||||
#endif
|
||||
return SSB_FAIL;
|
||||
|
||||
/* We can ignore word boundary tests. */
|
||||
|
|
@ -1257,6 +1254,16 @@ do
|
|||
with a value >= 0xc4 is a potentially valid starter because it starts a
|
||||
character with a value > 255. */
|
||||
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
case OP_XCLASS:
|
||||
if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0)
|
||||
return SSB_FAIL;
|
||||
/* All bits are set. */
|
||||
if ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0 && (tcode[1 + LINK_SIZE] & XCL_NOT) != 0)
|
||||
return SSB_FAIL;
|
||||
#endif
|
||||
/* Fall through */
|
||||
|
||||
case OP_NCLASS:
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (utf)
|
||||
|
|
@ -1273,8 +1280,21 @@ do
|
|||
case OP_CLASS:
|
||||
{
|
||||
pcre_uint8 *map;
|
||||
tcode++;
|
||||
map = (pcre_uint8 *)tcode;
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
map = NULL;
|
||||
if (*tcode == OP_XCLASS)
|
||||
{
|
||||
if ((tcode[1 + LINK_SIZE] & XCL_MAP) != 0)
|
||||
map = (pcre_uint8 *)(tcode + 1 + LINK_SIZE + 1);
|
||||
tcode += GET(tcode, 1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
tcode++;
|
||||
map = (pcre_uint8 *)tcode;
|
||||
tcode += 32 / sizeof(pcre_uchar);
|
||||
}
|
||||
|
||||
/* In UTF-8 mode, the bits in a bit map correspond to character
|
||||
values, not to byte values. However, the bit map we are constructing is
|
||||
|
|
@ -1282,31 +1302,35 @@ do
|
|||
value is > 127. In fact, there are only two possible starting bytes for
|
||||
characters in the range 128 - 255. */
|
||||
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (utf)
|
||||
{
|
||||
for (c = 0; c < 16; c++) start_bits[c] |= map[c];
|
||||
for (c = 128; c < 256; c++)
|
||||
{
|
||||
if ((map[c/8] && (1 << (c&7))) != 0)
|
||||
{
|
||||
int d = (c >> 6) | 0xc0; /* Set bit for this starter */
|
||||
start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
|
||||
c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
|
||||
if (map != NULL)
|
||||
#endif
|
||||
{
|
||||
/* In non-UTF-8 mode, the two bit maps are completely compatible. */
|
||||
for (c = 0; c < 32; c++) start_bits[c] |= map[c];
|
||||
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
|
||||
if (utf)
|
||||
{
|
||||
for (c = 0; c < 16; c++) start_bits[c] |= map[c];
|
||||
for (c = 128; c < 256; c++)
|
||||
{
|
||||
if ((map[c/8] && (1 << (c&7))) != 0)
|
||||
{
|
||||
int d = (c >> 6) | 0xc0; /* Set bit for this starter */
|
||||
start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */
|
||||
c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* In non-UTF-8 mode, the two bit maps are completely compatible. */
|
||||
for (c = 0; c < 32; c++) start_bits[c] |= map[c];
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance past the bit map, and act on what follows. For a zero
|
||||
minimum repeat, continue; otherwise stop processing. */
|
||||
|
||||
tcode += 32 / sizeof(pcre_uchar);
|
||||
switch (*tcode)
|
||||
{
|
||||
case OP_CRSTAR:
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ additional data. */
|
|||
|
||||
if (c < 256)
|
||||
{
|
||||
if ((*data & XCL_HASPROP) == 0)
|
||||
{
|
||||
if ((*data & XCL_MAP) == 0) return negated;
|
||||
return (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0;
|
||||
}
|
||||
if ((*data & XCL_MAP) != 0 &&
|
||||
(((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0)
|
||||
return !negated; /* char found */
|
||||
|
|
|
|||
|
|
@ -44,9 +44,11 @@
|
|||
/* #define SLJIT_CONFIG_ARM_V5 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_V7 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
|
||||
/* #define SLJIT_CONFIG_ARM_64 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_32 1 */
|
||||
/* #define SLJIT_CONFIG_PPC_64 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_32 1 */
|
||||
/* #define SLJIT_CONFIG_MIPS_64 1 */
|
||||
/* #define SLJIT_CONFIG_SPARC_32 1 */
|
||||
/* #define SLJIT_CONFIG_TILEGX 1 */
|
||||
|
||||
|
|
@ -106,6 +108,13 @@
|
|||
#define SLJIT_VERBOSE 1
|
||||
#endif
|
||||
|
||||
/* See the beginning of sljitConfigInternal.h */
|
||||
/*
|
||||
SLJIT_IS_FPU_AVAILABLE
|
||||
The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.
|
||||
zero value - FPU is NOT present.
|
||||
nonzero value - FPU is present.
|
||||
*/
|
||||
|
||||
/* For further configurations, see the beginning of sljitConfigInternal.h */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -59,9 +59,11 @@
|
|||
|| (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
|| (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
|
||||
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
|
|
@ -75,10 +77,12 @@
|
|||
+ (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \
|
||||
+ (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
+ (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
+ (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
|
||||
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|
||||
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|
||||
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
|
||||
|
|
@ -102,12 +106,16 @@
|
|||
#else
|
||||
#define SLJIT_CONFIG_ARM_V5 1
|
||||
#endif
|
||||
#elif defined (__aarch64__)
|
||||
#define SLJIT_CONFIG_ARM_64 1
|
||||
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
|
||||
#define SLJIT_CONFIG_PPC_64 1
|
||||
#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
|
||||
#define SLJIT_CONFIG_PPC_32 1
|
||||
#elif defined(__mips__) && !defined(_LP64)
|
||||
#define SLJIT_CONFIG_MIPS_32 1
|
||||
#elif defined(__mips64)
|
||||
#define SLJIT_CONFIG_MIPS_64 1
|
||||
#elif defined(__sparc__) || defined(__sparc)
|
||||
#define SLJIT_CONFIG_SPARC_32 1
|
||||
#elif defined(__tilegx__)
|
||||
|
|
@ -275,7 +283,9 @@ typedef signed int sljit_si;
|
|||
typedef unsigned long int sljit_uw;
|
||||
typedef long int sljit_sw;
|
||||
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
|
||||
&& !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
|
||||
#define SLJIT_32BIT_ARCHITECTURE 1
|
||||
#define SLJIT_WORD_SHIFT 2
|
||||
|
|
@ -353,13 +363,18 @@ typedef double sljit_d;
|
|||
|
||||
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
|
||||
|
||||
/* These macros are useful for the application. */
|
||||
/* These macros are useful for the applications. */
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|
||||
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
|
||||
|| (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
|
||||
#ifdef __MIPSEL__
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
|
|
@ -367,6 +382,10 @@ typedef double sljit_d;
|
|||
#define SLJIT_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
||||
#define SLJIT_BIG_ENDIAN 1
|
||||
|
||||
#else
|
||||
#define SLJIT_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
|
@ -383,7 +402,8 @@ typedef double sljit_d;
|
|||
#endif
|
||||
|
||||
#ifndef SLJIT_INDIRECT_CALL
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32 && defined _AIX)
|
||||
#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)) \
|
||||
|| ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)
|
||||
/* It seems certain ppc compilers use an indirect addressing for functions
|
||||
which makes things complicated. */
|
||||
#define SLJIT_INDIRECT_CALL 1
|
||||
|
|
@ -420,6 +440,7 @@ typedef double sljit_d;
|
|||
|| (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
|
||||
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|
||||
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|
||||
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|
||||
|| (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|
||||
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#define SLJIT_UNALIGNED 1
|
||||
|
|
|
|||
|
|
@ -83,13 +83,13 @@
|
|||
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
|
||||
|
||||
#define GET_OPCODE(op) \
|
||||
((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
|
||||
((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
|
||||
|
||||
#define GET_FLAGS(op) \
|
||||
((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))
|
||||
((op) & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))
|
||||
|
||||
#define GET_ALL_FLAGS(op) \
|
||||
((op) & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
|
||||
((op) & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))
|
||||
|
||||
#define TYPE_CAST_NEEDED(op) \
|
||||
(((op) >= SLJIT_MOV_UB && (op) <= SLJIT_MOV_SH) || ((op) >= SLJIT_MOVU_UB && (op) <= SLJIT_MOVU_SH))
|
||||
|
|
@ -102,6 +102,16 @@
|
|||
#define ABUF_SIZE 4096
|
||||
#endif
|
||||
|
||||
/* Parameter parsing. */
|
||||
#define REG_MASK 0x3f
|
||||
#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)
|
||||
#define OFFS_REG_MASK (REG_MASK << 8)
|
||||
#define TO_OFFS_REG(reg) ((reg) << 8)
|
||||
/* When reg cannot be unused. */
|
||||
#define FAST_IS_REG(reg) ((reg) <= REG_MASK)
|
||||
/* When reg can be unused. */
|
||||
#define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK)
|
||||
|
||||
/* Jump flags. */
|
||||
#define JUMP_LABEL 0x1
|
||||
#define JUMP_ADDR 0x2
|
||||
|
|
@ -127,39 +137,59 @@
|
|||
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
# define IS_COND 0x04
|
||||
# define IS_BL 0x08
|
||||
/* cannot be encoded as branch */
|
||||
# define B_TYPE0 0x00
|
||||
/* conditional + imm8 */
|
||||
# define B_TYPE1 0x10
|
||||
# define PATCH_TYPE1 0x10
|
||||
/* conditional + imm20 */
|
||||
# define B_TYPE2 0x20
|
||||
# define PATCH_TYPE2 0x20
|
||||
/* IT + imm24 */
|
||||
# define B_TYPE3 0x30
|
||||
# define PATCH_TYPE3 0x30
|
||||
/* imm11 */
|
||||
# define B_TYPE4 0x40
|
||||
# define PATCH_TYPE4 0x40
|
||||
/* imm24 */
|
||||
# define B_TYPE5 0x50
|
||||
# define PATCH_TYPE5 0x50
|
||||
/* BL + imm24 */
|
||||
# define BL_TYPE6 0x60
|
||||
# define PATCH_BL 0x60
|
||||
/* 0xf00 cc code for branches */
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
# define UNCOND_B 0x04
|
||||
# define PATCH_B 0x08
|
||||
# define ABSOLUTE_B 0x10
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
# define IS_COND 0x004
|
||||
# define IS_CBZ 0x008
|
||||
# define IS_BL 0x010
|
||||
# define PATCH_B 0x020
|
||||
# define PATCH_COND 0x040
|
||||
# define PATCH_ABS48 0x080
|
||||
# define PATCH_ABS64 0x100
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# define IS_MOVABLE 0x04
|
||||
# define IS_JAL 0x08
|
||||
# define IS_BIT26_COND 0x10
|
||||
# define IS_BIT16_COND 0x20
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
# define IS_COND 0x004
|
||||
# define IS_CALL 0x008
|
||||
# define PATCH_B 0x010
|
||||
# define PATCH_ABS_B 0x020
|
||||
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
# define PATCH_ABS32 0x040
|
||||
# define PATCH_ABS48 0x080
|
||||
#endif
|
||||
# define REMOVE_COND 0x100
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
# define IS_MOVABLE 0x004
|
||||
# define IS_JAL 0x008
|
||||
# define IS_CALL 0x010
|
||||
# define IS_BIT26_COND 0x020
|
||||
# define IS_BIT16_COND 0x040
|
||||
|
||||
# define IS_COND (IS_BIT26_COND | IS_BIT16_COND)
|
||||
|
||||
# define PATCH_B 0x40
|
||||
# define PATCH_J 0x80
|
||||
# define PATCH_B 0x080
|
||||
# define PATCH_J 0x100
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
# define PATCH_ABS32 0x200
|
||||
# define PATCH_ABS48 0x400
|
||||
#endif
|
||||
|
||||
/* instruction types */
|
||||
# define MOVABLE_INS 0
|
||||
|
|
@ -167,15 +197,15 @@
|
|||
/* no destination (i.e: store) */
|
||||
# define UNMOVABLE_INS 32
|
||||
/* FPU status register */
|
||||
# define FCSR_FCC 33
|
||||
# define FCSR_FCC 33
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
|
||||
# define IS_JAL 0x04
|
||||
# define IS_COND 0x08
|
||||
# define IS_JAL 0x04
|
||||
# define IS_COND 0x08
|
||||
|
||||
# define PATCH_B 0x10
|
||||
# define PATCH_J 0x20
|
||||
# define PATCH_B 0x10
|
||||
# define PATCH_J 0x20
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
|
|
@ -215,9 +245,13 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
#define SLJIT_HAS_VARIABLE_LOCALS_OFFSET 1
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
|
||||
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
|
||||
#ifdef _AIX
|
||||
#define FIXED_LOCALS_OFFSET ((6 + 8) * sizeof(sljit_sw))
|
||||
#else
|
||||
#define FIXED_LOCALS_OFFSET (2 * sizeof(sljit_sw))
|
||||
|
|
@ -234,6 +268,11 @@
|
|||
#define FIXED_LOCALS_OFFSET (4 * sizeof(sljit_sw))
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
|
||||
#define FIXED_LOCALS_OFFSET 0
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
#define SLJIT_HAS_FIXED_LOCALS_OFFSET 1
|
||||
#define FIXED_LOCALS_OFFSET (23 * sizeof(sljit_sw))
|
||||
|
|
@ -343,7 +382,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void)
|
|||
compiler->cpool_diff = 0xffffffff;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
compiler->delay_slot = UNMOVABLE_INS;
|
||||
#endif
|
||||
|
||||
|
|
@ -418,8 +457,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
|
|||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
|
||||
{
|
||||
if (SLJIT_LIKELY(!!jump)) {
|
||||
SLJIT_ASSERT(jump->flags & SLJIT_REWRITABLE_JUMP);
|
||||
|
||||
jump->flags &= ~JUMP_LABEL;
|
||||
jump->flags |= JUMP_ADDR;
|
||||
jump->u.target = target;
|
||||
|
|
@ -534,7 +571,7 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
}
|
||||
|
||||
#define ADDRESSING_DEPENDS_ON(exp, reg) \
|
||||
(((exp) & SLJIT_MEM) && (((exp) & 0xf) == reg || (((exp) >> 4) & 0xf) == reg))
|
||||
(((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
|
||||
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
#define FUNCTION_CHECK_OP() \
|
||||
|
|
@ -548,41 +585,43 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
case SLJIT_SHL: \
|
||||
case SLJIT_LSHR: \
|
||||
case SLJIT_ASHR: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C))); \
|
||||
break; \
|
||||
case SLJIT_NEG: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
|
||||
break; \
|
||||
case SLJIT_MUL: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))); \
|
||||
break; \
|
||||
case SLJIT_CMPD: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \
|
||||
break; \
|
||||
case SLJIT_ADD: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_U | SLJIT_SET_S))); \
|
||||
break; \
|
||||
case SLJIT_SUB: \
|
||||
break; \
|
||||
case SLJIT_ADDC: \
|
||||
case SLJIT_SUBC: \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O))); \
|
||||
break; \
|
||||
case SLJIT_BREAKPOINT: \
|
||||
case SLJIT_NOP: \
|
||||
case SLJIT_UMUL: \
|
||||
case SLJIT_SMUL: \
|
||||
case SLJIT_MOV: \
|
||||
case SLJIT_MOV_UI: \
|
||||
case SLJIT_MOV_P: \
|
||||
case SLJIT_MOVU: \
|
||||
case SLJIT_MOVU_UI: \
|
||||
case SLJIT_MOVU_P: \
|
||||
/* Nothing allowed */ \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
break; \
|
||||
default: \
|
||||
/* Only SLJIT_INT_OP or SLJIT_SINGLE_OP is allowed. */ \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
|
@ -600,12 +639,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
|
||||
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
|
||||
if ((p) & 0xf0) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
SLJIT_ASSERT(!((i) & ~0x3)); \
|
||||
} \
|
||||
SLJIT_ASSERT(((p) >> 9) == 0); \
|
||||
SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
|
||||
} \
|
||||
else \
|
||||
SLJIT_ASSERT_STOP();
|
||||
|
|
@ -617,12 +656,12 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
else if ((p) == (SLJIT_MEM1(SLJIT_LOCALS_REG))) \
|
||||
SLJIT_ASSERT((i) >= 0 && (i) < compiler->logical_local_size); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
|
||||
if ((p) & 0xf0) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
SLJIT_ASSERT(!((i) & ~0x3)); \
|
||||
} \
|
||||
SLJIT_ASSERT(((p) >> 9) == 0); \
|
||||
SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
|
||||
} \
|
||||
else \
|
||||
SLJIT_ASSERT_STOP();
|
||||
|
|
@ -631,23 +670,23 @@ static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_comp
|
|||
if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG6) \
|
||||
SLJIT_ASSERT(i == 0); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \
|
||||
if ((p) & 0xf0) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \
|
||||
SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & REG_MASK)); \
|
||||
if ((p) & OFFS_REG_MASK) { \
|
||||
SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(OFFS_REG(p))); \
|
||||
SLJIT_ASSERT(((p) & OFFS_REG_MASK) != TO_OFFS_REG(SLJIT_LOCALS_REG) && !(i & ~0x3)); \
|
||||
} else \
|
||||
SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \
|
||||
SLJIT_ASSERT(((p) >> 9) == 0); \
|
||||
SLJIT_ASSERT(OFFS_REG(p) == 0); \
|
||||
SLJIT_ASSERT(!((p) & ~(SLJIT_MEM | SLJIT_IMM | REG_MASK | OFFS_REG_MASK))); \
|
||||
} \
|
||||
else \
|
||||
SLJIT_ASSERT_STOP();
|
||||
|
||||
#define FUNCTION_CHECK_OP1() \
|
||||
if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_P) { \
|
||||
SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & 0xf) != SLJIT_LOCALS_REG); \
|
||||
SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & 0xf) != SLJIT_LOCALS_REG); \
|
||||
if ((src & SLJIT_MEM) && (src & 0xf)) \
|
||||
SLJIT_ASSERT((dst & 0xf) != (src & 0xf) && ((dst >> 4) & 0xf) != (src & 0xf)); \
|
||||
SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & REG_MASK) != SLJIT_LOCALS_REG); \
|
||||
SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & REG_MASK) != SLJIT_LOCALS_REG); \
|
||||
if ((src & SLJIT_MEM) && (src & REG_MASK)) \
|
||||
SLJIT_ASSERT((dst & REG_MASK) != (src & REG_MASK) && OFFS_REG(dst) != (src & REG_MASK)); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -670,7 +709,7 @@ static char* freg_names[] = {
|
|||
(char*)"f4", (char*)"f5", (char*)"f6"
|
||||
};
|
||||
|
||||
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
|
||||
#ifdef _WIN64
|
||||
# define SLJIT_PRINT_D "I64"
|
||||
#else
|
||||
|
|
@ -684,18 +723,18 @@ static char* freg_names[] = {
|
|||
if ((p) & SLJIT_IMM) \
|
||||
fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", (i)); \
|
||||
else if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & 0xf) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
if (i) { \
|
||||
if (((p) >> 4) & 0xf) \
|
||||
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)], 1 << (i)); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & 0xF], (i)); \
|
||||
fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & REG_MASK], (i)); \
|
||||
} \
|
||||
else { \
|
||||
if (((p) >> 4) & 0xf) \
|
||||
fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)]); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \
|
||||
fprintf(compiler->verbose, "[%s]", reg_names[(p) & REG_MASK]); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
|
|
@ -704,18 +743,18 @@ static char* freg_names[] = {
|
|||
fprintf(compiler->verbose, "%s", reg_names[p]);
|
||||
#define sljit_verbose_fparam(p, i) \
|
||||
if ((p) & SLJIT_MEM) { \
|
||||
if ((p) & 0xf) { \
|
||||
if ((p) & REG_MASK) { \
|
||||
if (i) { \
|
||||
if (((p) >> 4) & 0xf) \
|
||||
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)], 1 << (i)); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & 0xF], (i)); \
|
||||
fprintf(compiler->verbose, "[%s + #%" SLJIT_PRINT_D "d]", reg_names[(p) & REG_MASK], (i)); \
|
||||
} \
|
||||
else { \
|
||||
if (((p) >> 4) & 0xF) \
|
||||
fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \
|
||||
if ((p) & OFFS_REG_MASK) \
|
||||
fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & REG_MASK], reg_names[OFFS_REG(p)]); \
|
||||
else \
|
||||
fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \
|
||||
fprintf(compiler->verbose, "[%s]", reg_names[(p) & REG_MASK]); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
|
|
@ -941,7 +980,7 @@ static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, s
|
|||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s", !(op & SLJIT_SET_U) ? "" : ".u",
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
|
||||
!(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
|
|
@ -983,7 +1022,7 @@ static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, s
|
|||
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
|
||||
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
|
||||
fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)],
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_S) ? "" : ".s", !(op & SLJIT_SET_U) ? "" : ".u",
|
||||
!(op & SLJIT_SET_E) ? "" : ".e", !(op & SLJIT_SET_U) ? "" : ".u", !(op & SLJIT_SET_S) ? "" : ".s",
|
||||
!(op & SLJIT_SET_O) ? "" : ".o", !(op & SLJIT_SET_C) ? "" : ".c", !(op & SLJIT_KEEP_FLAGS) ? "" : ".k");
|
||||
sljit_verbose_param(dst, dstw);
|
||||
fprintf(compiler->verbose, ", ");
|
||||
|
|
@ -1225,7 +1264,7 @@ static SLJIT_INLINE void check_sljit_emit_op_flags(struct sljit_compiler *compil
|
|||
SLJIT_ASSERT(type >= SLJIT_C_EQUAL && type < SLJIT_JUMP);
|
||||
SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_MOV_UI || GET_OPCODE(op) == SLJIT_MOV_SI
|
||||
|| (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
|
||||
SLJIT_ASSERT((op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C)) == 0);
|
||||
SLJIT_ASSERT((op & (SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_O | SLJIT_SET_C)) == 0);
|
||||
SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_KEEP_FLAGS)) != (SLJIT_SET_E | SLJIT_KEEP_FLAGS));
|
||||
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
|
||||
if (GET_OPCODE(op) < SLJIT_ADD) {
|
||||
|
|
@ -1340,24 +1379,28 @@ static SLJIT_INLINE sljit_si emit_mov_before_return(struct sljit_compiler *compi
|
|||
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
|
||||
# include "sljitNativeX86_common.c"
|
||||
#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
# include "sljitNativeARM_v5.c"
|
||||
# include "sljitNativeARM_32.c"
|
||||
#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
|
||||
# include "sljitNativeARM_v5.c"
|
||||
# include "sljitNativeARM_32.c"
|
||||
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
|
||||
# include "sljitNativeARM_Thumb2.c"
|
||||
# include "sljitNativeARM_T2_32.c"
|
||||
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
# include "sljitNativeARM_64.c"
|
||||
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
|
||||
# include "sljitNativePPC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
# include "sljitNativePPC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# include "sljitNativeMIPS_common.c"
|
||||
#elif (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
# include "sljitNativeMIPS_common.c"
|
||||
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
# include "sljitNativeSPARC_common.c"
|
||||
#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
|
||||
# include "sljitNativeTILEGX.c"
|
||||
# include "sljitNativeTILEGX_64.c"
|
||||
#endif
|
||||
|
||||
#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
|
||||
sljit_si src1, sljit_sw src1w,
|
||||
|
|
@ -1371,6 +1414,19 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|
|||
check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w);
|
||||
|
||||
condition = type & 0xff;
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
if ((condition == SLJIT_C_EQUAL || condition == SLJIT_C_NOT_EQUAL)) {
|
||||
if ((src1 & SLJIT_IMM) && !src1w) {
|
||||
src1 = src2;
|
||||
src1w = src2w;
|
||||
src2 = SLJIT_IMM;
|
||||
src2w = 0;
|
||||
}
|
||||
if ((src2 & SLJIT_IMM) && !src2w)
|
||||
return emit_cmp_to0(compiler, type, src1, src1w);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) {
|
||||
/* Immediate is prefered as second argument by most architectures. */
|
||||
switch (condition) {
|
||||
|
|
|
|||
|
|
@ -265,13 +265,19 @@ struct sljit_compiler {
|
|||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
|
||||
sljit_si locals_offset;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
|
||||
sljit_sw imm;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
sljit_si delay_slot;
|
||||
sljit_si cache_arg;
|
||||
sljit_sw cache_argw;
|
||||
|
|
@ -478,11 +484,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
|
||||
/* Register output: simply the name of the register.
|
||||
For destination, you can use SLJIT_UNUSED as well. */
|
||||
#define SLJIT_MEM 0x100
|
||||
#define SLJIT_MEM 0x80
|
||||
#define SLJIT_MEM0() (SLJIT_MEM)
|
||||
#define SLJIT_MEM1(r1) (SLJIT_MEM | (r1))
|
||||
#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 4))
|
||||
#define SLJIT_IMM 0x200
|
||||
#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))
|
||||
#define SLJIT_IMM 0x40
|
||||
|
||||
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
|
||||
32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the
|
||||
|
|
@ -494,12 +500,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
is specified, all register arguments must be the result of other operations with
|
||||
the same SLJIT_INT_OP flag. In other words, although a register can hold either
|
||||
a 64 or 32 bit value, these values cannot be mixed. The only exceptions are
|
||||
SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOV_UI/SLJIT_MOVU_SI/SLJIT_MOV_UI
|
||||
with SLJIT_INT_OP flag) which can convert any source argument to SLJIT_INT_OP
|
||||
compatible result. This conversion might be unnecessary on some CPUs like x86-64,
|
||||
since the upper 32 bit is always ignored. In this case SLJIT is clever enough
|
||||
to not generate any instructions if the source and destination operands are the
|
||||
same registers. Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
|
||||
SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOVU_SI with SLJIT_INT_OP flag)
|
||||
which can convert any source argument to SLJIT_INT_OP compatible result. This
|
||||
conversion might be unnecessary on some CPUs like x86-64, since the upper 32
|
||||
bit is always ignored. In this case SLJIT is clever enough to not generate any
|
||||
instructions if the source and destination operands are the same registers.
|
||||
Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
|
||||
#define SLJIT_INT_OP 0x100
|
||||
|
||||
/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just
|
||||
|
|
@ -525,10 +531,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
|
||||
/* Set Equal (Zero) status flag (E). */
|
||||
#define SLJIT_SET_E 0x0200
|
||||
/* Set unsigned status flag (U). */
|
||||
#define SLJIT_SET_U 0x0400
|
||||
/* Set signed status flag (S). */
|
||||
#define SLJIT_SET_S 0x0400
|
||||
/* Set unsgined status flag (U). */
|
||||
#define SLJIT_SET_U 0x0800
|
||||
#define SLJIT_SET_S 0x0800
|
||||
/* Set signed overflow flag (O). */
|
||||
#define SLJIT_SET_O 0x1000
|
||||
/* Set carry flag (C).
|
||||
|
|
@ -575,7 +581,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
|
||||
|
||||
/* Notes for MOV instructions:
|
||||
U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1)
|
||||
U = Mov with update (pre form). If source or destination defined as SLJIT_MEM1(r1)
|
||||
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
|
||||
UB = unsigned byte (8 bit)
|
||||
SB = signed byte (8 bit)
|
||||
|
|
@ -602,7 +608,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOV_UI 11
|
||||
/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
|
||||
/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOV. */
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOV_SI 12
|
||||
|
|
@ -626,7 +632,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOVU_UI 19
|
||||
/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
|
||||
/* No SLJIT_INT_OP form, since it is the same as SLJIT_IMOVU. */
|
||||
/* Flags: I - (never set any flags)
|
||||
Note: see SLJIT_INT_OP for further details. */
|
||||
#define SLJIT_MOVU_SI 20
|
||||
|
|
@ -656,7 +662,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
/* Flags: I | C | K */
|
||||
#define SLJIT_ADDC 26
|
||||
#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
|
||||
/* Flags: I | E | S | U | O | C | K */
|
||||
/* Flags: I | E | U | S | O | C | K */
|
||||
#define SLJIT_SUB 27
|
||||
#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
|
||||
/* Flags: I | C | K */
|
||||
|
|
@ -851,8 +857,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
|||
|
||||
/* Set the destination of the jump to this label. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
|
||||
/* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag.
|
||||
Note: use sljit_emit_ijump for fixed jumps. */
|
||||
/* Set the destination address of the jump to this label. */
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
|
||||
|
||||
/* Call function or jump anywhere. Both direct and indirect form
|
||||
|
|
|
|||
|
|
@ -1379,54 +1379,57 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si inp_fl
|
|||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm));
|
||||
return -1;
|
||||
}
|
||||
return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
/* Fast loads/stores. */
|
||||
if (arg & 0xf) {
|
||||
if (!(arg & 0xf0)) {
|
||||
if (IS_TYPE1_TRANSFER(inp_flags)) {
|
||||
if (argw >= 0 && argw <= 0xfff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, argw));
|
||||
return -1;
|
||||
}
|
||||
if (argw < 0 && argw >= -0xfff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, -argw));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (argw >= 0 && argw <= 0xff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
|
||||
return -1;
|
||||
}
|
||||
if (argw < 0 && argw >= -0xff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
argw = -argw;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((argw & 0x3) == 0 || IS_TYPE1_TRANSFER(inp_flags)) {
|
||||
if (!(arg & REG_MASK))
|
||||
return 0;
|
||||
|
||||
if (arg & OFFS_REG_MASK) {
|
||||
if ((argw & 0x3) != 0 && !IS_TYPE1_TRANSFER(inp_flags))
|
||||
return 0;
|
||||
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK,
|
||||
RM(OFFS_REG(arg)) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IS_TYPE1_TRANSFER(inp_flags)) {
|
||||
if (argw >= 0 && argw <= 0xfff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf,
|
||||
RM((arg >> 4) & 0xf) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, argw));
|
||||
return -1;
|
||||
}
|
||||
if (argw < 0 && argw >= -0xfff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, -argw));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (argw >= 0 && argw <= 0xff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)));
|
||||
return -1;
|
||||
}
|
||||
if (argw < 0 && argw >= -0xff) {
|
||||
if (inp_flags & ARG_TEST)
|
||||
return 1;
|
||||
argw = -argw;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & REG_MASK, TYPE2_TRANSFER_IMM(argw)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See getput_arg below.
|
||||
|
|
@ -1439,10 +1442,10 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
return 0;
|
||||
|
||||
/* Always a simple operation. */
|
||||
if (arg & 0xf0)
|
||||
if (arg & OFFS_REG_MASK)
|
||||
return 0;
|
||||
|
||||
if (!(arg & 0xf)) {
|
||||
if (!(arg & REG_MASK)) {
|
||||
/* Immediate access. */
|
||||
if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff))
|
||||
return 1;
|
||||
|
|
@ -1469,7 +1472,7 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
|
||||
#define TEST_WRITE_BACK() \
|
||||
if (inp_flags & WRITE_BACK) { \
|
||||
tmp_r = arg & 0xf; \
|
||||
tmp_r = arg & REG_MASK; \
|
||||
if (reg == tmp_r) { \
|
||||
/* This can only happen for stores */ \
|
||||
/* since ldr reg, [reg, ...]! has no meaning */ \
|
||||
|
|
@ -1497,7 +1500,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3;
|
||||
max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff;
|
||||
|
||||
if ((arg & 0xf) == SLJIT_UNUSED) {
|
||||
if ((arg & REG_MASK) == SLJIT_UNUSED) {
|
||||
/* Write back is not used. */
|
||||
imm = (sljit_uw)(argw - compiler->cache_argw);
|
||||
if ((compiler->cache_arg & SLJIT_IMM) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
|
||||
|
|
@ -1530,11 +1533,11 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (arg & 0xf0) {
|
||||
if (arg & OFFS_REG_MASK) {
|
||||
SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00));
|
||||
if (inp_flags & WRITE_BACK)
|
||||
tmp_r = arg & 0xf;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
|
||||
tmp_r = arg & REG_MASK;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0)));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1555,7 +1558,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
imm = get_imm(argw & ~max_delta);
|
||||
if (imm) {
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, imm));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & REG_MASK, imm));
|
||||
GETPUT_ARG_DATA_TRANSFER(1, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1564,14 +1567,14 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
if (imm) {
|
||||
argw = -argw;
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & 0xf, imm));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, tmp_r, arg & REG_MASK, imm));
|
||||
GETPUT_ARG_DATA_TRANSFER(0, inp_flags & WRITE_BACK, reg, tmp_r, argw & max_delta);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) {
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1583,7 +1586,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
compiler->cache_argw = argw;
|
||||
|
||||
TEST_WRITE_BACK();
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1591,7 +1594,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
if (arg == next_arg && !(inp_flags & WRITE_BACK) && (imm <= (sljit_uw)max_delta || imm >= (sljit_uw)-max_delta)) {
|
||||
SLJIT_ASSERT(inp_flags & LOAD_DATA);
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf]));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & REG_MASK]));
|
||||
|
||||
compiler->cache_arg = arg;
|
||||
compiler->cache_argw = argw;
|
||||
|
|
@ -1600,14 +1603,14 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si inp_flags,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
if ((arg & 0xf) == tmp_r) {
|
||||
if ((arg & REG_MASK) == tmp_r) {
|
||||
compiler->cache_arg = SLJIT_IMM;
|
||||
compiler->cache_argw = argw;
|
||||
tmp_r = TMP_REG3;
|
||||
}
|
||||
|
||||
FAIL_IF(load_immediate(compiler, tmp_r, argw));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & REG_MASK, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0)));
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1653,7 +1656,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
|
|||
return SLJIT_SUCCESS;
|
||||
dst_r = TMP_REG2;
|
||||
}
|
||||
else if (dst <= TMP_REG3) {
|
||||
else if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
|
|
@ -1672,9 +1675,9 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
|
|||
}
|
||||
|
||||
/* Source 1. */
|
||||
if (src1 <= TMP_REG3)
|
||||
if (FAST_IS_REG(src1))
|
||||
src1_r = src1;
|
||||
else if (src2 <= TMP_REG3) {
|
||||
else if (FAST_IS_REG(src2)) {
|
||||
flags |= ARGS_SWAPPED;
|
||||
src1_r = src2;
|
||||
src2 = src1;
|
||||
|
|
@ -1720,7 +1723,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si i
|
|||
|
||||
/* Source 2. */
|
||||
if (src2_r == 0) {
|
||||
if (src2 <= TMP_REG3) {
|
||||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
|
|
@ -2026,9 +2029,13 @@ static void init_compiler(void)
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
{
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#else
|
||||
if (arm_fpu_type == -1)
|
||||
init_compiler();
|
||||
return arm_fpu_type;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -2056,18 +2063,18 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
|||
sljit_sw inst = VSTR_F32 | (flags & (SLJIT_SINGLE_OP | FPU_LOAD));
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & 0xf0)) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7)));
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
|
||||
arg = SLJIT_MEM | TMP_REG1;
|
||||
argw = 0;
|
||||
}
|
||||
|
||||
/* Fast loads and stores. */
|
||||
if ((arg & 0xf)) {
|
||||
if ((arg & REG_MASK)) {
|
||||
if (!(argw & ~0x3fc))
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & 0xf, reg, argw >> 2));
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
|
||||
if (!(-argw & ~0x3fc))
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & 0xf, reg, (-argw) >> 2));
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
|
||||
}
|
||||
|
||||
if (compiler->cache_arg == arg) {
|
||||
|
|
@ -2083,29 +2090,29 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
|||
}
|
||||
}
|
||||
|
||||
if (arg & 0xf) {
|
||||
if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
if (arg & REG_MASK) {
|
||||
if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
FAIL_IF(compiler->error);
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
|
||||
}
|
||||
imm = get_imm(argw & ~0x3fc);
|
||||
if (imm) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, imm));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & REG_MASK, imm));
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
|
||||
}
|
||||
imm = get_imm(-argw & ~0x3fc);
|
||||
if (imm) {
|
||||
argw = -argw;
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, imm));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & REG_MASK, imm));
|
||||
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
|
||||
}
|
||||
}
|
||||
|
||||
compiler->cache_arg = arg;
|
||||
compiler->cache_argw = argw;
|
||||
if (arg & 0xf) {
|
||||
if (arg & REG_MASK) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & 0xf, reg_map[TMP_REG1]));
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & REG_MASK, reg_map[TMP_REG1]));
|
||||
}
|
||||
else
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
|
|
@ -2128,11 +2135,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst > SLJIT_FLOAT_REG6) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, dst, dstw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
if (src > SLJIT_FLOAT_REG6) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src, srcw));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
|
|
@ -2141,9 +2148,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
|
||||
dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src > SLJIT_FLOAT_REG6) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_fr, src, srcw));
|
||||
src = dst_fr;
|
||||
}
|
||||
|
|
@ -2184,14 +2191,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
compiler->cache_argw = 0;
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
|
||||
dst_fr = FAST_IS_REG(dst) ? dst : TMP_FREG1;
|
||||
|
||||
if (src2 > SLJIT_FLOAT_REG6) {
|
||||
if (src2 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
||||
if (src1 > SLJIT_FLOAT_REG6) {
|
||||
if (src1 & SLJIT_MEM) {
|
||||
FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
|
|
@ -2238,7 +2245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (dst <= TMP_REG3)
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3)));
|
||||
|
||||
/* Memory. */
|
||||
|
|
@ -2257,7 +2264,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= TMP_REG3)
|
||||
if (FAST_IS_REG(src))
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw))
|
||||
|
|
@ -2398,26 +2405,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
/* In ARM, we don't need to touch the arguments. */
|
||||
if (src & SLJIT_IMM) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
|
||||
jump->u.target = srcw;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
FAIL_IF(prepare_blx(compiler));
|
||||
FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
FAIL_IF(emit_blx(compiler));
|
||||
#else
|
||||
FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
|
||||
FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
|
||||
#endif
|
||||
jump->addr = compiler->size;
|
||||
}
|
||||
else {
|
||||
if (src <= TMP_REG3)
|
||||
if (!(src & SLJIT_IMM)) {
|
||||
if (FAST_IS_REG(src))
|
||||
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
|
||||
|
||||
SLJIT_ASSERT(src & SLJIT_MEM);
|
||||
|
|
@ -2425,6 +2414,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2));
|
||||
}
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
|
||||
jump->u.target = srcw;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
FAIL_IF(prepare_blx(compiler));
|
||||
FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
FAIL_IF(emit_blx(compiler));
|
||||
#else
|
||||
FAIL_IF(emit_imm(compiler, TMP_REG1, 0));
|
||||
FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
|
||||
#endif
|
||||
jump->addr = compiler->size;
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -2446,7 +2451,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
|
||||
op = GET_OPCODE(op);
|
||||
cc = get_cc(type);
|
||||
dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
if (op < SLJIT_ADD) {
|
||||
EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst_r, SLJIT_UNUSED, SRC2_IMM | 0));
|
||||
|
|
@ -2455,7 +2460,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
}
|
||||
|
||||
ins = (op == SLJIT_AND ? AND_DP : (op == SLJIT_OR ? ORR_DP : EOR_DP));
|
||||
if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) {
|
||||
if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
|
||||
EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ins, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc);
|
||||
/* The condition must always be set, even if the ORR/EOR is not executed above. */
|
||||
return (flags & SLJIT_SET_E) ? push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))) : SLJIT_SUCCESS;
|
||||
|
|
@ -2493,7 +2498,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
|
||||
PTR_FAIL_IF(!const_);
|
||||
|
||||
reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
|
||||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
|
||||
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value));
|
||||
|
|
@ -2503,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
#endif
|
||||
set_const(const_, compiler);
|
||||
|
||||
if (reg == TMP_REG2 && dst != SLJIT_UNUSED)
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
|
||||
return const_;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -207,7 +207,7 @@ static SLJIT_INLINE sljit_si emit_imm32_const(struct sljit_compiler *compiler, s
|
|||
COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm)
|
||||
static SLJIT_INLINE void modify_imm32_const(sljit_uh *inst, sljit_uw new_imm)
|
||||
{
|
||||
sljit_si dst = inst[1] & 0x0f00;
|
||||
SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
|
||||
|
|
@ -238,33 +238,33 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh
|
|||
if (jump->flags & IS_COND) {
|
||||
SLJIT_ASSERT(!(jump->flags & IS_BL));
|
||||
if (diff <= 127 && diff >= -128) {
|
||||
jump->flags |= B_TYPE1;
|
||||
jump->flags |= PATCH_TYPE1;
|
||||
return 5;
|
||||
}
|
||||
if (diff <= 524287 && diff >= -524288) {
|
||||
jump->flags |= B_TYPE2;
|
||||
jump->flags |= PATCH_TYPE2;
|
||||
return 4;
|
||||
}
|
||||
/* +1 comes from the prefix IT instruction. */
|
||||
diff--;
|
||||
if (diff <= 8388607 && diff >= -8388608) {
|
||||
jump->flags |= B_TYPE3;
|
||||
jump->flags |= PATCH_TYPE3;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else if (jump->flags & IS_BL) {
|
||||
if (diff <= 8388607 && diff >= -8388608) {
|
||||
jump->flags |= BL_TYPE6;
|
||||
jump->flags |= PATCH_BL;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (diff <= 1023 && diff >= -1024) {
|
||||
jump->flags |= B_TYPE4;
|
||||
jump->flags |= PATCH_TYPE4;
|
||||
return 4;
|
||||
}
|
||||
if (diff <= 8388607 && diff >= -8388608) {
|
||||
jump->flags |= B_TYPE5;
|
||||
jump->flags |= PATCH_TYPE5;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
|
@ -272,15 +272,6 @@ static SLJIT_INLINE sljit_si detect_jump_type(struct sljit_jump *jump, sljit_uh
|
|||
return 0;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, sljit_si flush)
|
||||
{
|
||||
sljit_uh* inst = (sljit_uh*)addr;
|
||||
modify_imm32_const(inst, new_addr);
|
||||
if (flush) {
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 3);
|
||||
}
|
||||
}
|
||||
|
||||
static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
|
||||
{
|
||||
sljit_si type = (jump->flags >> 4) & 0xf;
|
||||
|
|
@ -289,7 +280,7 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump)
|
|||
sljit_si s, j1, j2;
|
||||
|
||||
if (SLJIT_UNLIKELY(type == 0)) {
|
||||
inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0);
|
||||
modify_imm32_const((sljit_uh*)jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +416,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
return (void*)((sljit_uw)code | 0x1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Core code generator functions. */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#define INVALID_IMM 0x80000000
|
||||
static sljit_uw get_imm(sljit_uw imm)
|
||||
{
|
||||
|
|
@ -502,7 +497,6 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst, sl
|
|||
#define ARG1_IMM 0x0010000
|
||||
#define ARG2_IMM 0x0020000
|
||||
#define KEEP_FLAGS 0x0040000
|
||||
#define SET_MULOV 0x0080000
|
||||
/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
|
||||
#define SET_FLAGS 0x0100000
|
||||
#define UNUSED_RETURN 0x0200000
|
||||
|
|
@ -516,7 +510,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
arg1 must be register, TMP_REG1, imm
|
||||
arg2 must be register, TMP_REG2, imm */
|
||||
sljit_si reg;
|
||||
sljit_uw imm, negated_imm;
|
||||
sljit_uw imm, nimm;
|
||||
|
||||
if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
|
||||
/* Both are immediates. */
|
||||
|
|
@ -530,6 +524,10 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
imm = (flags & ARG2_IMM) ? arg2 : arg1;
|
||||
|
||||
switch (flags & 0xffff) {
|
||||
case SLJIT_CLZ:
|
||||
case SLJIT_MUL:
|
||||
/* No form with immediate operand. */
|
||||
break;
|
||||
case SLJIT_MOV:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
|
||||
return load_immediate(compiler, dst, imm);
|
||||
|
|
@ -537,30 +535,27 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
if (!(flags & SET_FLAGS))
|
||||
return load_immediate(compiler, dst, ~imm);
|
||||
/* Since the flags should be set, we just fallback to the register mode.
|
||||
Although I could do some clever things here, "NOT IMM" does not worth the efforts. */
|
||||
break;
|
||||
case SLJIT_CLZ:
|
||||
/* No form with immediate operand. */
|
||||
Although some clever things could be done here, "NOT IMM" does not worth the efforts. */
|
||||
break;
|
||||
case SLJIT_ADD:
|
||||
negated_imm = (sljit_uw)-(sljit_sw)imm;
|
||||
nimm = -imm;
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
|
||||
if (imm <= 0x7)
|
||||
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
|
||||
if (negated_imm <= 0x7)
|
||||
return push_inst16(compiler, SUBSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg));
|
||||
if (nimm <= 0x7)
|
||||
return push_inst16(compiler, SUBSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));
|
||||
if (reg == dst) {
|
||||
if (imm <= 0xff)
|
||||
return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));
|
||||
if (negated_imm <= 0xff)
|
||||
return push_inst16(compiler, SUBSI8 | IMM8(negated_imm) | RDN3(dst));
|
||||
if (nimm <= 0xff)
|
||||
return push_inst16(compiler, SUBSI8 | IMM8(nimm) | RDN3(dst));
|
||||
}
|
||||
}
|
||||
if (!(flags & SET_FLAGS)) {
|
||||
if (imm <= 0xfff)
|
||||
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));
|
||||
if (negated_imm <= 0xfff)
|
||||
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(negated_imm));
|
||||
if (nimm <= 0xfff)
|
||||
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(nimm));
|
||||
}
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
|
|
@ -572,63 +567,59 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
case SLJIT_SUB:
|
||||
if (flags & ARG2_IMM) {
|
||||
negated_imm = (sljit_uw)-(sljit_sw)imm;
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
|
||||
if (imm <= 0x7)
|
||||
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
|
||||
if (negated_imm <= 0x7)
|
||||
return push_inst16(compiler, ADDSI3 | IMM3(negated_imm) | RD3(dst) | RN3(reg));
|
||||
if (reg == dst) {
|
||||
if (imm <= 0xff)
|
||||
return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
|
||||
if (negated_imm <= 0xff)
|
||||
return push_inst16(compiler, ADDSI8 | IMM8(negated_imm) | RDN3(dst));
|
||||
}
|
||||
if (imm <= 0xff && (flags & UNUSED_RETURN))
|
||||
return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
|
||||
}
|
||||
if (!(flags & SET_FLAGS)) {
|
||||
if (imm <= 0xfff)
|
||||
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
|
||||
if (negated_imm <= 0xfff)
|
||||
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(negated_imm));
|
||||
}
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
}
|
||||
else {
|
||||
if (flags & ARG1_IMM) {
|
||||
if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst))
|
||||
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
nimm = -imm;
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) {
|
||||
if (imm <= 0x7)
|
||||
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
|
||||
if (nimm <= 0x7)
|
||||
return push_inst16(compiler, ADDSI3 | IMM3(nimm) | RD3(dst) | RN3(reg));
|
||||
if (reg == dst) {
|
||||
if (imm <= 0xff)
|
||||
return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
|
||||
if (nimm <= 0xff)
|
||||
return push_inst16(compiler, ADDSI8 | IMM8(nimm) | RDN3(dst));
|
||||
}
|
||||
if (imm <= 0xff && (flags & UNUSED_RETURN))
|
||||
return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
|
||||
}
|
||||
if (!(flags & SET_FLAGS)) {
|
||||
if (imm <= 0xfff)
|
||||
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
|
||||
if (nimm <= 0xfff)
|
||||
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(nimm));
|
||||
}
|
||||
break;
|
||||
case SLJIT_MUL:
|
||||
/* No form with immediate operand. */
|
||||
break;
|
||||
case SLJIT_AND:
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1));
|
||||
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
case SLJIT_SUBC:
|
||||
if (flags & ARG1_IMM)
|
||||
break;
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
case SLJIT_AND:
|
||||
nimm = get_imm(imm);
|
||||
if (nimm != INVALID_IMM)
|
||||
return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
case SLJIT_OR:
|
||||
nimm = get_imm(imm);
|
||||
if (nimm != INVALID_IMM)
|
||||
return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
|
||||
imm = get_imm(imm);
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1));
|
||||
if (imm != INVALID_IMM)
|
||||
return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
|
|
@ -638,50 +629,32 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
|
||||
break;
|
||||
case SLJIT_SHL:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
case SLJIT_LSHR:
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ARG1_IMM)
|
||||
break;
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
switch (flags & 0xffff) {
|
||||
case SLJIT_SHL:
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
|
||||
return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
|
||||
}
|
||||
break;
|
||||
case SLJIT_LSHR:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
case SLJIT_LSHR:
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
|
||||
return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
|
||||
}
|
||||
break;
|
||||
case SLJIT_ASHR:
|
||||
if (flags & ARG2_IMM) {
|
||||
imm &= 0x1f;
|
||||
if (imm == 0) {
|
||||
if (!(flags & SET_FLAGS))
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
|
||||
if (IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
|
||||
return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
|
||||
}
|
||||
default: /* SLJIT_ASHR */
|
||||
if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg))
|
||||
return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
|
||||
return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SLJIT_ASSERT_STOP();
|
||||
break;
|
||||
|
|
@ -708,6 +681,8 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
case SLJIT_MOVU_SI:
|
||||
case SLJIT_MOVU_P:
|
||||
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
|
||||
if (dst == arg2)
|
||||
return SLJIT_SUCCESS;
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOVU_UB:
|
||||
|
|
@ -834,7 +809,7 @@ static sljit_si emit_op_imm(struct sljit_compiler *compiler, sljit_si flags, slj
|
|||
s = store
|
||||
*/
|
||||
|
||||
static SLJIT_CONST sljit_uw sljit_mem16[12] = {
|
||||
static SLJIT_CONST sljit_ins sljit_mem16[12] = {
|
||||
/* w u l */ 0x5800 /* ldr */,
|
||||
/* w u s */ 0x5000 /* str */,
|
||||
/* w s l */ 0x5800 /* ldr */,
|
||||
|
|
@ -851,7 +826,7 @@ static SLJIT_CONST sljit_uw sljit_mem16[12] = {
|
|||
/* h s s */ 0x5200 /* strh */,
|
||||
};
|
||||
|
||||
static SLJIT_CONST sljit_uw sljit_mem16_imm5[12] = {
|
||||
static SLJIT_CONST sljit_ins sljit_mem16_imm5[12] = {
|
||||
/* w u l */ 0x6800 /* ldr imm5 */,
|
||||
/* w u s */ 0x6000 /* str imm5 */,
|
||||
/* w s l */ 0x6800 /* ldr imm5 */,
|
||||
|
|
@ -870,7 +845,7 @@ static SLJIT_CONST sljit_uw sljit_mem16_imm5[12] = {
|
|||
|
||||
#define MEM_IMM8 0xc00
|
||||
#define MEM_IMM12 0x800000
|
||||
static SLJIT_CONST sljit_uw sljit_mem32[12] = {
|
||||
static SLJIT_CONST sljit_ins sljit_mem32[12] = {
|
||||
/* w u l */ 0xf8500000 /* ldr.w */,
|
||||
/* w u s */ 0xf8400000 /* str.w */,
|
||||
/* w s l */ 0xf8500000 /* ldr.w */,
|
||||
|
|
@ -911,69 +886,71 @@ static sljit_si emit_set_delta(struct sljit_compiler *compiler, sljit_si dst, sl
|
|||
/* Can perform an operation using at most 1 instruction. */
|
||||
static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw)
|
||||
{
|
||||
sljit_si tmp;
|
||||
sljit_si other_r, shift;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if (SLJIT_UNLIKELY(flags & UPDATE)) {
|
||||
if ((arg & 0xf) && !(arg & 0xf0) && argw <= 0xff && argw >= -0xff) {
|
||||
flags &= ~UPDATE;
|
||||
arg &= 0xf;
|
||||
if ((arg & REG_MASK) && !(arg & OFFS_REG_MASK) && argw <= 0xff && argw >= -0xff) {
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
|
||||
flags &= ~UPDATE;
|
||||
arg &= 0xf;
|
||||
if (argw >= 0)
|
||||
argw |= 0x200;
|
||||
else {
|
||||
argw = -argw;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff);
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw));
|
||||
return -1;
|
||||
}
|
||||
return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & 0xf0)) {
|
||||
argw &= 0x3;
|
||||
tmp = (arg >> 4) & 0xf;
|
||||
arg &= 0xf;
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
|
||||
if (!argw && IS_3_LO_REGS(reg, arg, tmp))
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp)));
|
||||
argw &= 0x3;
|
||||
other_r = OFFS_REG(arg);
|
||||
arg &= 0xf;
|
||||
|
||||
if (!argw && IS_3_LO_REGS(reg, arg, other_r))
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
|
||||
else
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4)));
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(arg & 0xf) || argw > 0xfff || argw < -0xff)
|
||||
return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0;
|
||||
if (!(arg & REG_MASK) || argw > 0xfff || argw < -0xff)
|
||||
return 0;
|
||||
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
|
||||
arg &= 0xf;
|
||||
if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
|
||||
tmp = 3;
|
||||
shift = 3;
|
||||
if (IS_WORD_SIZE(flags)) {
|
||||
if (OFFSET_CHECK(0x1f, 2))
|
||||
tmp = 2;
|
||||
shift = 2;
|
||||
}
|
||||
else if (flags & BYTE_SIZE)
|
||||
{
|
||||
if (OFFSET_CHECK(0x1f, 0))
|
||||
tmp = 0;
|
||||
shift = 0;
|
||||
}
|
||||
else {
|
||||
SLJIT_ASSERT(flags & HALF_SIZE);
|
||||
if (OFFSET_CHECK(0x1f, 1))
|
||||
tmp = 1;
|
||||
shift = 1;
|
||||
}
|
||||
|
||||
if (tmp != 3) {
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp))));
|
||||
if (shift != 3) {
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - shift))));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -996,12 +973,13 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
|
|||
operators always uses word arguments without write back. */
|
||||
static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
{
|
||||
/* Simple operation except for updates. */
|
||||
if ((arg & 0xf0) || !(next_arg & SLJIT_MEM))
|
||||
sljit_sw diff;
|
||||
if ((arg & OFFS_REG_MASK) || !(next_arg & SLJIT_MEM))
|
||||
return 0;
|
||||
|
||||
if (!(arg & 0xf)) {
|
||||
if ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff)
|
||||
if (!(arg & REG_MASK)) {
|
||||
diff = argw - next_argw;
|
||||
if (diff <= 0xfff && diff >= -0xfff)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1009,17 +987,19 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
if (argw == next_argw)
|
||||
return 1;
|
||||
|
||||
if (arg == next_arg && ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff))
|
||||
diff = argw - next_argw;
|
||||
if (arg == next_arg && diff <= 0xfff && diff >= -0xfff)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Emit the necessary instructions. See can_cache above. */
|
||||
static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg, sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, sljit_si reg,
|
||||
sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_sw next_argw)
|
||||
{
|
||||
sljit_si tmp_r;
|
||||
sljit_sw tmp;
|
||||
sljit_si tmp_r, other_r;
|
||||
sljit_sw diff;
|
||||
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
if (!(next_arg & SLJIT_MEM)) {
|
||||
|
|
@ -1029,69 +1009,76 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
|
||||
tmp_r = (flags & STORE) ? TMP_REG3 : reg;
|
||||
|
||||
if (SLJIT_UNLIKELY(flags & UPDATE)) {
|
||||
flags &= ~UPDATE;
|
||||
if (SLJIT_UNLIKELY((flags & UPDATE) && (arg & REG_MASK))) {
|
||||
/* Update only applies if a base register exists. */
|
||||
if (arg & 0xf) {
|
||||
/* There is no caching here. */
|
||||
tmp = (arg & 0xf0) >> 4;
|
||||
arg &= 0xf;
|
||||
/* There is no caching here. */
|
||||
other_r = OFFS_REG(arg);
|
||||
arg &= 0xf;
|
||||
flags &= ~UPDATE;
|
||||
|
||||
if (!tmp) {
|
||||
if (!(argw & ~0xfff)) {
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
|
||||
return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
|
||||
if (!other_r) {
|
||||
if (!(argw & ~0xfff)) {
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw));
|
||||
return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw));
|
||||
}
|
||||
|
||||
if (compiler->cache_arg == SLJIT_MEM) {
|
||||
if (argw == compiler->cache_argw) {
|
||||
other_r = TMP_REG3;
|
||||
argw = 0;
|
||||
}
|
||||
|
||||
if (compiler->cache_arg == SLJIT_MEM) {
|
||||
if (argw == compiler->cache_argw) {
|
||||
tmp = TMP_REG3;
|
||||
argw = 0;
|
||||
}
|
||||
else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
FAIL_IF(compiler->error);
|
||||
compiler->cache_argw = argw;
|
||||
tmp = TMP_REG3;
|
||||
argw = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argw) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
compiler->cache_arg = SLJIT_MEM;
|
||||
else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
FAIL_IF(compiler->error);
|
||||
compiler->cache_argw = argw;
|
||||
tmp = TMP_REG3;
|
||||
other_r = TMP_REG3;
|
||||
argw = 0;
|
||||
}
|
||||
}
|
||||
|
||||
argw &= 0x3;
|
||||
if (!argw && IS_3_LO_REGS(reg, arg, tmp)) {
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp)));
|
||||
return push_inst16(compiler, ADD | SET_REGS44(arg, tmp));
|
||||
if (argw) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
compiler->cache_arg = SLJIT_MEM;
|
||||
compiler->cache_argw = argw;
|
||||
other_r = TMP_REG3;
|
||||
argw = 0;
|
||||
}
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4)));
|
||||
return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(tmp) | (argw << 6));
|
||||
}
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(!(arg & 0xf0));
|
||||
argw &= 0x3;
|
||||
if (!argw && IS_3_LO_REGS(reg, arg, other_r)) {
|
||||
FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r)));
|
||||
return push_inst16(compiler, ADD | SET_REGS44(arg, other_r));
|
||||
}
|
||||
FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4)));
|
||||
return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(other_r) | (argw << 6));
|
||||
}
|
||||
flags &= ~UPDATE;
|
||||
|
||||
SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
|
||||
|
||||
if (compiler->cache_arg == arg) {
|
||||
if (!((argw - compiler->cache_argw) & ~0xfff))
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | (argw - compiler->cache_argw));
|
||||
diff = argw - compiler->cache_argw;
|
||||
if (!(diff & ~0xfff))
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | diff);
|
||||
if (!((compiler->cache_argw - argw) & ~0xff))
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw));
|
||||
if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, diff) != SLJIT_ERR_UNSUPPORTED) {
|
||||
FAIL_IF(compiler->error);
|
||||
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0);
|
||||
}
|
||||
}
|
||||
|
||||
next_arg = (arg & 0xf) && (arg == next_arg);
|
||||
next_arg = (arg & REG_MASK) && (arg == next_arg) && (argw != next_argw);
|
||||
arg &= 0xf;
|
||||
if (arg && compiler->cache_arg == SLJIT_MEM && compiler->cache_argw == argw)
|
||||
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
|
||||
if (arg && compiler->cache_arg == SLJIT_MEM) {
|
||||
if (compiler->cache_argw == argw)
|
||||
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
|
||||
if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
FAIL_IF(compiler->error);
|
||||
compiler->cache_argw = argw;
|
||||
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3));
|
||||
}
|
||||
}
|
||||
|
||||
compiler->cache_argw = argw;
|
||||
if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
|
|
@ -1103,7 +1090,8 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
compiler->cache_arg = SLJIT_MEM;
|
||||
|
||||
if (next_arg) {
|
||||
diff = argw - next_argw;
|
||||
if (next_arg && diff <= 0xfff && diff >= -0xfff) {
|
||||
FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg)));
|
||||
compiler->cache_arg = SLJIT_MEM | arg;
|
||||
arg = 0;
|
||||
|
|
@ -1270,11 +1258,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
op = GET_OPCODE(op);
|
||||
switch (op) {
|
||||
case SLJIT_BREAKPOINT:
|
||||
push_inst16(compiler, BKPT);
|
||||
break;
|
||||
return push_inst16(compiler, BKPT);
|
||||
case SLJIT_NOP:
|
||||
push_inst16(compiler, NOP);
|
||||
break;
|
||||
return push_inst16(compiler, NOP);
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL)
|
||||
|
|
@ -1321,7 +1307,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1;
|
||||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_P) {
|
||||
|
|
@ -1454,7 +1440,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_r = (dst >= SLJIT_SCRATCH_REG1 && dst <= TMP_REG3) ? dst : TMP_REG1;
|
||||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0);
|
||||
|
||||
if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw))
|
||||
|
|
@ -1505,9 +1491,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
if (dst == SLJIT_UNUSED)
|
||||
flags |= UNUSED_RETURN;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_MUL && (op & SLJIT_SET_O))
|
||||
flags |= SET_MULOV;
|
||||
|
||||
emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
|
||||
|
||||
if (dst & SLJIT_MEM) {
|
||||
|
|
@ -1550,7 +1533,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
{
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#else
|
||||
/* Available by default. */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define FPU_LOAD (1 << 20)
|
||||
|
|
@ -1564,20 +1552,21 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
|||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
/* Fast loads and stores. */
|
||||
if (SLJIT_UNLIKELY(arg & 0xf0)) {
|
||||
FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & 0xf) | RM4((arg & 0xf0) >> 4) | ((argw & 0x3) << 6)));
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
|
||||
arg = SLJIT_MEM | TMP_REG2;
|
||||
argw = 0;
|
||||
}
|
||||
|
||||
if ((arg & 0xf) && (argw & 0x3) == 0) {
|
||||
if ((arg & REG_MASK) && (argw & 0x3) == 0) {
|
||||
if (!(argw & ~0x3fc))
|
||||
return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2));
|
||||
return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | (argw >> 2));
|
||||
if (!(-argw & ~0x3fc))
|
||||
return push_inst32(compiler, inst | RN4(arg & 0xf) | DD4(reg) | (-argw >> 2));
|
||||
return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2));
|
||||
}
|
||||
|
||||
SLJIT_ASSERT(!(arg & 0xf0));
|
||||
/* Slow cases */
|
||||
SLJIT_ASSERT(!(arg & OFFS_REG_MASK));
|
||||
if (compiler->cache_arg == arg) {
|
||||
tmp = argw - compiler->cache_argw;
|
||||
if (!(tmp & ~0x3fc))
|
||||
|
|
@ -1591,20 +1580,20 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
|||
}
|
||||
}
|
||||
|
||||
if (arg & 0xf) {
|
||||
if (emit_set_delta(compiler, TMP_REG1, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
if (arg & REG_MASK) {
|
||||
if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
|
||||
FAIL_IF(compiler->error);
|
||||
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
|
||||
}
|
||||
imm = get_imm(argw & ~0x3fc);
|
||||
if (imm != INVALID_IMM) {
|
||||
FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm));
|
||||
FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
|
||||
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
|
||||
}
|
||||
imm = get_imm(-argw & ~0x3fc);
|
||||
if (imm != INVALID_IMM) {
|
||||
argw = -argw;
|
||||
FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & 0xf) | imm));
|
||||
FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
|
||||
return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
|
||||
}
|
||||
}
|
||||
|
|
@ -1612,13 +1601,9 @@ static sljit_si emit_fop_mem(struct sljit_compiler *compiler, sljit_si flags, sl
|
|||
compiler->cache_arg = arg;
|
||||
compiler->cache_argw = argw;
|
||||
|
||||
if (SLJIT_UNLIKELY(!(arg & 0xf)))
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
else {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
if (arg & 0xf)
|
||||
FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & 0xf))));
|
||||
}
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
|
||||
if (arg & REG_MASK)
|
||||
FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & REG_MASK))));
|
||||
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg));
|
||||
}
|
||||
|
||||
|
|
@ -1649,7 +1634,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
return push_inst32(compiler, VMRS);
|
||||
}
|
||||
|
||||
dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
|
||||
if (src & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, dst_r, src, srcw);
|
||||
src = dst_r;
|
||||
|
|
@ -1668,9 +1653,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
break;
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
|
||||
|
|
@ -1687,7 +1672,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
compiler->cache_argw = 0;
|
||||
op ^= SLJIT_SINGLE_OP;
|
||||
|
||||
dst_r = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : dst;
|
||||
dst_r = (dst <= REG_MASK) ? dst : TMP_FREG1;
|
||||
if (src1 & SLJIT_MEM) {
|
||||
emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
|
||||
src1 = TMP_FREG1;
|
||||
|
|
@ -1712,9 +1697,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
break;
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
return SLJIT_SUCCESS;
|
||||
if (!(dst & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_fop_mem(compiler, (op & SLJIT_SINGLE_OP), TMP_FREG1, dst, dstw);
|
||||
}
|
||||
|
||||
#undef FPU_LOAD
|
||||
|
|
@ -1733,7 +1718,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (dst <= TMP_REG3)
|
||||
if (dst <= REG_MASK)
|
||||
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3));
|
||||
|
||||
/* Memory. */
|
||||
|
|
@ -1752,7 +1737,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= TMP_REG3)
|
||||
if (src <= REG_MASK)
|
||||
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src)));
|
||||
else if (src & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw))
|
||||
|
|
@ -1846,7 +1831,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type)
|
||||
{
|
||||
struct sljit_jump *jump;
|
||||
sljit_si cc;
|
||||
sljit_ins cc;
|
||||
|
||||
CHECK_ERROR_PTR();
|
||||
check_sljit_emit_jump(compiler, type);
|
||||
|
|
@ -1885,25 +1870,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
/* In ARM, we don't need to touch the arguments. */
|
||||
if (src & SLJIT_IMM) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
|
||||
jump->u.target = srcw;
|
||||
|
||||
FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
|
||||
jump->addr = compiler->size;
|
||||
FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1)));
|
||||
}
|
||||
else {
|
||||
if (src <= TMP_REG3)
|
||||
if (!(src & SLJIT_IMM)) {
|
||||
if (FAST_IS_REG(src))
|
||||
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
|
||||
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw));
|
||||
if (type >= SLJIT_FAST_CALL)
|
||||
return push_inst16(compiler, BLX | RN3(TMP_REG1));
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
FAIL_IF(!jump);
|
||||
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
|
||||
jump->u.target = srcw;
|
||||
|
||||
FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
|
||||
jump->addr = compiler->size;
|
||||
return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
|
||||
|
|
@ -1912,8 +1895,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
sljit_si type)
|
||||
{
|
||||
sljit_si dst_r, flags = GET_ALL_FLAGS(op);
|
||||
sljit_ins ins;
|
||||
sljit_uw cc;
|
||||
sljit_ins cc, ins;
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
|
||||
|
|
@ -1925,7 +1907,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
|
||||
op = GET_OPCODE(op);
|
||||
cc = get_cc(type);
|
||||
dst_r = (dst <= TMP_REG3) ? dst : TMP_REG2;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
if (op < SLJIT_ADD) {
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
|
||||
|
|
@ -1936,11 +1918,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
|
||||
FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
|
||||
}
|
||||
return dst_r == TMP_REG2 ? emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw) : SLJIT_SUCCESS;
|
||||
if (dst_r != TMP_REG2)
|
||||
return SLJIT_SUCCESS;
|
||||
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw);
|
||||
}
|
||||
|
||||
ins = (op == SLJIT_AND ? ANDI : (op == SLJIT_OR ? ORRI : EORI));
|
||||
if ((op == SLJIT_OR || op == SLJIT_XOR) && dst <= TMP_REG3 && dst == src) {
|
||||
if ((op == SLJIT_OR || op == SLJIT_XOR) && FAST_IS_REG(dst) && dst == src) {
|
||||
/* Does not change the other bits. */
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst) | 1));
|
||||
|
|
@ -1956,18 +1940,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG1, src, srcw, dst, dstw));
|
||||
src = TMP_REG1;
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw));
|
||||
src = TMP_REG2;
|
||||
srcw = 0;
|
||||
} else if (src & SLJIT_IMM) {
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
|
||||
src = TMP_REG2;
|
||||
srcw = 0;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
|
||||
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
|
||||
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
|
||||
if (op == SLJIT_AND || src != dst_r) {
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
|
||||
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
|
||||
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 0));
|
||||
}
|
||||
else {
|
||||
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
|
||||
FAIL_IF(push_inst32(compiler, ins | RN4(src) | RD4(dst_r) | 1));
|
||||
}
|
||||
|
||||
if (dst_r == TMP_REG2)
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0));
|
||||
|
||||
|
|
@ -1993,7 +1984,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
dst_r = (dst <= TMP_REG3) ? dst : TMP_REG1;
|
||||
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
|
||||
PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
|
|
@ -2003,12 +1994,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
inline_set_jump_addr(addr, new_addr, 1);
|
||||
sljit_uh *inst = (sljit_uh*)addr;
|
||||
modify_imm32_const(inst, new_addr);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 4);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_uh* inst = (sljit_uh*)addr;
|
||||
sljit_uh *inst = (sljit_uh*)addr;
|
||||
modify_imm32_const(inst, new_constant);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 3);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 4);
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
|
|||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_imm, op_norm) \
|
||||
#define EMIT_SHIFT(op_imm, op_v) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
|
|
@ -61,16 +61,14 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar,
|
|||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
sljit_si overflow_ra = 0;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_UI:
|
||||
|
|
@ -138,30 +136,31 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src2 < 0)
|
||||
FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
else {
|
||||
|
|
@ -172,45 +171,28 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(dst) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
if (src2 < 0)
|
||||
FAIL_IF(push_inst(compiler, XORI | SA(OVERFLOW_FLAG) | TA(OVERFLOW_FLAG) | IMM(1), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src1 != dst)
|
||||
overflow_ra = DR(src1);
|
||||
else if (src2 != dst)
|
||||
overflow_ra = DR(src2);
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & SLJIT_SET_C)
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
}
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & SLJIT_SET_C)
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_O)
|
||||
return push_inst(compiler, MOVN | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
return SLJIT_SUCCESS;
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SLL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & SRC2_IMM) {
|
||||
|
|
@ -236,14 +218,13 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
if (!(op & SLJIT_SET_C))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(TMP_EREG2) | IMM(1), TMP_EREG2));
|
||||
FAIL_IF(push_inst(compiler, AND | SA(TMP_EREG2) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
|
||||
/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(TMP_EREG2) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_S | SLJIT_SET_U)) || src2 == SIMM_MIN)) {
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
|
|
@ -251,40 +232,25 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src2 < 0)
|
||||
FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
|
||||
if (src1 != dst)
|
||||
overflow_ra = DR(src1);
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & SLJIT_SET_C)
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
|
||||
if (src1 != dst)
|
||||
overflow_ra = DR(src1);
|
||||
else {
|
||||
/* Rare ocasion. */
|
||||
FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
|
||||
overflow_ra = TMP_EREG2;
|
||||
}
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C))
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_U)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
|
||||
|
|
@ -293,16 +259,16 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_O) {
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, MOVZ | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
}
|
||||
return SLJIT_SUCCESS;
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SLL | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
|
|
@ -313,7 +279,7 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(-src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
|
|
@ -325,14 +291,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj
|
|||
}
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, MOVZ | SA(ULESS_FLAG) | T(dst) | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, ADDU | SA(TMP_EREG1) | TA(0) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
* Stack-less Just-In-Time compiler
|
||||
*
|
||||
* Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* mips 64-bit arch dependent functions. */
|
||||
|
||||
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
|
||||
{
|
||||
sljit_si shift = 32;
|
||||
sljit_si shift2;
|
||||
sljit_si inv = 0;
|
||||
sljit_ins ins;
|
||||
sljit_uw uimm;
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm < 0 && imm >= SIMM_MIN)
|
||||
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
|
||||
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Zero extended number. */
|
||||
uimm = imm;
|
||||
if (imm < 0) {
|
||||
uimm = ~imm;
|
||||
inv = 1;
|
||||
}
|
||||
|
||||
while (!(uimm & 0xff00000000000000l)) {
|
||||
shift -= 8;
|
||||
uimm <<= 8;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xf000000000000000l)) {
|
||||
shift -= 4;
|
||||
uimm <<= 4;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xc000000000000000l)) {
|
||||
shift -= 2;
|
||||
uimm <<= 2;
|
||||
}
|
||||
|
||||
if ((sljit_sw)uimm < 0) {
|
||||
uimm >>= 1;
|
||||
shift += 1;
|
||||
}
|
||||
SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
|
||||
|
||||
if (inv)
|
||||
uimm = ~uimm;
|
||||
|
||||
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
|
||||
if (uimm & 0x0000ffff00000000l)
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
|
||||
|
||||
imm &= (1l << shift) - 1;
|
||||
if (!(imm & ~0xffff)) {
|
||||
ins = (shift == 32) ? DSLL32 : DSLL;
|
||||
if (shift < 32)
|
||||
ins |= SH_IMM(shift);
|
||||
FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
|
||||
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
}
|
||||
|
||||
/* Double shifts needs to be performed. */
|
||||
uimm <<= 32;
|
||||
shift2 = shift - 16;
|
||||
|
||||
while (!(uimm & 0xf000000000000000l)) {
|
||||
shift2 -= 4;
|
||||
uimm <<= 4;
|
||||
}
|
||||
|
||||
if (!(uimm & 0xc000000000000000l)) {
|
||||
shift2 -= 2;
|
||||
uimm <<= 2;
|
||||
}
|
||||
|
||||
if (!(uimm & 0x8000000000000000l)) {
|
||||
shift2--;
|
||||
uimm <<= 1;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
|
||||
|
||||
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
|
||||
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
|
||||
|
||||
imm &= (1l << shift2) - 1;
|
||||
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
|
||||
}
|
||||
|
||||
#define SELECT_OP(a, b) \
|
||||
(!(op & SLJIT_INT_OP) ? a : b)
|
||||
|
||||
#define EMIT_LOGICAL(op_imm, op_norm) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
|
||||
if (flags & SRC2_IMM) { \
|
||||
if (src2 >= 32) { \
|
||||
SLJIT_ASSERT(!(op & SLJIT_INT_OP)); \
|
||||
ins = op_dimm32; \
|
||||
src2 -= 32; \
|
||||
} \
|
||||
else \
|
||||
ins = (op & SLJIT_INT_OP) ? op_imm : op_dimm; \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
|
||||
} \
|
||||
else { \
|
||||
ins = (op & SLJIT_INT_OP) ? op_v : op_dv; \
|
||||
if (op & SLJIT_SET_E) \
|
||||
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
|
||||
if (CHECK_FLAGS(SLJIT_SET_E)) \
|
||||
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
|
||||
sljit_si dst, sljit_si src1, sljit_sw src2)
|
||||
{
|
||||
sljit_ins ins;
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (dst != src2)
|
||||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
case SLJIT_MOV_SB:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SB) {
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
|
||||
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
case SLJIT_MOV_SH:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
|
||||
if (op == SLJIT_MOV_SH) {
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
|
||||
}
|
||||
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
|
||||
}
|
||||
else if (dst != src2)
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
SLJIT_ASSERT(!(op & SLJIT_INT_OP));
|
||||
FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
|
||||
return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
|
||||
|
||||
case SLJIT_MOV_SI:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
|
||||
|
||||
case SLJIT_NOT:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_CLZ:
|
||||
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
|
||||
#else
|
||||
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
|
||||
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
|
||||
}
|
||||
/* Nearly all instructions are unmovable in the following sequence. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
|
||||
/* Check zero. */
|
||||
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_INT_OP) ? 32 : 64), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
|
||||
/* Loop for searching the highest bit. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
|
||||
if (op & SLJIT_SET_E)
|
||||
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
|
||||
#endif
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ADD:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O)) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
}
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
/* a + b >= a | b (otherwise, the carry should be set to 1). */
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_ADDC:
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
else {
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
}
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
|
||||
} else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
if (!(op & SLJIT_SET_C))
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
/* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
/* Set carry flag. */
|
||||
return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
|
||||
|
||||
case SLJIT_SUB:
|
||||
if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_O) {
|
||||
if (src2 >= 0)
|
||||
FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1));
|
||||
}
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_O)
|
||||
FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
if (op & SLJIT_SET_E)
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
|
||||
if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O))
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
|
||||
if (op & SLJIT_SET_U)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
|
||||
if (op & SLJIT_SET_S) {
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
|
||||
FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
|
||||
}
|
||||
/* dst may be the same as src1 or src2. */
|
||||
if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C))
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (!(op & SLJIT_SET_O))
|
||||
return SLJIT_SUCCESS;
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
|
||||
return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_SUBC:
|
||||
if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
|
||||
FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
|
||||
src2 = TMP_REG2;
|
||||
flags &= ~SRC2_IMM;
|
||||
}
|
||||
|
||||
if (flags & SRC2_IMM) {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
|
||||
}
|
||||
else {
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
|
||||
/* dst may be the same as src1 or src2. */
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
|
||||
}
|
||||
|
||||
if (op & SLJIT_SET_C)
|
||||
FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
|
||||
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
|
||||
return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_MUL:
|
||||
SLJIT_ASSERT(!(flags & SRC2_IMM));
|
||||
if (!(op & SLJIT_SET_O)) {
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
if (op & SLJIT_INT_OP)
|
||||
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
|
||||
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
|
||||
return push_inst(compiler, MFLO | D(dst), DR(dst));
|
||||
#endif
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
|
||||
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
|
||||
|
||||
case SLJIT_AND:
|
||||
EMIT_LOGICAL(ANDI, AND);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_OR:
|
||||
EMIT_LOGICAL(ORI, OR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_XOR:
|
||||
EMIT_LOGICAL(XORI, XOR);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_SHL:
|
||||
EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_LSHR:
|
||||
EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
case SLJIT_ASHR:
|
||||
EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
SLJIT_ASSERT_STOP();
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
|
||||
{
|
||||
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
|
||||
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
|
||||
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
|
||||
{
|
||||
sljit_ins *inst = (sljit_ins*)addr;
|
||||
|
||||
inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
|
||||
inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
|
||||
inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
|
||||
inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
|
||||
SLJIT_CACHE_FLUSH(inst, inst + 6);
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void)
|
||||
{
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
return "MIPS(32)" SLJIT_CPUINFO;
|
||||
return "MIPS V" SLJIT_CPUINFO;
|
||||
#else
|
||||
return "MIPS III" SLJIT_CPUINFO;
|
||||
#endif
|
||||
|
|
@ -47,7 +47,7 @@ typedef sljit_ui sljit_ins;
|
|||
/* For position independent code, t9 must contain the function address. */
|
||||
#define PIC_ADDR_REG TMP_REG2
|
||||
|
||||
/* TMP_EREG1 is used mainly for literal encoding on 64 bit. */
|
||||
/* TMP_EREGs are used mainly for arithmetic operations. */
|
||||
#define TMP_EREG1 15
|
||||
#define TMP_EREG2 24
|
||||
/* Floating point status register. */
|
||||
|
|
@ -86,7 +86,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
|||
#define FS(s) ((s) << 11)
|
||||
#define FD(d) ((d) << 6)
|
||||
#define IMM(imm) ((imm) & 0xffff)
|
||||
#define SH_IMM(imm) ((imm & 0x1f) << 6)
|
||||
#define SH_IMM(imm) ((imm) << 6)
|
||||
|
||||
#define DR(dr) (reg_map[dr])
|
||||
#define HI(opcode) ((opcode) << 26)
|
||||
|
|
@ -96,8 +96,8 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
|||
|
||||
#define ABS_fmt (HI(17) | FMT_SD | LO(5))
|
||||
#define ADD_fmt (HI(17) | FMT_SD | LO(0))
|
||||
#define ADDU (HI(0) | LO(33))
|
||||
#define ADDIU (HI(9))
|
||||
#define ADDU (HI(0) | LO(33))
|
||||
#define AND (HI(0) | LO(36))
|
||||
#define ANDI (HI(12))
|
||||
#define B (HI(4))
|
||||
|
|
@ -116,9 +116,25 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
|||
#define C_UEQ_fmt (HI(17) | FMT_SD | LO(51))
|
||||
#define C_ULE_fmt (HI(17) | FMT_SD | LO(55))
|
||||
#define C_ULT_fmt (HI(17) | FMT_SD | LO(53))
|
||||
#define DADDIU (HI(25))
|
||||
#define DADDU (HI(0) | LO(45))
|
||||
#define DDIV (HI(0) | LO(30))
|
||||
#define DDIVU (HI(0) | LO(31))
|
||||
#define DIV (HI(0) | LO(26))
|
||||
#define DIVU (HI(0) | LO(27))
|
||||
#define DIV_fmt (HI(17) | FMT_SD | LO(3))
|
||||
#define DMULT (HI(0) | LO(28))
|
||||
#define DMULTU (HI(0) | LO(29))
|
||||
#define DSLL (HI(0) | LO(56))
|
||||
#define DSLL32 (HI(0) | LO(60))
|
||||
#define DSLLV (HI(0) | LO(20))
|
||||
#define DSRA (HI(0) | LO(59))
|
||||
#define DSRA32 (HI(0) | LO(63))
|
||||
#define DSRAV (HI(0) | LO(23))
|
||||
#define DSRL (HI(0) | LO(58))
|
||||
#define DSRL32 (HI(0) | LO(62))
|
||||
#define DSRLV (HI(0) | LO(22))
|
||||
#define DSUBU (HI(0) | LO(47))
|
||||
#define J (HI(2))
|
||||
#define JAL (HI(3))
|
||||
#define JALR (HI(0) | LO(9))
|
||||
|
|
@ -129,8 +145,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
|||
#define MFHI (HI(0) | LO(16))
|
||||
#define MFLO (HI(0) | LO(18))
|
||||
#define MOV_fmt (HI(17) | FMT_SD | LO(6))
|
||||
#define MOVN (HI(0) | LO(11))
|
||||
#define MOVZ (HI(0) | LO(10))
|
||||
#define MUL_fmt (HI(17) | FMT_SD | LO(2))
|
||||
#define MULT (HI(0) | LO(24))
|
||||
#define MULTU (HI(0) | LO(25))
|
||||
|
|
@ -158,6 +172,7 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = {
|
|||
|
||||
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
|
||||
#define CLZ (HI(28) | LO(32))
|
||||
#define DCLZ (HI(28) | LO(36))
|
||||
#define MUL (HI(28) | LO(2))
|
||||
#define SEB (HI(31) | (16 << 6) | LO(32))
|
||||
#define SEH (HI(31) | (24 << 6) | LO(32))
|
||||
|
|
@ -198,15 +213,20 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_si flags)
|
|||
return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16);
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
|
||||
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
|
||||
{
|
||||
sljit_sw diff;
|
||||
sljit_uw target_addr;
|
||||
sljit_ins *inst;
|
||||
sljit_ins saved_inst;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
|
||||
return code_ptr;
|
||||
#else
|
||||
if (jump->flags & SLJIT_REWRITABLE_JUMP)
|
||||
return code_ptr;
|
||||
#endif
|
||||
|
||||
if (jump->flags & JUMP_ADDR)
|
||||
target_addr = jump->u.target;
|
||||
|
|
@ -218,6 +238,11 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
|
|||
if (jump->flags & IS_COND)
|
||||
inst--;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if (jump->flags & IS_CALL)
|
||||
goto keep_address;
|
||||
#endif
|
||||
|
||||
/* B instructions. */
|
||||
if (jump->flags & IS_MOVABLE) {
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst)) >> 2;
|
||||
|
|
@ -237,24 +262,34 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
|
|||
return inst;
|
||||
}
|
||||
}
|
||||
else {
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
|
||||
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
|
||||
jump->flags |= PATCH_B;
|
||||
|
||||
diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1)) >> 2;
|
||||
if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
|
||||
jump->flags |= PATCH_B;
|
||||
|
||||
if (!(jump->flags & IS_COND)) {
|
||||
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
|
||||
if (!(jump->flags & IS_COND)) {
|
||||
inst[0] = (jump->flags & IS_JAL) ? BAL : B;
|
||||
inst[1] = NOP;
|
||||
return inst + 1;
|
||||
}
|
||||
inst[0] = inst[0] ^ invert_branch(jump->flags);
|
||||
inst[1] = NOP;
|
||||
jump->addr -= sizeof(sljit_ins);
|
||||
return inst + 1;
|
||||
}
|
||||
inst[0] = inst[0] ^ invert_branch(jump->flags);
|
||||
inst[1] = NOP;
|
||||
jump->addr -= sizeof(sljit_ins);
|
||||
return inst + 1;
|
||||
}
|
||||
|
||||
if (jump->flags & IS_COND) {
|
||||
if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
|
||||
if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~0xfffffff)) {
|
||||
jump->flags |= PATCH_J;
|
||||
saved_inst = inst[0];
|
||||
inst[0] = inst[-1];
|
||||
inst[-1] = (saved_inst & 0xffff0000) | 3;
|
||||
inst[1] = J;
|
||||
inst[2] = NOP;
|
||||
return inst + 2;
|
||||
}
|
||||
else if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
|
||||
jump->flags |= PATCH_J;
|
||||
inst[0] = (inst[0] & 0xffff0000) | 3;
|
||||
inst[1] = NOP;
|
||||
|
|
@ -263,26 +298,48 @@ static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins
|
|||
jump->addr += sizeof(sljit_ins);
|
||||
return inst + 3;
|
||||
}
|
||||
return code_ptr;
|
||||
}
|
||||
|
||||
/* J instuctions. */
|
||||
if (jump->flags & IS_MOVABLE) {
|
||||
if ((target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
|
||||
else {
|
||||
/* J instuctions. */
|
||||
if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
|
||||
jump->flags |= PATCH_J;
|
||||
inst[0] = inst[-1];
|
||||
inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
|
||||
jump->addr -= sizeof(sljit_ins);
|
||||
return inst;
|
||||
}
|
||||
|
||||
if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
|
||||
jump->flags |= PATCH_J;
|
||||
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
|
||||
inst[1] = NOP;
|
||||
return inst + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
|
||||
jump->flags |= PATCH_J;
|
||||
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
|
||||
inst[1] = NOP;
|
||||
return inst + 1;
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
keep_address:
|
||||
if (target_addr <= 0x7fffffff) {
|
||||
jump->flags |= PATCH_ABS32;
|
||||
if (jump->flags & IS_COND) {
|
||||
inst[0] -= 4;
|
||||
inst++;
|
||||
}
|
||||
inst[2] = inst[6];
|
||||
inst[3] = inst[7];
|
||||
return inst + 3;
|
||||
}
|
||||
if (target_addr <= 0x7fffffffffffl) {
|
||||
jump->flags |= PATCH_ABS48;
|
||||
if (jump->flags & IS_COND) {
|
||||
inst[0] -= 2;
|
||||
inst++;
|
||||
}
|
||||
inst[4] = inst[6];
|
||||
inst[5] = inst[7];
|
||||
return inst + 5;
|
||||
}
|
||||
#endif
|
||||
|
||||
return code_ptr;
|
||||
}
|
||||
|
|
@ -340,9 +397,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
jump->addr = (sljit_uw)(code_ptr - 3);
|
||||
#else
|
||||
#error "Implementation required"
|
||||
jump->addr = (sljit_uw)(code_ptr - 7);
|
||||
#endif
|
||||
code_ptr = optimize_jump(jump, code_ptr, code);
|
||||
code_ptr = detect_jump_type(jump, code_ptr, code);
|
||||
jump = jump->next;
|
||||
}
|
||||
if (const_ && const_->addr == word_count) {
|
||||
|
|
@ -391,7 +448,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
|
||||
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
|
||||
#else
|
||||
#error "Implementation required"
|
||||
if (jump->flags & PATCH_ABS32) {
|
||||
SLJIT_ASSERT(addr <= 0x7fffffff);
|
||||
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
|
||||
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
|
||||
}
|
||||
else if (jump->flags & PATCH_ABS48) {
|
||||
SLJIT_ASSERT(addr <= 0x7fffffffffffl);
|
||||
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
|
||||
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
|
||||
buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
|
||||
}
|
||||
else {
|
||||
buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
|
||||
buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
|
||||
buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
|
||||
buf_ptr[5] = (buf_ptr[5] & 0xffff0000) | (addr & 0xffff);
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
jump = jump->next;
|
||||
|
|
@ -473,7 +546,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
#endif
|
||||
|
||||
local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
local_size = (local_size + 15) & ~0xf;
|
||||
#else
|
||||
local_size = (local_size + 31) & ~0x1f;
|
||||
#endif
|
||||
compiler->local_size = local_size;
|
||||
|
||||
if (local_size <= SIMM_MAX) {
|
||||
|
|
@ -523,7 +600,11 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
|
|||
#endif
|
||||
|
||||
local_size += (saveds + 1 + 4) * sizeof(sljit_sw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
compiler->local_size = (local_size + 15) & ~0xf;
|
||||
#else
|
||||
compiler->local_size = (local_size + 31) & ~0x1f;
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
|
||||
|
|
@ -612,11 +693,11 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
|
|||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if ((!(flags & WRITE_BACK) || !(arg & 0xf)) && !(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) && !(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
|
||||
/* Works for both absoulte and relative addresses. */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & 0xf)
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
|
||||
| TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -631,10 +712,10 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
|
||||
|
||||
/* Simple operation except for updates. */
|
||||
if (arg & 0xf0) {
|
||||
if (arg & OFFS_REG_MASK) {
|
||||
argw &= 0x3;
|
||||
next_argw &= 0x3;
|
||||
if (argw && argw == next_argw && (arg == next_arg || (arg & 0xf0) == (next_arg & 0xf0)))
|
||||
if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -666,9 +747,9 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
tmp_ar = DR(TMP_REG1);
|
||||
delay_slot = MOVABLE_INS;
|
||||
}
|
||||
base = arg & 0xf;
|
||||
base = arg & REG_MASK;
|
||||
|
||||
if (SLJIT_UNLIKELY(arg & 0xf0)) {
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
if ((flags & WRITE_BACK) && reg_ar == DR(base)) {
|
||||
SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar);
|
||||
|
|
@ -681,7 +762,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
if (!(flags & WRITE_BACK)) {
|
||||
if (arg == compiler->cache_arg)
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
|
||||
if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
|
||||
if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
|
||||
if (arg == next_arg && argw == (next_argw & 0x3)) {
|
||||
compiler->cache_arg = arg;
|
||||
compiler->cache_argw = argw;
|
||||
|
|
@ -693,7 +774,7 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
}
|
||||
}
|
||||
else {
|
||||
if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) {
|
||||
if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base)));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
|
@ -701,23 +782,23 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
}
|
||||
|
||||
if (SLJIT_UNLIKELY(argw)) {
|
||||
compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
|
||||
compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
|
||||
compiler->cache_argw = argw;
|
||||
FAIL_IF(push_inst(compiler, SLL_W | T((arg >> 4) & 0xf) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
|
||||
FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
|
||||
}
|
||||
|
||||
if (!(flags & WRITE_BACK)) {
|
||||
if (arg == next_arg && argw == (next_argw & 0x3)) {
|
||||
compiler->cache_arg = arg;
|
||||
compiler->cache_argw = argw;
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
|
||||
tmp_ar = DR(TMP_REG3);
|
||||
}
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | DA(tmp_ar), tmp_ar));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(base), DR(base)));
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(base), DR(base)));
|
||||
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), delay_slot);
|
||||
}
|
||||
|
||||
|
|
@ -829,7 +910,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
if (GET_FLAGS(op))
|
||||
flags |= UNUSED_DEST;
|
||||
}
|
||||
else if (dst <= TMP_REG3) {
|
||||
else if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
|
|
@ -862,7 +943,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
}
|
||||
|
||||
/* Source 1. */
|
||||
if (src1 <= TMP_REG3) {
|
||||
if (FAST_IS_REG(src1)) {
|
||||
src1_r = src1;
|
||||
flags |= REG1_SOURCE;
|
||||
}
|
||||
|
|
@ -883,7 +964,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
}
|
||||
|
||||
/* Source 2. */
|
||||
if (src2 <= TMP_REG3) {
|
||||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
|
|
@ -941,6 +1022,10 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op)
|
||||
{
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
sljit_si int_op = op & SLJIT_INT_OP;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op0(compiler, op);
|
||||
|
||||
|
|
@ -952,7 +1037,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
case SLJIT_UMUL:
|
||||
case SLJIT_SMUL:
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? DMULTU : DMULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
#endif
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
|
||||
case SLJIT_UDIV:
|
||||
|
|
@ -961,7 +1050,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler
|
|||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
#endif
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if (int_op)
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DDIVU : DDIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
#else
|
||||
FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_SCRATCH_REG1) | T(SLJIT_SCRATCH_REG2), MOVABLE_INS));
|
||||
#endif
|
||||
|
||||
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_SCRATCH_REG1), DR(SLJIT_SCRATCH_REG1)));
|
||||
return push_inst(compiler, MFHI | D(SLJIT_SCRATCH_REG2), DR(SLJIT_SCRATCH_REG2));
|
||||
}
|
||||
|
|
@ -975,6 +1073,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
{
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# define flags 0
|
||||
#else
|
||||
sljit_si flags = 0;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
|
|
@ -982,50 +1082,74 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
ADJUST_LOCAL_OFFSET(dst, dstw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if ((op & SLJIT_INT_OP) && GET_OPCODE(op) >= SLJIT_NOT) {
|
||||
flags |= INT_DATA | SIGNED_DATA;
|
||||
if (src & SLJIT_IMM)
|
||||
srcw = (sljit_si)srcw;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_MOV:
|
||||
case SLJIT_MOV_P:
|
||||
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOV_UI:
|
||||
return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_UI, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ui)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOV_SI:
|
||||
return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_si)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOV_UB:
|
||||
return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_SB:
|
||||
return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_UH:
|
||||
return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
|
||||
|
||||
case SLJIT_MOV_SH:
|
||||
return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU:
|
||||
case SLJIT_MOVU_P:
|
||||
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
||||
case SLJIT_MOVU_UI:
|
||||
return emit_op(compiler, SLJIT_MOV_UI, flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_UI, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ui)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOVU_SI:
|
||||
return emit_op(compiler, SLJIT_MOV_SI, flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
#else
|
||||
return emit_op(compiler, SLJIT_MOV_SI, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_si)srcw : srcw);
|
||||
#endif
|
||||
|
||||
case SLJIT_MOVU_UB:
|
||||
return emit_op(compiler, SLJIT_MOV_UB, flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_UB, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_ub)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_SB:
|
||||
return emit_op(compiler, SLJIT_MOV_SB, flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_SB, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sb)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_UH:
|
||||
return emit_op(compiler, SLJIT_MOV_UH, flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_UH, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_uh)srcw : srcw);
|
||||
|
||||
case SLJIT_MOVU_SH:
|
||||
return emit_op(compiler, SLJIT_MOV_SH, flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
|
||||
return emit_op(compiler, SLJIT_MOV_SH, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_sh)srcw : srcw);
|
||||
|
||||
case SLJIT_NOT:
|
||||
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
|
||||
|
|
@ -1038,6 +1162,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler
|
|||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# undef flags
|
||||
#endif
|
||||
|
|
@ -1050,6 +1175,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
{
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# define flags 0
|
||||
#else
|
||||
sljit_si flags = 0;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
|
|
@ -1058,6 +1185,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
ADJUST_LOCAL_OFFSET(src1, src1w);
|
||||
ADJUST_LOCAL_OFFSET(src2, src2w);
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if (op & SLJIT_INT_OP) {
|
||||
flags |= INT_DATA | SIGNED_DATA;
|
||||
if (src1 & SLJIT_IMM)
|
||||
src1w = (sljit_si)src1w;
|
||||
if (src2 & SLJIT_IMM)
|
||||
src2w = (sljit_si)src2w;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (GET_OPCODE(op)) {
|
||||
case SLJIT_ADD:
|
||||
case SLJIT_ADDC:
|
||||
|
|
@ -1082,12 +1219,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler
|
|||
if (src2 & SLJIT_IMM)
|
||||
src2w &= 0x1f;
|
||||
#else
|
||||
SLJIT_ASSERT_STOP();
|
||||
if (src2 & SLJIT_IMM) {
|
||||
if (op & SLJIT_INT_OP)
|
||||
src2w &= 0x1f;
|
||||
else
|
||||
src2w &= 0x3f;
|
||||
}
|
||||
#endif
|
||||
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
|
||||
}
|
||||
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# undef flags
|
||||
#endif
|
||||
|
|
@ -1121,9 +1264,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
{
|
||||
#if (defined SLJIT_QEMU && SLJIT_QEMU)
|
||||
/* Qemu says fir is 0 by default. */
|
||||
return 1;
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#elif defined(__GNUC__)
|
||||
sljit_sw fir;
|
||||
asm ("cfc1 %0, $0" : "=r"(fir));
|
||||
|
|
@ -1150,14 +1292,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
compiler->cache_argw = 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst > SLJIT_FLOAT_REG6) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
dst <<= 1;
|
||||
|
||||
if (src > SLJIT_FLOAT_REG6) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
|
|
@ -1185,9 +1327,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
return push_inst(compiler, C_UN_fmt | FMT(op) | FT(src) | FS(dst), FCSR_FCC);
|
||||
}
|
||||
|
||||
dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
if (src > SLJIT_FLOAT_REG6) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
|
||||
src = dst_fr;
|
||||
}
|
||||
|
|
@ -1229,9 +1371,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
|
||||
if (src1 > SLJIT_FLOAT_REG6) {
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
FAIL_IF(compiler->error);
|
||||
src1 = TMP_FREG1;
|
||||
|
|
@ -1241,7 +1383,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 > SLJIT_FLOAT_REG6) {
|
||||
if (src2 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
|
||||
FAIL_IF(compiler->error);
|
||||
src2 = TMP_FREG2;
|
||||
|
|
@ -1309,7 +1451,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (dst <= TMP_REG3)
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
|
||||
|
||||
/* Memory. */
|
||||
|
|
@ -1322,7 +1464,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= TMP_REG3)
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
|
||||
else if (src & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
|
||||
|
|
@ -1357,7 +1499,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
|
|||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
#define JUMP_LENGTH 4
|
||||
#else
|
||||
#error "Implementation required"
|
||||
#define JUMP_LENGTH 8
|
||||
#endif
|
||||
|
||||
#define BR_Z(src) \
|
||||
|
|
@ -1467,7 +1609,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
} else {
|
||||
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
|
||||
/* Cannot be optimized out if type is >= CALL0. */
|
||||
jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0);
|
||||
jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? IS_CALL : 0);
|
||||
PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
/* A NOP if type < CALL1. */
|
||||
|
|
@ -1631,14 +1773,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|
|||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
if (src1 > SLJIT_FLOAT_REG6) {
|
||||
if (src1 & SLJIT_MEM) {
|
||||
PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
|
||||
src1 = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 > SLJIT_FLOAT_REG6) {
|
||||
if (src2 & SLJIT_MEM) {
|
||||
PTR_FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
|
||||
src2 = TMP_FREG2;
|
||||
}
|
||||
|
|
@ -1714,7 +1856,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
check_sljit_emit_ijump(compiler, type, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= TMP_REG3) {
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (DR(src) != 4)
|
||||
src_r = src;
|
||||
else
|
||||
|
|
@ -1770,6 +1912,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
{
|
||||
sljit_si sugg_dst_ar, dst_ar;
|
||||
sljit_si flags = GET_ALL_FLAGS(op);
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# define mem_type WORD_DATA
|
||||
#else
|
||||
sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
|
||||
#endif
|
||||
|
||||
CHECK_ERROR();
|
||||
check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type);
|
||||
|
|
@ -1779,13 +1926,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
return SLJIT_SUCCESS;
|
||||
|
||||
op = GET_OPCODE(op);
|
||||
sugg_dst_ar = DR((op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2);
|
||||
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
|
||||
if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI)
|
||||
mem_type = INT_DATA | SIGNED_DATA;
|
||||
#endif
|
||||
sugg_dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
if (op >= SLJIT_ADD && (src & SLJIT_MEM)) {
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
|
||||
FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
|
||||
src = TMP_REG1;
|
||||
srcw = 0;
|
||||
}
|
||||
|
|
@ -1853,15 +2004,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
if (op >= SLJIT_ADD) {
|
||||
if (DR(TMP_REG2) != dst_ar)
|
||||
FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
|
||||
return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
|
||||
return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0);
|
||||
}
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw);
|
||||
return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw);
|
||||
|
||||
if (sugg_dst_ar != dst_ar)
|
||||
return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar);
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
|
||||
# undef mem_type
|
||||
#endif
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value)
|
||||
|
|
@ -1877,7 +2032,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
|
||||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
|
|||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
|
||||
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
|
||||
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sl
|
|||
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
|
||||
|
||||
if (!(imm & ~0xffff))
|
||||
return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
|
||||
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
|
||||
|
||||
if (imm <= SLJIT_W(0x7fffffff) && imm >= SLJIT_W(-0x80000000)) {
|
||||
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
|
||||
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
|
||||
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -87,7 +87,7 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
|
|||
#define TMP_REG2 (SLJIT_NO_REGISTERS + 2)
|
||||
#define TMP_REG3 (SLJIT_NO_REGISTERS + 3)
|
||||
#define TMP_REG4 (SLJIT_NO_REGISTERS + 4)
|
||||
#define LINK_REG (SLJIT_NO_REGISTERS + 5)
|
||||
#define TMP_LINK (SLJIT_NO_REGISTERS + 5)
|
||||
|
||||
#define TMP_FREG1 (0)
|
||||
#define TMP_FREG2 ((SLJIT_FLOAT_REG6 + 1) << 1)
|
||||
|
|
@ -190,7 +190,7 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
|
||||
static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code)
|
||||
{
|
||||
sljit_sw diff;
|
||||
sljit_uw target_addr;
|
||||
|
|
@ -311,7 +311,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
|
|||
#else
|
||||
jump->addr = (sljit_uw)(code_ptr - 6);
|
||||
#endif
|
||||
code_ptr = optimize_jump(jump, code_ptr, code);
|
||||
code_ptr = detect_jump_type(jump, code_ptr, code);
|
||||
jump = jump->next;
|
||||
}
|
||||
if (const_ && const_->addr == word_count) {
|
||||
|
|
@ -465,7 +465,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
CHECK_ERROR();
|
||||
check_sljit_emit_return(compiler, op, src, srcw);
|
||||
|
||||
if (op != SLJIT_MOV || !(src <= TMP_REG3)) {
|
||||
if (op != SLJIT_MOV || !FAST_IS_REG(src)) {
|
||||
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
|
||||
src = SLJIT_SCRATCH_REG1;
|
||||
}
|
||||
|
|
@ -516,15 +516,15 @@ static sljit_si getput_arg_fast(struct sljit_compiler *compiler, sljit_si flags,
|
|||
{
|
||||
SLJIT_ASSERT(arg & SLJIT_MEM);
|
||||
|
||||
if (!(flags & WRITE_BACK) || !(arg & 0xf)) {
|
||||
if ((!(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN)
|
||||
|| ((arg & 0xf0) && (argw & 0x3) == 0)) {
|
||||
if (!(flags & WRITE_BACK) || !(arg & REG_MASK)) {
|
||||
if ((!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN)
|
||||
|| ((arg & OFFS_REG_MASK) && (argw & 0x3) == 0)) {
|
||||
/* Works for both absoulte and relative addresses (immediate case). */
|
||||
if (SLJIT_UNLIKELY(flags & ARG_TEST))
|
||||
return 1;
|
||||
FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK]
|
||||
| ((flags & MEM_MASK) <= GPR_REG ? D(reg) : DA(reg))
|
||||
| S1(arg & 0xf) | ((arg & 0xf0) ? S2((arg >> 4) & 0xf) : IMM(argw)),
|
||||
| S1(arg & REG_MASK) | ((arg & OFFS_REG_MASK) ? S2(OFFS_REG(arg)) : IMM(argw)),
|
||||
((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? DR(reg) : MOVABLE_INS));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -540,11 +540,11 @@ static sljit_si can_cache(sljit_si arg, sljit_sw argw, sljit_si next_arg, sljit_
|
|||
SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
|
||||
|
||||
/* Simple operation except for updates. */
|
||||
if (arg & 0xf0) {
|
||||
if (arg & OFFS_REG_MASK) {
|
||||
argw &= 0x3;
|
||||
SLJIT_ASSERT(argw);
|
||||
next_argw &= 0x3;
|
||||
if ((arg & 0xf0) == (next_arg & 0xf0) && argw == next_argw)
|
||||
if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == next_argw)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -566,25 +566,25 @@ static sljit_si getput_arg(struct sljit_compiler *compiler, sljit_si flags, slji
|
|||
next_argw = 0;
|
||||
}
|
||||
|
||||
base = arg & 0xf;
|
||||
if (SLJIT_UNLIKELY(arg & 0xf0)) {
|
||||
base = arg & REG_MASK;
|
||||
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
|
||||
argw &= 0x3;
|
||||
SLJIT_ASSERT(argw != 0);
|
||||
|
||||
/* Using the cache. */
|
||||
if (((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) && (argw == compiler->cache_argw))
|
||||
if (((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) && (argw == compiler->cache_argw))
|
||||
arg2 = TMP_REG3;
|
||||
else {
|
||||
if ((arg & 0xf0) == (next_arg & 0xf0) && argw == (next_argw & 0x3)) {
|
||||
compiler->cache_arg = SLJIT_MEM | (arg & 0xf0);
|
||||
if ((arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK) && argw == (next_argw & 0x3)) {
|
||||
compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
|
||||
compiler->cache_argw = argw;
|
||||
arg2 = TMP_REG3;
|
||||
}
|
||||
else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && (reg << 4) != (arg & 0xf0))
|
||||
else if ((flags & LOAD_DATA) && ((flags & MEM_MASK) <= GPR_REG) && reg != base && reg != OFFS_REG(arg))
|
||||
arg2 = reg;
|
||||
else /* It must be a mov operation, so tmp1 must be free to use. */
|
||||
arg2 = TMP_REG1;
|
||||
FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1((arg >> 4) & 0xf) | IMM_ARG | argw, DR(arg2)));
|
||||
FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | argw, DR(arg2)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -658,7 +658,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM))
|
||||
return SLJIT_SUCCESS;
|
||||
}
|
||||
else if (dst <= TMP_REG3) {
|
||||
else if (FAST_IS_REG(dst)) {
|
||||
dst_r = dst;
|
||||
flags |= REG_DEST;
|
||||
if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
|
|
@ -689,7 +689,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
}
|
||||
|
||||
/* Source 1. */
|
||||
if (src1 <= TMP_REG3)
|
||||
if (FAST_IS_REG(src1))
|
||||
src1_r = src1;
|
||||
else if (src1 & SLJIT_IMM) {
|
||||
if (src1w) {
|
||||
|
|
@ -708,7 +708,7 @@ static sljit_si emit_op(struct sljit_compiler *compiler, sljit_si op, sljit_si f
|
|||
}
|
||||
|
||||
/* Source 2. */
|
||||
if (src2 <= TMP_REG3) {
|
||||
if (FAST_IS_REG(src2)) {
|
||||
src2_r = src2;
|
||||
flags |= REG2_SOURCE;
|
||||
if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI)
|
||||
|
|
@ -943,7 +943,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *co
|
|||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void)
|
||||
{
|
||||
#ifdef SLJIT_IS_FPU_AVAILABLE
|
||||
return SLJIT_IS_FPU_AVAILABLE;
|
||||
#else
|
||||
/* Available by default. */
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_SINGLE_OP) >> 7))
|
||||
|
|
@ -963,14 +968,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
compiler->cache_argw = 0;
|
||||
|
||||
if (GET_OPCODE(op) == SLJIT_CMPD) {
|
||||
if (dst > SLJIT_FLOAT_REG6) {
|
||||
if (dst & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, dst, dstw, src, srcw));
|
||||
dst = TMP_FREG1;
|
||||
}
|
||||
else
|
||||
dst <<= 1;
|
||||
|
||||
if (src > SLJIT_FLOAT_REG6) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src, srcw, 0, 0));
|
||||
src = TMP_FREG2;
|
||||
}
|
||||
|
|
@ -980,9 +985,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compile
|
|||
return push_inst(compiler, SELECT_FOP(op, FCMPS, FCMPD) | S1A(dst) | S2A(src), FCC_IS_SET | MOVABLE_INS);
|
||||
}
|
||||
|
||||
dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG1 : (dst << 1);
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG1;
|
||||
|
||||
if (src > SLJIT_FLOAT_REG6) {
|
||||
if (src & SLJIT_MEM) {
|
||||
FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_fr, src, srcw, dst, dstw));
|
||||
src = dst_fr;
|
||||
}
|
||||
|
|
@ -1031,9 +1036,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
||||
dst_fr = (dst > SLJIT_FLOAT_REG6) ? TMP_FREG2 : (dst << 1);
|
||||
dst_fr = FAST_IS_REG(dst) ? (dst << 1) : TMP_FREG2;
|
||||
|
||||
if (src1 > SLJIT_FLOAT_REG6) {
|
||||
if (src1 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
|
||||
FAIL_IF(compiler->error);
|
||||
src1 = TMP_FREG1;
|
||||
|
|
@ -1043,7 +1048,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compile
|
|||
else
|
||||
src1 <<= 1;
|
||||
|
||||
if (src2 > SLJIT_FLOAT_REG6) {
|
||||
if (src2 & SLJIT_MEM) {
|
||||
if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
|
||||
FAIL_IF(compiler->error);
|
||||
src2 = TMP_FREG2;
|
||||
|
|
@ -1114,11 +1119,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
if (dst == SLJIT_UNUSED)
|
||||
return SLJIT_SUCCESS;
|
||||
|
||||
if (dst <= TMP_REG3)
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(LINK_REG), DR(dst));
|
||||
if (FAST_IS_REG(dst))
|
||||
return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst));
|
||||
|
||||
/* Memory. */
|
||||
return emit_op_mem(compiler, WORD_DATA, LINK_REG, dst, dstw);
|
||||
return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw);
|
||||
}
|
||||
|
||||
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
|
||||
|
|
@ -1127,14 +1132,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
check_sljit_emit_fast_return(compiler, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= TMP_REG3)
|
||||
FAIL_IF(push_inst(compiler, OR | D(LINK_REG) | S1(0) | S2(src), DR(LINK_REG)));
|
||||
if (FAST_IS_REG(src))
|
||||
FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));
|
||||
else if (src & SLJIT_MEM)
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, LINK_REG, src, srcw));
|
||||
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));
|
||||
else if (src & SLJIT_IMM)
|
||||
FAIL_IF(load_immediate(compiler, LINK_REG, srcw));
|
||||
FAIL_IF(load_immediate(compiler, TMP_LINK, srcw));
|
||||
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(LINK_REG) | IMM(8), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
}
|
||||
|
||||
|
|
@ -1269,7 +1274,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
|
|||
}
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
|
||||
PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
|
||||
PTR_FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(TMP_REG2) | IMM(0), UNMOVABLE_INS));
|
||||
jump->addr = compiler->size;
|
||||
PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
|
||||
|
||||
|
|
@ -1285,7 +1290,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
check_sljit_emit_ijump(compiler, type, src, srcw);
|
||||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if (src <= TMP_REG3)
|
||||
if (FAST_IS_REG(src))
|
||||
src_r = src;
|
||||
else if (src & SLJIT_IMM) {
|
||||
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
|
||||
|
|
@ -1305,7 +1310,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil
|
|||
src_r = TMP_REG2;
|
||||
}
|
||||
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? LINK_REG : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
|
||||
FAIL_IF(push_inst(compiler, JMPL | D(type >= SLJIT_FAST_CALL ? TMP_LINK : 0) | S1(src_r) | IMM(0), UNMOVABLE_INS));
|
||||
if (jump)
|
||||
jump->addr = compiler->size;
|
||||
return push_inst(compiler, NOP, UNMOVABLE_INS);
|
||||
|
|
@ -1327,7 +1332,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com
|
|||
|
||||
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
|
||||
op = GET_OPCODE(op);
|
||||
reg = (op < SLJIT_ADD && dst <= TMP_REG3) ? dst : TMP_REG2;
|
||||
reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
|
||||
|
||||
compiler->cache_arg = 0;
|
||||
compiler->cache_argw = 0;
|
||||
|
|
@ -1368,12 +1373,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
|
|||
PTR_FAIL_IF(!const_);
|
||||
set_const(const_, compiler);
|
||||
|
||||
reg = (dst <= TMP_REG3) ? dst : TMP_REG2;
|
||||
reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
|
||||
|
||||
PTR_FAIL_IF(emit_const(compiler, reg, init_value));
|
||||
|
||||
if (dst & SLJIT_MEM)
|
||||
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
|
||||
|
||||
return const_;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -89,11 +89,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
FAIL_IF(!inst);
|
||||
|
||||
INC_SIZE(size);
|
||||
PUSH_REG(reg_map[TMP_REGISTER]);
|
||||
PUSH_REG(reg_map[TMP_REG1]);
|
||||
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_REG | (reg_map[TMP_REGISTER] << 3) | 0x4 /* esp */;
|
||||
*inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
|
||||
}
|
||||
#endif
|
||||
if (saveds > 2)
|
||||
|
|
@ -121,17 +121,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil
|
|||
#else
|
||||
if (args > 0) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 2;
|
||||
}
|
||||
if (args > 1) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 3;
|
||||
}
|
||||
if (args > 2) {
|
||||
*inst++ = MOV_r_rm;
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
|
||||
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REG1];
|
||||
*inst++ = sizeof(sljit_sw) * 4;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -245,7 +245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi
|
|||
POP_REG(reg_map[SLJIT_SAVED_REG2]);
|
||||
if (compiler->saveds > 2)
|
||||
POP_REG(reg_map[SLJIT_SAVED_REG3]);
|
||||
POP_REG(reg_map[TMP_REGISTER]);
|
||||
POP_REG(reg_map[TMP_REG1]);
|
||||
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
|
||||
if (compiler->args > 2)
|
||||
RET_I16(sizeof(sljit_sw));
|
||||
|
|
@ -301,9 +301,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & 0x0f) == SLJIT_UNUSED)
|
||||
if ((b & REG_MASK) == SLJIT_UNUSED)
|
||||
inst_size += sizeof(sljit_sw);
|
||||
else if (immb != 0 && !(b & 0xf0)) {
|
||||
else if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
|
|
@ -311,10 +311,10 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
inst_size += sizeof(sljit_sw);
|
||||
}
|
||||
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
|
||||
b |= SLJIT_LOCALS_REG << 4;
|
||||
if ((b & REG_MASK) == SLJIT_LOCALS_REG && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_LOCALS_REG);
|
||||
|
||||
if ((b & 0xf0) != SLJIT_UNUSED)
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED)
|
||||
inst_size += 1; /* SIB byte. */
|
||||
}
|
||||
|
||||
|
|
@ -393,8 +393,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
#else
|
||||
*buf_ptr++ |= MOD_REG + reg_map[b];
|
||||
#endif
|
||||
else if ((b & 0x0f) != SLJIT_UNUSED) {
|
||||
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_LOCALS_REG)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
|
|
@ -402,11 +402,11 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
*buf_ptr |= 0x80;
|
||||
}
|
||||
|
||||
if ((b & 0xf0) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_map[b & 0x0f];
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_map[b & REG_MASK];
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3);
|
||||
*buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0) {
|
||||
|
|
@ -420,7 +420,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3) | (immb << 6);
|
||||
*buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -495,9 +495,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REGISTER;
|
||||
dst = TMP_REG1;
|
||||
|
||||
if (dst <= TMP_REGISTER) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
/* Unused dest is possible here. */
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
|
@ -524,7 +524,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
|
||||
CHECK_EXTRA_REGS(src, srcw, (void)0);
|
||||
|
||||
if (src <= TMP_REGISTER) {
|
||||
if (FAST_IS_REG(src)) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si
|
|||
{
|
||||
sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
|
||||
|
||||
if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
|
||||
if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
|
||||
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
|
||||
*(sljit_sw*)code_ptr = delta;
|
||||
}
|
||||
|
|
@ -420,12 +420,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
size &= 0xf;
|
||||
inst_size = size;
|
||||
|
||||
if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) {
|
||||
if ((b & SLJIT_MEM) && !(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
|
||||
if (emit_load_imm64(compiler, TMP_REG3, immb))
|
||||
return NULL;
|
||||
immb = 0;
|
||||
if (b & 0xf)
|
||||
b |= TMP_REG3 << 4;
|
||||
if (b & REG_MASK)
|
||||
b |= TO_OFFS_REG(TMP_REG3);
|
||||
else
|
||||
b |= TMP_REG3;
|
||||
}
|
||||
|
|
@ -445,12 +445,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
/* Calculate size of b. */
|
||||
inst_size += 1; /* mod r/m byte. */
|
||||
if (b & SLJIT_MEM) {
|
||||
if ((b & 0x0f) == SLJIT_UNUSED)
|
||||
if ((b & REG_MASK) == SLJIT_UNUSED)
|
||||
inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
|
||||
else {
|
||||
if (reg_map[b & 0x0f] >= 8)
|
||||
if (reg_map[b & REG_MASK] >= 8)
|
||||
rex |= REX_B;
|
||||
if (immb != 0 && !(b & 0xf0)) {
|
||||
if (immb != 0 && !(b & OFFS_REG_MASK)) {
|
||||
/* Immediate operand. */
|
||||
if (immb <= 127 && immb >= -128)
|
||||
inst_size += sizeof(sljit_sb);
|
||||
|
|
@ -459,12 +459,12 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
}
|
||||
}
|
||||
|
||||
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
|
||||
b |= SLJIT_LOCALS_REG << 4;
|
||||
if ((b & REG_MASK) == SLJIT_LOCALS_REG && !(b & OFFS_REG_MASK))
|
||||
b |= TO_OFFS_REG(SLJIT_LOCALS_REG);
|
||||
|
||||
if ((b & 0xf0) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
|
||||
inst_size += 1; /* SIB byte. */
|
||||
if (reg_map[(b >> 4) & 0x0f] >= 8)
|
||||
if (reg_map[OFFS_REG(b)] >= 8)
|
||||
rex |= REX_X;
|
||||
}
|
||||
}
|
||||
|
|
@ -563,8 +563,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
#else
|
||||
*buf_ptr++ |= MOD_REG + reg_lmap[b];
|
||||
#endif
|
||||
else if ((b & 0x0f) != SLJIT_UNUSED) {
|
||||
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
|
||||
else if ((b & REG_MASK) != SLJIT_UNUSED) {
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_LOCALS_REG)) {
|
||||
if (immb != 0) {
|
||||
if (immb <= 127 && immb >= -128)
|
||||
*buf_ptr |= 0x40;
|
||||
|
|
@ -572,11 +572,11 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
*buf_ptr |= 0x80;
|
||||
}
|
||||
|
||||
if ((b & 0xf0) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_lmap[b & 0x0f];
|
||||
if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
|
||||
*buf_ptr++ |= reg_lmap[b & REG_MASK];
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3);
|
||||
*buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3);
|
||||
}
|
||||
|
||||
if (immb != 0) {
|
||||
|
|
@ -590,7 +590,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si
|
|||
}
|
||||
else {
|
||||
*buf_ptr++ |= 0x04;
|
||||
*buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6);
|
||||
*buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -662,9 +662,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c
|
|||
|
||||
/* For UNUSED dst. Uncommon, but possible. */
|
||||
if (dst == SLJIT_UNUSED)
|
||||
dst = TMP_REGISTER;
|
||||
dst = TMP_REG1;
|
||||
|
||||
if (dst <= TMP_REGISTER) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
if (reg_map[dst] < 8) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
|
@ -698,11 +698,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *
|
|||
ADJUST_LOCAL_OFFSET(src, srcw);
|
||||
|
||||
if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) {
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw));
|
||||
src = TMP_REGISTER;
|
||||
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
|
||||
src = TMP_REG1;
|
||||
}
|
||||
|
||||
if (src <= TMP_REGISTER) {
|
||||
if (FAST_IS_REG(src)) {
|
||||
if (reg_map[src] < 8) {
|
||||
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
|
||||
FAIL_IF(!inst);
|
||||
|
|
@ -765,7 +765,7 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
|||
return SLJIT_SUCCESS; /* Empty instruction. */
|
||||
|
||||
if (src & SLJIT_IMM) {
|
||||
if (dst <= TMP_REGISTER) {
|
||||
if (FAST_IS_REG(dst)) {
|
||||
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
|
||||
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
|
||||
FAIL_IF(!inst);
|
||||
|
|
@ -782,9 +782,9 @@ static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
|
|||
return SLJIT_SUCCESS;
|
||||
}
|
||||
|
||||
dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
|
||||
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
|
||||
|
||||
if ((dst & SLJIT_MEM) && (src <= TMP_REGISTER))
|
||||
if ((dst & SLJIT_MEM) && FAST_IS_REG(src))
|
||||
dst_r = src;
|
||||
else {
|
||||
if (sign) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue