1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-15 02:29:32 +00:00

Merge pull request #1 from cc65/master

Update
This commit is contained in:
polluks2 2021-01-13 12:26:00 +01:00 committed by GitHub
commit 0636c4bc30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1032 additions and 888 deletions

View File

@ -15,6 +15,7 @@ PROMPT := $33 ; Used by GETLN
RNDL := $4E ; Random counter low
RNDH := $4F ; Random counter high
HIMEM := $73 ; Highest available memory address+1
CURLIN := $75 ; Current line number being executed
;-----------------------------------------------------------------------------
; Vectors

View File

@ -7,6 +7,7 @@
; Zero page, Commodore stuff
TXTPTR := $3D ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A0 ; 60HZ clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address

View File

@ -9,6 +9,7 @@
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $7A ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A0 ; 60 HZ clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address

View File

@ -10,6 +10,7 @@ TMPPTR := $22 ; Temporary ptr used by BASIC
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $3B ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A3 ; 60HZ clock
FNAM_LEN := $AB ; Length of filename
LFN := $AC ; Logical file number

View File

@ -9,6 +9,7 @@
VARTAB := $2D ; Pointer to start of BASIC variables
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
TXTPTR := $7A ; Pointer into BASIC source code
STATUS := $90 ; Kernal I/O completion status
TIME := $A0 ; 60HZ clock
FNAM_LEN := $B7 ; Length of filename
SECADR := $B9 ; Secondary address

View File

@ -73,7 +73,18 @@ Special locations:
Programs containing Atari 5200 specific code may use the <tt/atari5200.h/ header file.
This also includes access to operating system locations (e.g. hardware shadow registers) by a structure called
"<tt/OS/".
The names are the usual ones you can find in system reference manuals. Example:
<tscreen><verb>
...
OS.sdmctl = 0x00; // screen off
OS.color4 = 14; // white frame
tics = OS.rtclok[1] // get ticks
...
</verb></tscreen>
<sect1>Atari 5200 specific functions<p>
<itemize>

View File

@ -6,8 +6,9 @@
<url url="mailto:gregdk@users.sf.net" name="Greg King">
<abstract>
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
computers like the Commodore and Atari machines, but it is easily retargetable.
cc65 is a C compiler for 6502 targets. It supports several 6502-based home
computers such as the Commodore and Atari machines, but it easily is
retargetable.
</abstract>
<!-- Table of contents -->
@ -548,6 +549,8 @@ Here is a description of all the command line options:
<tag><tt/remap-zero/</tag>
Warn about a <tt/<ref id="pragma-charmap" name="#pragma charmap()">/
that changes a character's code number from/to 0x00.
<tag><tt/return-type/</tag>
Warn about no return statement in function returning non-void.
<tag><tt/struct-param/</tag>
Warn when passing structs by value.
<tag><tt/unknown-pragma/</tag>
@ -706,12 +709,13 @@ This cc65 version has some extensions to the ISO C standard.
places.
<p>
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
Both refer to the primary register that is used by the compiler to
evaluate expressions or return function results. <tt/__AX__/ is of
type <tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/
respectively. The pseudo variables may be used as lvalue and rvalue as
every other variable. They are most useful together with short
<item> There are three pseudo variables named <tt/__A__/, <tt/__AX__/ and
<tt/__EAX__/. They all refer to the primary register that is used
by the compiler to evaluate expressions or return function results.
<tt/__A__/ is of type <tt/unsigned char/, <tt/__AX__/ is of type
<tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/
respectively. The pseudo variables may be used as lvalue and rvalue
as every other variable. They are most useful together with short
sequences of assembler code. For example, the macro
<tscreen><verb>
@ -1011,7 +1015,7 @@ The compiler defines several macros at startup:
<tag><tt>__TELESTRAT__</tt></tag>
This macro is defined if the target is the Telestrat (-t telestrat).
<tag><tt>__TIME__</tt></tag>
This macro expands to the time of translation of the preprocessing
@ -1045,26 +1049,39 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma bss-name (&lsqb;push,&rsqb; &lt;name&gt;)</tt><label id="pragma-bss-name"><p>
<sect1><tt>#pragma bss-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-bss-name"><p>
This pragma changes the name used for the BSS segment (the BSS segment
is used to store variables with static storage duration and no explicit
initializer). The argument is a string enclosed in double quotes.
This pragma changes the name used for the BSS segment (the BSS segment is
used to store variables with static storage duration and no explicit
initializers). The <tt/name/ argument is a string enclosed in quotation
marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
Beware: The startup code will zero only the default BSS segment. If you
use another BSS segment, you have to do that yourself, otherwise
variables with static storage duration and no explicit initializer will
not have the value zero.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
The <tt/#pragma/ understands the push and pop parameters as explained above.
Beware: The start-up code will zero only the default BSS segment. If you use
another BSS segment, then you must do that yourself; otherwise, variables
with static storage duration and no explicit initializer will not have the
value zero.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma bss-name ("MyBSS")
#pragma bss-name ("MyBSS")
#pragma bss-name (push, "MyBSS")
#pragma bss-name ("MyBSS", "zp")
</verb></tscreen>
@ -1120,21 +1137,33 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma code-name ([push,] &lt;name&gt;)</tt><label id="pragma-code-name"><p>
<sect1><tt>#pragma code-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-code-name"><p>
This pragma changes the name used for the CODE segment (the CODE segment
is used to store executable code). The argument is a string enclosed in
double quotes.
This pragma changes the name used for the CODE segment (the CODE segment is
used to store executable code). The <tt/name/ argument is a string enclosed
in quotation marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
The <tt/#pragma/ understands the push and pop parameters as explained above.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma code-name ("MyCODE")
#pragma code-name ("MyCODE")
#pragma code-name (push, "MyCODE")
#pragma code-name (push, "MyCODE", "far")
</verb></tscreen>
@ -1148,21 +1177,33 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma data-name ([push,] &lt;name&gt;)</tt><label id="pragma-data-name"><p>
<sect1><tt>#pragma data-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-data-name"><p>
This pragma changes the name used for the DATA segment (the DATA segment
is used to store initialized data). The argument is a string enclosed in
double quotes.
This pragma changes the name used for the DATA segment (the DATA segment is
used to store initialized data). The <tt/name/ argument is a string enclosed
in quotation marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
The <tt/#pragma/ understands the push and pop parameters as explained above.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma data-name ("MyDATA")
#pragma data-name ("MyDATA")
#pragma data-name (push, "MyDATA")
#pragma data-name ("MyDATA", "zeropage")
</verb></tscreen>
@ -1224,21 +1265,32 @@ parameter with the <tt/#pragma/.
The <tt/#pragma/ understands the push and pop parameters as explained above.
<sect1><tt>#pragma rodata-name ([push,] &lt;name&gt;)</tt><label id="pragma-rodata-name"><p>
<sect1><tt>#pragma rodata-name ([push, ]&lt;name>[ ,&lt;addrsize>])</tt><label id="pragma-rodata-name"><p>
This pragma changes the name used for the RODATA segment (the RODATA
segment is used to store readonly data). The argument is a string
enclosed in double quotes.
This pragma changes the name used for the RODATA segment (the RODATA segment
is used to store read-only data). The <tt/name/ argument is a string enclosed
in quotation marks.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
<tt/addrsize/ is an optional string that gives a hint about where the
<tt/name/ segment will be put in the CPU's address space. It describes the
width of address numbers that point into that segment. Only words that
are known to ca65 are allowed:
<enum>
<item>"zp", "zeropage", "direct"
<item>"abs", "absolute", "near", "default"
<item>"far"
<item>"long", "dword"
</enum>
The <tt/#pragma/ understands the push and pop parameters as explained above.
Note: The default linker configuration file maps only the standard segments.
If you use other segments, you must create a new linker configuration file.
Example:
The <tt/#pragma/ understands the push and pop parameters, as explained above.
Examples:
<tscreen><verb>
#pragma rodata-name ("MyRODATA")
#pragma rodata-name ("MyRODATA")
#pragma rodata-name (push, "MyRODATA")
</verb></tscreen>

80
include/_atari5200os.h Normal file
View File

@ -0,0 +1,80 @@
/*****************************************************************************/
/* */
/* _atari5200os.h */
/* */
/* Internal include file, do not use directly */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef __ATARI5200OS_H
#define __ATARI5200OS_H
struct __os {
/*Page zero*/
unsigned char pokmsk; // = $00 System mask for POKEY IRQ enable
unsigned char rtclok[2]; // = $01,$02 Real time clock
unsigned char critic; // = $03 Critical section flag
unsigned char atract; // = $04 Attract mode counter
union {
struct {
unsigned char sdlstl; // = $05 Save display list LO
unsigned char sdlsth; // = $06 Save display list HI
};
void* sdlst; // = $05,$06 Display list shadow
};
unsigned char sdmctl; // = $07 DMACTL shadow
unsigned char pcolr0; // = $08 PM color 0
unsigned char pcolr1; // = $09 PM color 1
unsigned char pcolr2; // = $0A PM color 2
unsigned char pcolr3; // = $0B PM color 3
unsigned char color0; // = $0C PF color 0
unsigned char color1; // = $0D PF color 1
unsigned char color2; // = $0E PF color 2
unsigned char color3; // = $0F PF color 3
unsigned char color4; // = $10 PF color 4
unsigned char _free_1[0xEF]; // = $11-$FF User space
/*Stack*/
unsigned char stack[0x100]; // = $100-$1FF Stack
/*Page 2 OS variables*/
void (*vinter)(void); // = $200 Immediate IRQ vector
void (*vvblki)(void); // = $202 Immediate VBI vector
void (*vvblkd)(void); // = $204 Deferred VBI vector
void (*vdslst)(void); // = $206 DLI vector
void (*vkeybd)(void); // = $208 Keyboard IRQ vector
void (*vkeypd)(void); // = $20A Keyboard continuation vector
void (*vbrkky)(void); // = $20C Break key interrupt vector
void (*vbreak)(void); // = $20E BRK instruction interrupt vector
void (*vserin)(void); // = $210 Serial input ready vector
void (*vseror)(void); // = $212 Serial output data needed vector
void (*vseroc)(void); // = $214 Serial output completed vector
void (*vtimr1)(void); // = $216 POKEY timer 1 IRQ vector
void (*vtimr2)(void); // = $218 POKEY timer 2 IRQ vector
void (*vtimr4)(void); // = $21A POKEY timer 4 IRQ vector
};
#endif

View File

@ -65,6 +65,10 @@ extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */
#define AT_NTSC 0
#define AT_PAL 1
/* Define variables used by the OS*/
#include <_atari5200os.h>
#define OS (*(struct __os*)0x0000)
/* define hardware */
#include <_gtia.h>
#define GTIA_READ (*(struct __gtia_read*)0xC000)

View File

@ -19,11 +19,14 @@
.segment "ONCE"
initprompt:
; Set prompt <> ']' to let DOS 3.3 know that we're
; not in Applesoft immediate mode and thus keep it
; from scanning our device I/O for DOS commands.
; Set prompt <> ']' and currently executed Applesoft
; line number hibyte <> $FF to let DOS 3.3 (at $A65E)
; know that we're not in Applesoft immediate mode and
; thus keep it from scanning our device I/O for DOS
; commands.
lda #$80 ; Same value used at $D52C
sta PROMPT
sta CURLIN+1 ; Any value <> $FF will do
rts
.code

View File

@ -20,18 +20,19 @@
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; save count with each byte incremented separately
jsr popptr1 ; get buf
jsr popax ; get fd and discard
L1: inc ptr2
L1: dec ptr2
bnz L2
inc ptr2+1
dec ptr2+1
bze L9 ; no more room in buf
; If there are no more characters in BASIC's input buffer, then get a line from

View File

@ -17,17 +17,17 @@
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; save count with each byte incremented separately
jsr popptr1 ; get buf
jsr popax ; get fd and discard
L1: inc ptr2
L1: dec ptr2
bne L2
inc ptr2+1
dec ptr2+1
beq L9
L2: ldy #0
lda (ptr1),y

View File

@ -45,11 +45,11 @@
_cbm_read:
eor #$FF
sta ptr1
txa
eor #$FF
sta ptr1+1 ; Save -size-1
inx
stx ptr1+1
tax
inx
stx ptr1 ; Save size with both bytes incremented separately.
jsr popax
sta ptr2
@ -92,9 +92,9 @@ _cbm_read:
bne @L3
inc ptr3+1 ; ++bytesread;
@L3: inc ptr1
@L3: dec ptr1
bne @L1
inc ptr1+1
dec ptr1+1
bne @L1
@L4: jsr CLRCH

View File

@ -39,11 +39,11 @@
_cbm_write:
sta ptr3
stx ptr3+1 ; Save size
eor #$FF
sta ptr1
txa
eor #$FF
sta ptr1+1 ; Save -size-1
inx
stx ptr1+1
tax
inx
stx ptr1 ; Save size with both bytes incremented separately
jsr popax
sta ptr2
@ -69,9 +69,9 @@ _cbm_write:
@L2: jsr BSOUT ; cbm_k_bsout (A);
@L3: inc ptr1 ; --size;
@L3: dec ptr1 ; --size;
bne @L1
inc ptr1+1
dec ptr1+1
bne @L1
jsr CLRCH

View File

@ -106,9 +106,9 @@
; Decrement the count
@L3: inc ptr2
@L3: dec ptr2
bne @L0
inc ptr2+1
dec ptr2+1
bne @L0
beq done ; Branch always

View File

@ -21,11 +21,11 @@
.proc rwcommon
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; Remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; Save count with each byte incremented separately
jsr popptr1 ; Get buf to ptr1, Y=0 by call

View File

@ -83,9 +83,9 @@
; Decrement count
@L2: inc ptr2
@L2: dec ptr2
bne @L0
inc ptr2+1
dec ptr2+1
bne @L0
; Wrote all chars or disk full. Close the output channel

View File

@ -17,22 +17,22 @@
.proc _getcwd
; Remember -size-1 because this simplifies the following loop
; Remember size with each byte incremented because this simplifies the following loop
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1
inx
stx ptr2+1
tax
inx
stx ptr2 ; Save size with each byte incremented separately
jsr popptr1 ; Get buf to ptr1
; Copy __cwd to the given buffer checking the length
; ldy #$00 is guaranteed by popptr1
loop: inc ptr2
loop: dec ptr2
bne @L1
inc ptr2+1
dec ptr2+1
beq overflow
; Copy one character, end the loop if the zero terminator is reached. We

View File

@ -10,14 +10,14 @@
_memcmp:
; Calculate (-count-1) and store it into ptr3. This is some overhead here but
; saves time in the compare loop
; Calculate a special count, and store it into ptr3. That is some overhead here,
; but saves time in the compare loop
eor #$FF
sta ptr3
txa
eor #$FF
sta ptr3+1
inx
stx ptr3+1
tax
inx
stx ptr3 ; Save count with each byte incremented separately
; Get the pointer parameters
@ -29,12 +29,12 @@ _memcmp:
; Loop initialization
;ldy #$00 ; Initialize pointer (Y=0 guaranteed by popptr1)
ldx ptr3 ; Load low counter byte into X
ldx ptr3 ; Load inner counter byte into .X
; Head of compare loop: Test for the end condition
Loop: inx ; Bump low byte of (-count-1)
beq BumpHiCnt ; Jump on overflow
Loop: dex
beq BumpHiCnt ; Jump on end of inner count
; Do the compare
@ -50,10 +50,10 @@ Comp: lda (ptr1),y
inc ptr2+1
bne Loop ; Branch always (pointer wrap is illegal)
; Entry on low counter byte overflow
; Entry on inner loop end
BumpHiCnt:
inc ptr3+1 ; Bump high byte of (-count-1)
dec ptr3+1
bne Comp ; Jump if not done
jmp return0 ; Count is zero, areas are identical
@ -67,4 +67,3 @@ NotEqual:
Greater:
ldx #$01 ; Make result positive
rts

View File

@ -5,17 +5,17 @@
; char* strncat (char* dest, const char* src, size_t n);
;
.export _strncat
.import popax, popptr1
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
.macpack cpu
.export _strncat
.import popax, popptr1
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
.macpack cpu
_strncat:
eor #$FF ; one's complement to count upwards
sta tmp1
txa
eor #$FF
sta tmp2
inx
stx tmp2
tax
inx
stx tmp1 ; save count with each byte incremented separately
jsr popptr1 ; get src
@ -49,9 +49,9 @@ L2: sty ptr2
L3: ldy #0
ldx tmp1 ; low counter byte
L4: inx
L4: dex
bne L5
inc tmp2
dec tmp2
beq L6 ; jump if done
L5: lda (ptr1),y
sta (ptr2),y

View File

@ -10,11 +10,11 @@
.proc _strncpy
eor #$FF
sta tmp1
txa
eor #$FF
sta tmp2 ; Store -size - 1
inx
stx tmp2
tax
inx
stx tmp1 ; save count with each byte incremented separately
jsr popptr1 ; get src
jsr popax ; get dest
@ -24,11 +24,11 @@
; Copy src -> dest up to size bytes
ldx tmp1 ; Load low byte of ones complement of size
ldx tmp1
ldy #$00
L1: inx
L1: dex
bne L2
inc tmp2
dec tmp2
beq L9
L2: lda (ptr1),y ; Copy one character
@ -42,8 +42,8 @@ L2: lda (ptr1),y ; Copy one character
; Fill the remaining bytes.
L3: inx ; Counter low byte
beq L6 ; Branch on overflow
L3: dex ; Counter low byte
beq L6
L4: sta (ptr2),y ; Clear one byte
L5: iny ; Bump pointer
bne L3
@ -52,7 +52,7 @@ L5: iny ; Bump pointer
; Bump the counter high byte
L6: inc tmp2
L6: dec tmp2
bne L4
; Done, return dest

View File

@ -15,17 +15,11 @@
_strnicmp:
_strncasecmp:
; Convert the given counter value in a/x from a downward counter into an
; upward counter, so we can increment the counter in the loop below instead
; of decrementing it. This adds some overhead now, but is cheaper than
; executing a more complex test in each iteration of the loop. We do also
; correct the value by one, so we can do the test on top of the loop.
eor #$FF
sta ptr3
txa
eor #$FF
sta ptr3+1
inx
stx ptr3+1
tax
inx
stx ptr3 ; save count with each byte incremented separately
; Get the remaining arguments
@ -40,8 +34,8 @@ _strncasecmp:
; Start of compare loop. Check the counter.
Loop: inc ptr3
beq IncHi ; increment high byte
Loop: dec ptr3 ; decrement high byte
beq IncHi
; Compare a byte from the strings
@ -79,7 +73,7 @@ L2: ldx tmp1
; Increment hi byte
IncHi: inc ptr3+1
IncHi: dec ptr3+1
bne Comp ; jump if counter not zero
; Exit code if strings are equal. a/x not set

View File

@ -47,12 +47,12 @@ outdesc: ; Static outdesc structure
out: jsr popax ; count
sta ptr2
eor #$FF
sta outdesc+6
txa
sta ptr2+1
eor #$FF
sta outdesc+7
stx ptr2+1
inx
stx outdesc+7
tax
inx
stx outdesc+6
jsr popptr1 ; buf
@ -74,7 +74,7 @@ out: jsr popax ; count
; Loop outputting characters
@L1: inc outdesc+6
@L1: dec outdesc+6
beq @L4
@L2: ldy tmp1
lda (ptr1),y
@ -85,7 +85,7 @@ out: jsr popax ; count
jsr _cputc
jmp @L1
@L4: inc outdesc+7
@L4: dec outdesc+7
bne @L2
rts

View File

@ -94,11 +94,12 @@ _read:
; popax - fd, must be == to the above one
; return -1+__oserror or number of bytes read
eor #$ff
sta ptr1
txa
eor #$ff
sta ptr1+1 ; -(# of bytes to read)-1
inx
stx ptr1+1
tax
inx
stx ptr1 ; save count with each byte incremented separately
jsr popax
sta ptr2
stx ptr2+1 ; buffer ptr
@ -152,9 +153,9 @@ _read:
beq @done ; yes, we're done
jmp __mappederrno ; no, we're screwed
@L3: inc ptr1 ; decrement the count
@L3: dec ptr1 ; decrement the count
bne @L0
inc ptr1+1
dec ptr1+1
bne @L0
@done:

View File

@ -50,16 +50,15 @@ LINEDIST = $20 ; Offset in video RAM between two lines
ldx #>load_addr
sta load
stx load+1
lda #<load_size
eor #$FF
sta count ; store (-size - 1)
lda #>load_size
eor #$FF
sta count+1
L1: inc count ; pre-count one's-complement upwards
ldx #(<load_size) + 1
stx count
ldx #(>load_size) + 1
stx count+1 ; save size with each byte incremented separately
L1: dec count
bnz L2
inc count+1
dec count+1
bze L3
L2: jsr GETCHAR ; (doesn't change .Y)
sta (load),y

View File

@ -13,11 +13,11 @@
sta ptr3
stx ptr3+1 ; save count as result
eor #$FF
sta ptr2
txa
eor #$FF
sta ptr2+1 ; remember -count-1
inx
stx ptr2+1
tax
inx
stx ptr2 ; save count with each byte incremented separately
jsr popptr1 ; get buf
jsr popax ; get fd and discard
@ -51,9 +51,9 @@ next:
rts
L1: inc ptr2
L1: dec ptr2
bne L2
inc ptr2+1
dec ptr2+1
beq L9
L2: ldy #0
lda (ptr1),y

View File

@ -1433,17 +1433,20 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs)
/* Note that this logic is largely duplicated by ArithmeticConvert. */
/* Before we apply the integral promotions, we check if both types are unsigned char.
** If so, we return unsigned int, rather than int, which would be returned by the standard
** rules. This is only a performance optimization and does not affect correctness, as
** the flags are only used for code generation, and not to determine types of other
** expressions containing this one. All unsigned char bit-patterns are valid as both int
** and unsigned int and represent the same value, so either signed or unsigned int operations
** can be used. This special case part is not duplicated by ArithmeticConvert.
/* Before we apply the integral promotions, we check if both types are the same character type.
** If so, we return that type, rather than int, which would be returned by the standard
** rules. This is only a performance optimization allowing the use of unsigned and/or char
** operations; it does not affect correctness, as the flags are only used for code generation,
** and not to determine types of other expressions containing this one. For codgen, CF_CHAR
** means the operands are char and the result is int (unless CF_FORCECHAR is also set, in
** which case the result is char). This special case part is not duplicated by
** ArithmeticConvert.
*/
if ((lhs & CF_TYPEMASK) == CF_CHAR && (lhs & CF_UNSIGNED) &&
(rhs & CF_TYPEMASK) == CF_CHAR && (rhs & CF_UNSIGNED)) {
return const_flag | CF_UNSIGNED | CF_INT;
if ((lhs & CF_TYPEMASK) == CF_CHAR && (rhs & CF_TYPEMASK) == CF_CHAR &&
(lhs & CF_UNSIGNED) == (rhs & CF_UNSIGNED)) {
/* Signedness flags are the same, so just use one of them. */
const unsigned unsigned_flag = lhs & CF_UNSIGNED;
return const_flag | unsigned_flag | CF_CHAR;
}
/* Apply integral promotions for types char/short. */
@ -3111,9 +3114,26 @@ void g_asr (unsigned flags, unsigned long val)
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if (flags & CF_FORCECHAR) {
if ((flags & CF_UNSIGNED) != 0 && val < 8) {
while (val--) {
AddCodeLine ("lsr a");
val &= 7;
if ((flags & CF_UNSIGNED) != 0) {
/* Instead of `val` right shifts, we can also do `9 - val` left rotates
** and a mask. This saves 3 bytes and 8 cycles for `val == 7` and
** 1 byte and 4 cycles for `val == 6`.
*/
if (val < 6) {
while (val--) {
AddCodeLine ("lsr a"); /* 1 byte, 2 cycles */
}
} else {
unsigned i;
/* The first ROL shifts in garbage and sets carry to the high bit.
** The garbage is cleaned up by the mask.
*/
for (i = val; i < 9; ++i) {
AddCodeLine ("rol a"); /* 1 byte, 2 cycles */
}
/* 2 bytes, 2 cycles */
AddCodeLine ("and #$%02X", 0xFF >> val);
}
return;
} else if (val <= 2) {
@ -3267,9 +3287,21 @@ void g_asl (unsigned flags, unsigned long val)
if (flags & CF_CONST) {
switch (flags & CF_TYPEMASK) {
case CF_CHAR:
if ((flags & CF_FORCECHAR) != 0 && val <= 6) {
while (val--) {
AddCodeLine ("asl a");
if ((flags & CF_FORCECHAR) != 0) {
val &= 7;
/* Large shifts are faster and smaller with ROR. See g_asr for detailed
** byte and cycle counts.
*/
if (val < 6) {
while (val--) {
AddCodeLine ("asl a");
}
} else {
unsigned i;
for (i = val; i < 9; ++i) {
AddCodeLine ("ror a");
}
AddCodeLine ("and #$%02X", (~0U << val) & 0xFF);
}
return;
}

View File

@ -287,7 +287,7 @@ static unsigned Opt_tosshift (StackOpData* D, const char* Name)
/* ldx */
X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI);
InsertEntry (D, X, D->IP++);
/* Lhs load entries can be removed if not used later */
D->Lhs.X.Flags |= LI_REMOVE;
D->Lhs.A.Flags |= LI_REMOVE;
@ -1100,7 +1100,7 @@ static unsigned Opt_tosxorax (StackOpData* D)
static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
/* Optimize the tos compare sequence with a bool transformer */
/* Optimize the TOS compare sequence with a bool transformer */
{
CodeEntry* X;
cmp_t Cond;
@ -1119,9 +1119,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
D->Rhs.A.Flags |= LI_REMOVE;
} else if ((D->Lhs.A.Flags & LI_DIRECT) != 0) {
/* If the lhs is direct (but not stack relative), encode compares with lhs
** effectively reverting the order (which doesn't matter for ==).
/* If the lhs is direct (but not stack relative), encode compares with lhs,
** effectively reversing the order (which doesn't matter for == and !=).
*/
Cond = FindBoolCmpCond (BoolTransformer);
Cond = GetRevertedCond (Cond);
@ -1138,7 +1137,6 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
D->Lhs.A.Flags |= LI_REMOVE;
} else {
/* We'll do reverse-compare */
Cond = FindBoolCmpCond (BoolTransformer);
Cond = GetRevertedCond (Cond);
@ -1162,7 +1160,7 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI);
InsertEntry (D, X, D->IP++);
/* Remove the push and the call to the tosgeax function */
/* Remove the push and the call to the TOS function */
RemoveRemainders (D);
/* We changed the sequence */
@ -1179,22 +1177,6 @@ static unsigned Opt_a_toseq (StackOpData* D)
static unsigned Opt_a_tosge (StackOpData* D)
/* Optimize the tosgeax sequence */
{
return Opt_a_toscmpbool (D, "boolge");
}
static unsigned Opt_a_tosgt (StackOpData* D)
/* Optimize the tosgtax sequence */
{
return Opt_a_toscmpbool (D, "boolgt");
}
static unsigned Opt_a_tosicmp (StackOpData* D)
/* Replace tosicmp with CMP */
{
@ -1236,7 +1218,7 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
}
InsertEntry (D, X, D->IP++);
/* cmp src,y OR cmp (sp),y*/
/* cmp src,y OR cmp (sp),y */
if (D->Rhs.A.LoadEntry->OPC == OP65_JSR) {
/* opc (sp),y */
X = NewCodeEntry (OP65_CMP, AM65_ZP_INDY, "sp", 0, D->OpEntry->LI);
@ -1268,18 +1250,18 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
InsertEntry (D, X, D->IP-3);
} else {
/* Just clear A,Z,N and set C */
/* Just clear A,Z,N; and set C */
Arg = MakeHexArg (0);
if ((RI = GetLastChangedRegInfo (D, &D->Lhs.A)) != 0 &&
RegValIsKnown (RI->Out.RegA) &&
(RI->Out.RegA & 0xFF) == 0) {
Arg = MakeHexArg (0);
X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI);
X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex + 1);
} else {
Arg = MakeHexArg (0);
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI);
X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex + 1);
X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI);
X = NewCodeEntry (OP65_CMP, AM65_IMM, Arg, 0, D->OpEntry->LI);
InsertEntry (D, X, D->OpIndex + 2);
}
}
@ -1292,24 +1274,8 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
static unsigned Opt_a_tosle (StackOpData* D)
/* Optimize the tosleax sequence */
{
return Opt_a_toscmpbool (D, "boolle");
}
static unsigned Opt_a_toslt (StackOpData* D)
/* Optimize the tosltax sequence */
{
return Opt_a_toscmpbool (D, "boollt");
}
static unsigned Opt_a_tosne (StackOpData* D)
/* Optimize the toseqax sequence */
/* Optimize the tosneax sequence */
{
return Opt_a_toscmpbool (D, "boolne");
}
@ -1317,7 +1283,7 @@ static unsigned Opt_a_tosne (StackOpData* D)
static unsigned Opt_a_tosuge (StackOpData* D)
/* Optimize the tosugeax sequence */
/* Optimize the tosgeax and tosugeax sequences */
{
return Opt_a_toscmpbool (D, "booluge");
}
@ -1325,7 +1291,7 @@ static unsigned Opt_a_tosuge (StackOpData* D)
static unsigned Opt_a_tosugt (StackOpData* D)
/* Optimize the tosugtax sequence */
/* Optimize the tosgtax and tosugtax sequences */
{
return Opt_a_toscmpbool (D, "boolugt");
}
@ -1333,7 +1299,7 @@ static unsigned Opt_a_tosugt (StackOpData* D)
static unsigned Opt_a_tosule (StackOpData* D)
/* Optimize the tosuleax sequence */
/* Optimize the tosleax and tosuleax sequences */
{
return Opt_a_toscmpbool (D, "boolule");
}
@ -1341,7 +1307,7 @@ static unsigned Opt_a_tosule (StackOpData* D)
static unsigned Opt_a_tosult (StackOpData* D)
/* Optimize the tosultax sequence */
/* Optimize the tosltax and tosultax sequences */
{
return Opt_a_toscmpbool (D, "boolult");
}
@ -1354,6 +1320,8 @@ static unsigned Opt_a_tosult (StackOpData* D)
/* The first column of these two tables must be sorted in lexical order */
static const OptFuncDesc FuncTable[] = {
{ "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN },
{ "staspidx", Opt_staspidx, REG_NONE, OP_NONE },
@ -1379,11 +1347,11 @@ static const OptFuncDesc FuncTable[] = {
static const OptFuncDesc FuncRegATable[] = {
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
{ "tosgeax", Opt_a_tosge, REG_NONE, OP_NONE },
{ "tosgtax", Opt_a_tosgt, REG_NONE, OP_NONE },
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
{ "tosicmp", Opt_a_tosicmp, REG_NONE, OP_NONE },
{ "tosleax", Opt_a_tosle, REG_NONE, OP_NONE },
{ "tosltax", Opt_a_toslt, REG_NONE, OP_NONE },
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },

View File

@ -74,6 +74,7 @@ IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */
IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */
IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */
IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */
IntStack WarnReturnType = INTSTACK(1); /* - control reaches end of non-void function */
/* Map the name of a warning to the intstack that holds its state */
typedef struct WarnMapEntry WarnMapEntry;
@ -92,6 +93,7 @@ static WarnMapEntry WarnMap[] = {
{ &WarnUnusedLabel, "unused-label" },
{ &WarnUnusedParam, "unused-param" },
{ &WarnUnusedVar, "unused-var" },
{ &WarnReturnType, "return-type" },
};
Collection DiagnosticStrBufs;

View File

@ -71,6 +71,7 @@ extern IntStack WarnUnknownPragma; /* - unknown #pragmas */
extern IntStack WarnUnusedLabel; /* - unused labels */
extern IntStack WarnUnusedParam; /* - unused parameters */
extern IntStack WarnUnusedVar; /* - unused variables */
extern IntStack WarnReturnType; /* - control reaches end of non-void function */
/* Forward */
struct StrBuf;

View File

@ -23,10 +23,10 @@
#define SQP_KEEP_NONE 0x00
#define SQP_KEEP_TEST 0x01U
#define SQP_KEEP_EAX 0x02U
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */
#define SQP_KEEP_NONE 0x00
#define SQP_KEEP_TEST 0x01U
#define SQP_KEEP_EAX 0x02U
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */

View File

@ -654,8 +654,8 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
** environment returning int, output a warning if we didn't see a return
** statement.
*/
if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc) {
Warning ("Control reaches end of non-void function");
if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc && IS_Get (&WarnReturnType)) {
Warning ("Control reaches end of non-void function [-Wreturn-type]");
}
/* If this is the main function in a C99 environment returning an int, let

View File

@ -117,14 +117,6 @@ $(WORKDIR)/endless.$1.$2.prg: endless.c | $(WORKDIR)
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
$(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR)
# this one fails when optimization are enabled
$(WORKDIR)/bug1348.$1.$2.prg: bug1348.c | $(WORKDIR)
$(if $(QUIET),echo misc/bug1348.$1.$2.prg)
$(CC65) -Osr -t sim$2 -$1 -o $$(@:.prg=.s) $$< $(NULLERR)
$(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR)
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
$(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR)
# these need reference data that can't be generated by a host-compiled program,
# in a useful way
$(WORKDIR)/limits.$1.$2.prg: limits.c $(ISEQUAL) | $(WORKDIR)

File diff suppressed because it is too large Load Diff

View File

@ -7,24 +7,24 @@
struct ImageStruct
{
uint8_t _imageData;
#if !defined(NO_COLOR)
uint8_t _color;
#endif
uint8_t _imageData;
#if !defined(NO_COLOR)
uint8_t _color;
#endif
};
typedef struct ImageStruct Image;
struct CharacterStruct
{
// character coordinates
uint8_t _x;
uint8_t _y;
// character coordinates
uint8_t _x;
uint8_t _y;
// _status decides whether the character is active
uint8_t _status;
// _status decides whether the character is active
uint8_t _status;
Image* _imagePtr;
Image* _imagePtr;
};
typedef struct CharacterStruct Character;
@ -53,20 +53,20 @@ Character bombs[BOMBS_NUMBER];
uint16_t test1(void)
{
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
{
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*8;
}
return GHOST_MIN_SLOWDOWN;
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
{
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*8;
}
return GHOST_MIN_SLOWDOWN;
}
uint16_t test2(void)
{
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
{
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*16;
}
return GHOST_MIN_SLOWDOWN;
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
{
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*16;
}
return GHOST_MIN_SLOWDOWN;
}
uint16_t res = 0;

View File

@ -1,27 +1,26 @@
/* bug#1348, wrongly optimized integer promotion in comparison */
/* bug #1348, wrongly optimized integer promotion in comparison */
#include <stdio.h>
int notrandtab[] = {
static const int notrandtab[] = {
0xffff, 0x7fff, 0x3fff, 0x1fff,
0x0fff, 0x07ff, 0x03ff, 0x01ff,
0x00ff, 0x007f, 0x003f, 0x001f,
0x000f, 0x0007, 0x0003, 0x0001
};
unsigned char notrandcount = 0;
static unsigned char notrandcount = 0;
int notrand(void)
static int notrand(void)
{
return notrandtab[notrandcount & 0x0f];
}
unsigned char n1, n2;
unsigned char i, ii, s;
unsigned char err = 0;
static unsigned char n1, n2;
static unsigned char i, ii, s;
static unsigned char err = 0;
unsigned char cmptab[] = {
static const unsigned char cmptab[] = {
0xff, 0x7f, 0x3f, 0x1f,
0x0f, 0x07, 0x03, 0x01,
0x80, 0x40, 0x20, 0x10,
@ -40,13 +39,14 @@ int main(void)
if ((notrand() & 0xffu) > s) {
n2 = 1;
}
printf("%5d>%3d %d(%02x) %d(%02x) %s\n",
notrandtab[notrandcount & 0x0f], s,
printf("%5d > %3d %u(%02x) %u(%02x) %s\n",
notrandtab[i], s,
n1, (notrand() & 0xff),
n2, (notrand() & 0xffu),
n1 == n2 ? "=" : "!="
);
if (n1 != n2) err = 1;
n1 == n2 ? "=" : "!=");
if (n1 != n2) {
err = 1;
}
notrandcount++;
}
}

View File

@ -28,83 +28,83 @@ static uint32_t seed;
int ref_rand()
{
uint16_t output;
/* seed follows the LCG sequence * 0x01010101 + 0xB3B3B3B3 */
seed = seed * 0x01010101UL + 0xB3B3B3B3UL;
/* output uses the top two bytes (reversed) XOR with bottom two bytes */
{
uint16_t s0 = (seed >> 0) & 0xFF;
uint16_t s1 = (seed >> 8) & 0xFF;
uint16_t s2 = (seed >> 16) & 0xFF;
uint16_t s3 = (seed >> 24) & 0xFF;
uint16_t o0 = s3 ^ s1;
uint16_t o1 = s2 ^ s0;
output = o0 | (o1 << 8);
}
return (int)(output & 0x7FFF);
uint16_t output;
/* seed follows the LCG sequence * 0x01010101 + 0xB3B3B3B3 */
seed = seed * 0x01010101UL + 0xB3B3B3B3UL;
/* output uses the top two bytes (reversed) XOR with bottom two bytes */
{
uint16_t s0 = (seed >> 0) & 0xFF;
uint16_t s1 = (seed >> 8) & 0xFF;
uint16_t s2 = (seed >> 16) & 0xFF;
uint16_t s3 = (seed >> 24) & 0xFF;
uint16_t o0 = s3 ^ s1;
uint16_t o1 = s2 ^ s0;
output = o0 | (o1 << 8);
}
return (int)(output & 0x7FFF);
}
void ref_srand(int ax)
{
uint32_t s = (unsigned int)ax;
seed = s | (s << 16); /* low 16 bits is convenient filler for high 16 bits */
ref_rand(); /* one pre-call "shuffles" the first rand() result so it isn't too predictable */
uint32_t s = (unsigned int)ax;
seed = s | (s << 16); /* low 16 bits is convenient filler for high 16 bits */
ref_rand(); /* one pre-call "shuffles" the first rand() result so it isn't too predictable */
}
int main(void)
{
unsigned int i,j;
int a,b;
unsigned int i,j;
int a,b;
/* test that startup state is equivalent to srand(1) */
{
//srand(1); // implied
ref_srand(1);
for (j=0; j<SUBTESTS; ++j)
{
a = rand();
b = ref_rand();
if (a != b)
{
printf("failed startup seed at test %d. rand()=%d reference=%d\n",j,a,b);
return EXIT_FAILURE;
}
}
}
/* test that startup state is equivalent to srand(1) */
{
//srand(1); // implied
ref_srand(1);
for (j=0; j<SUBTESTS; ++j)
{
a = rand();
b = ref_rand();
if (a != b)
{
printf("failed startup seed at test %d. rand()=%d reference=%d\n",j,a,b);
return EXIT_FAILURE;
}
}
}
/* test every power of 2 seed */
for (i = 0; i < 16; ++i)
{
srand(1<<i);
ref_srand(1<<i);
for (j=0; j<SUBTESTS; ++j)
{
a = rand();
b = ref_rand();
if (a != b)
{
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
return EXIT_FAILURE;
}
}
}
/* test every power of 2 seed */
for (i = 0; i < 16; ++i)
{
srand(1<<i);
ref_srand(1<<i);
for (j=0; j<SUBTESTS; ++j)
{
a = rand();
b = ref_rand();
if (a != b)
{
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
return EXIT_FAILURE;
}
}
}
/* test a sampling of seeds*/
for (i = 0; i < 32768UL; i += TESTINC)
{
srand(i);
ref_srand(i);
for (j=0; j<SUBTESTS; ++j)
{
a = rand();
b = ref_rand();
if (a != b)
{
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
return EXIT_FAILURE;
}
}
}
/* test a sampling of seeds*/
for (i = 0; i < 32768UL; i += TESTINC)
{
srand(i);
ref_srand(i);
for (j=0; j<SUBTESTS; ++j)
{
a = rand();
b = ref_rand();
if (a != b)
{
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
return EXIT_FAILURE;
}
}
}
return EXIT_SUCCESS;
return EXIT_SUCCESS;
}