@@ -15,6 +15,7 @@ PROMPT := $33 ; Used by GETLN
|
|||||||
RNDL := $4E ; Random counter low
|
RNDL := $4E ; Random counter low
|
||||||
RNDH := $4F ; Random counter high
|
RNDH := $4F ; Random counter high
|
||||||
HIMEM := $73 ; Highest available memory address+1
|
HIMEM := $73 ; Highest available memory address+1
|
||||||
|
CURLIN := $75 ; Current line number being executed
|
||||||
|
|
||||||
;-----------------------------------------------------------------------------
|
;-----------------------------------------------------------------------------
|
||||||
; Vectors
|
; Vectors
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
; Zero page, Commodore stuff
|
; Zero page, Commodore stuff
|
||||||
|
|
||||||
TXTPTR := $3D ; Pointer into BASIC source code
|
TXTPTR := $3D ; Pointer into BASIC source code
|
||||||
|
STATUS := $90 ; Kernal I/O completion status
|
||||||
TIME := $A0 ; 60HZ clock
|
TIME := $A0 ; 60HZ clock
|
||||||
FNAM_LEN := $B7 ; Length of filename
|
FNAM_LEN := $B7 ; Length of filename
|
||||||
SECADR := $B9 ; Secondary address
|
SECADR := $B9 ; Secondary address
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
VARTAB := $2D ; Pointer to start of BASIC variables
|
VARTAB := $2D ; Pointer to start of BASIC variables
|
||||||
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
|
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
|
||||||
TXTPTR := $7A ; Pointer into BASIC source code
|
TXTPTR := $7A ; Pointer into BASIC source code
|
||||||
|
STATUS := $90 ; Kernal I/O completion status
|
||||||
TIME := $A0 ; 60 HZ clock
|
TIME := $A0 ; 60 HZ clock
|
||||||
FNAM_LEN := $B7 ; Length of filename
|
FNAM_LEN := $B7 ; Length of filename
|
||||||
SECADR := $B9 ; Secondary address
|
SECADR := $B9 ; Secondary address
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ TMPPTR := $22 ; Temporary ptr used by BASIC
|
|||||||
VARTAB := $2D ; Pointer to start of BASIC variables
|
VARTAB := $2D ; Pointer to start of BASIC variables
|
||||||
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
|
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
|
||||||
TXTPTR := $3B ; Pointer into BASIC source code
|
TXTPTR := $3B ; Pointer into BASIC source code
|
||||||
|
STATUS := $90 ; Kernal I/O completion status
|
||||||
TIME := $A3 ; 60HZ clock
|
TIME := $A3 ; 60HZ clock
|
||||||
FNAM_LEN := $AB ; Length of filename
|
FNAM_LEN := $AB ; Length of filename
|
||||||
LFN := $AC ; Logical file number
|
LFN := $AC ; Logical file number
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
VARTAB := $2D ; Pointer to start of BASIC variables
|
VARTAB := $2D ; Pointer to start of BASIC variables
|
||||||
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
|
MEMSIZE := $37 ; Pointer to highest BASIC RAM location (+1)
|
||||||
TXTPTR := $7A ; Pointer into BASIC source code
|
TXTPTR := $7A ; Pointer into BASIC source code
|
||||||
|
STATUS := $90 ; Kernal I/O completion status
|
||||||
TIME := $A0 ; 60HZ clock
|
TIME := $A0 ; 60HZ clock
|
||||||
FNAM_LEN := $B7 ; Length of filename
|
FNAM_LEN := $B7 ; Length of filename
|
||||||
SECADR := $B9 ; Secondary address
|
SECADR := $B9 ; Secondary address
|
||||||
|
|||||||
@@ -73,6 +73,17 @@ Special locations:
|
|||||||
|
|
||||||
Programs containing Atari 5200 specific code may use the <tt/atari5200.h/ header file.
|
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>
|
<sect1>Atari 5200 specific functions<p>
|
||||||
|
|
||||||
|
|||||||
156
doc/cc65.sgml
156
doc/cc65.sgml
@@ -6,8 +6,9 @@
|
|||||||
<url url="mailto:gregdk@users.sf.net" name="Greg King">
|
<url url="mailto:gregdk@users.sf.net" name="Greg King">
|
||||||
|
|
||||||
<abstract>
|
<abstract>
|
||||||
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
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.
|
computers such as the Commodore and Atari machines, but it easily is
|
||||||
|
retargetable.
|
||||||
</abstract>
|
</abstract>
|
||||||
|
|
||||||
<!-- Table of contents -->
|
<!-- Table of contents -->
|
||||||
@@ -548,6 +549,8 @@ Here is a description of all the command line options:
|
|||||||
<tag><tt/remap-zero/</tag>
|
<tag><tt/remap-zero/</tag>
|
||||||
Warn about a <tt/<ref id="pragma-charmap" name="#pragma charmap()">/
|
Warn about a <tt/<ref id="pragma-charmap" name="#pragma charmap()">/
|
||||||
that changes a character's code number from/to 0x00.
|
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>
|
<tag><tt/struct-param/</tag>
|
||||||
Warn when passing structs by value.
|
Warn when passing structs by value.
|
||||||
<tag><tt/unknown-pragma/</tag>
|
<tag><tt/unknown-pragma/</tag>
|
||||||
@@ -706,12 +709,13 @@ This cc65 version has some extensions to the ISO C standard.
|
|||||||
places.
|
places.
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
<item> There are two pseudo variables named <tt/__AX__/ and <tt/__EAX__/.
|
<item> There are three pseudo variables named <tt/__A__/, <tt/__AX__/ and
|
||||||
Both refer to the primary register that is used by the compiler to
|
<tt/__EAX__/. They all refer to the primary register that is used
|
||||||
evaluate expressions or return function results. <tt/__AX__/ is of
|
by the compiler to evaluate expressions or return function results.
|
||||||
type <tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/
|
<tt/__A__/ is of type <tt/unsigned char/, <tt/__AX__/ is of type
|
||||||
respectively. The pseudo variables may be used as lvalue and rvalue as
|
<tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/
|
||||||
every other variable. They are most useful together with short
|
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
|
sequences of assembler code. For example, the macro
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
@@ -1045,26 +1049,39 @@ parameter with the <tt/#pragma/.
|
|||||||
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
||||||
|
|
||||||
|
|
||||||
<sect1><tt>#pragma bss-name ([push,] <name>)</tt><label id="pragma-bss-name"><p>
|
<sect1><tt>#pragma bss-name ([push, ]<name>[ ,<addrsize>])</tt><label id="pragma-bss-name"><p>
|
||||||
|
|
||||||
This pragma changes the name used for the BSS segment (the BSS segment
|
This pragma changes the name used for the BSS segment (the BSS segment is
|
||||||
is used to store variables with static storage duration and no explicit
|
used to store variables with static storage duration and no explicit
|
||||||
initializer). The argument is a string enclosed in double quotes.
|
initializers). The <tt/name/ argument is a string enclosed in quotation
|
||||||
|
marks.
|
||||||
|
|
||||||
Note: The default linker configuration file does only map the standard
|
<tt/addrsize/ is an optional string that gives a hint about where the
|
||||||
segments. If you use other segments, you have to create a new linker
|
<tt/name/ segment will be put in the CPU's address space. It describes the
|
||||||
configuration file.
|
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
|
Note: The default linker configuration file maps only the standard segments.
|
||||||
use another BSS segment, you have to do that yourself, otherwise
|
If you use other segments, you must create a new linker configuration file.
|
||||||
variables with static storage duration and no explicit initializer will
|
|
||||||
not have the value zero.
|
|
||||||
|
|
||||||
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>
|
<tscreen><verb>
|
||||||
#pragma bss-name ("MyBSS")
|
#pragma bss-name ("MyBSS")
|
||||||
|
#pragma bss-name (push, "MyBSS")
|
||||||
|
#pragma bss-name ("MyBSS", "zp")
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
@@ -1120,21 +1137,33 @@ parameter with the <tt/#pragma/.
|
|||||||
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
||||||
|
|
||||||
|
|
||||||
<sect1><tt>#pragma code-name ([push,] <name>)</tt><label id="pragma-code-name"><p>
|
<sect1><tt>#pragma code-name ([push, ]<name>[ ,<addrsize>])</tt><label id="pragma-code-name"><p>
|
||||||
|
|
||||||
This pragma changes the name used for the CODE segment (the CODE segment
|
This pragma changes the name used for the CODE segment (the CODE segment is
|
||||||
is used to store executable code). The argument is a string enclosed in
|
used to store executable code). The <tt/name/ argument is a string enclosed
|
||||||
double quotes.
|
in quotation marks.
|
||||||
|
|
||||||
Note: The default linker configuration file does only map the standard
|
<tt/addrsize/ is an optional string that gives a hint about where the
|
||||||
segments. If you use other segments, you have to create a new linker
|
<tt/name/ segment will be put in the CPU's address space. It describes the
|
||||||
configuration file.
|
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>
|
<tscreen><verb>
|
||||||
#pragma code-name ("MyCODE")
|
#pragma code-name ("MyCODE")
|
||||||
|
#pragma code-name (push, "MyCODE")
|
||||||
|
#pragma code-name (push, "MyCODE", "far")
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
@@ -1148,21 +1177,33 @@ parameter with the <tt/#pragma/.
|
|||||||
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
||||||
|
|
||||||
|
|
||||||
<sect1><tt>#pragma data-name ([push,] <name>)</tt><label id="pragma-data-name"><p>
|
<sect1><tt>#pragma data-name ([push, ]<name>[ ,<addrsize>])</tt><label id="pragma-data-name"><p>
|
||||||
|
|
||||||
This pragma changes the name used for the DATA segment (the DATA segment
|
This pragma changes the name used for the DATA segment (the DATA segment is
|
||||||
is used to store initialized data). The argument is a string enclosed in
|
used to store initialized data). The <tt/name/ argument is a string enclosed
|
||||||
double quotes.
|
in quotation marks.
|
||||||
|
|
||||||
Note: The default linker configuration file does only map the standard
|
<tt/addrsize/ is an optional string that gives a hint about where the
|
||||||
segments. If you use other segments, you have to create a new linker
|
<tt/name/ segment will be put in the CPU's address space. It describes the
|
||||||
configuration file.
|
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>
|
<tscreen><verb>
|
||||||
#pragma data-name ("MyDATA")
|
#pragma data-name ("MyDATA")
|
||||||
|
#pragma data-name (push, "MyDATA")
|
||||||
|
#pragma data-name ("MyDATA", "zeropage")
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
@@ -1224,21 +1265,32 @@ parameter with the <tt/#pragma/.
|
|||||||
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
The <tt/#pragma/ understands the push and pop parameters as explained above.
|
||||||
|
|
||||||
|
|
||||||
<sect1><tt>#pragma rodata-name ([push,] <name>)</tt><label id="pragma-rodata-name"><p>
|
<sect1><tt>#pragma rodata-name ([push, ]<name>[ ,<addrsize>])</tt><label id="pragma-rodata-name"><p>
|
||||||
|
|
||||||
This pragma changes the name used for the RODATA segment (the RODATA
|
This pragma changes the name used for the RODATA segment (the RODATA segment
|
||||||
segment is used to store readonly data). The argument is a string
|
is used to store read-only data). The <tt/name/ argument is a string enclosed
|
||||||
enclosed in double quotes.
|
in quotation marks.
|
||||||
|
|
||||||
Note: The default linker configuration file does only map the standard
|
<tt/addrsize/ is an optional string that gives a hint about where the
|
||||||
segments. If you use other segments, you have to create a new linker
|
<tt/name/ segment will be put in the CPU's address space. It describes the
|
||||||
configuration file.
|
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>
|
<tscreen><verb>
|
||||||
#pragma rodata-name ("MyRODATA")
|
#pragma rodata-name ("MyRODATA")
|
||||||
|
#pragma rodata-name (push, "MyRODATA")
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
80
include/_atari5200os.h
Normal file
80
include/_atari5200os.h
Normal 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
|
||||||
@@ -65,6 +65,10 @@ extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */
|
|||||||
#define AT_NTSC 0
|
#define AT_NTSC 0
|
||||||
#define AT_PAL 1
|
#define AT_PAL 1
|
||||||
|
|
||||||
|
/* Define variables used by the OS*/
|
||||||
|
#include <_atari5200os.h>
|
||||||
|
#define OS (*(struct __os*)0x0000)
|
||||||
|
|
||||||
/* define hardware */
|
/* define hardware */
|
||||||
#include <_gtia.h>
|
#include <_gtia.h>
|
||||||
#define GTIA_READ (*(struct __gtia_read*)0xC000)
|
#define GTIA_READ (*(struct __gtia_read*)0xC000)
|
||||||
|
|||||||
@@ -19,11 +19,14 @@
|
|||||||
.segment "ONCE"
|
.segment "ONCE"
|
||||||
|
|
||||||
initprompt:
|
initprompt:
|
||||||
; Set prompt <> ']' to let DOS 3.3 know that we're
|
; Set prompt <> ']' and currently executed Applesoft
|
||||||
; not in Applesoft immediate mode and thus keep it
|
; line number hibyte <> $FF to let DOS 3.3 (at $A65E)
|
||||||
; from scanning our device I/O for DOS commands.
|
; 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
|
lda #$80 ; Same value used at $D52C
|
||||||
sta PROMPT
|
sta PROMPT
|
||||||
|
sta CURLIN+1 ; Any value <> $FF will do
|
||||||
rts
|
rts
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|||||||
@@ -20,18 +20,19 @@
|
|||||||
|
|
||||||
sta ptr3
|
sta ptr3
|
||||||
stx ptr3+1 ; save count as result
|
stx ptr3+1 ; save count as result
|
||||||
eor #$FF
|
|
||||||
sta ptr2
|
inx
|
||||||
txa
|
stx ptr2+1
|
||||||
eor #$FF
|
tax
|
||||||
sta ptr2+1 ; Remember -count-1
|
inx
|
||||||
|
stx ptr2 ; save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; get buf
|
jsr popptr1 ; get buf
|
||||||
jsr popax ; get fd and discard
|
jsr popax ; get fd and discard
|
||||||
|
|
||||||
L1: inc ptr2
|
L1: dec ptr2
|
||||||
bnz L2
|
bnz L2
|
||||||
inc ptr2+1
|
dec ptr2+1
|
||||||
bze L9 ; no more room in buf
|
bze L9 ; no more room in buf
|
||||||
|
|
||||||
; If there are no more characters in BASIC's input buffer, then get a line from
|
; If there are no more characters in BASIC's input buffer, then get a line from
|
||||||
|
|||||||
@@ -17,17 +17,17 @@
|
|||||||
sta ptr3
|
sta ptr3
|
||||||
stx ptr3+1 ; save count as result
|
stx ptr3+1 ; save count as result
|
||||||
|
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2
|
stx ptr2+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2+1 ; Remember -count-1
|
stx ptr2 ; save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; get buf
|
jsr popptr1 ; get buf
|
||||||
jsr popax ; get fd and discard
|
jsr popax ; get fd and discard
|
||||||
L1: inc ptr2
|
L1: dec ptr2
|
||||||
bne L2
|
bne L2
|
||||||
inc ptr2+1
|
dec ptr2+1
|
||||||
beq L9
|
beq L9
|
||||||
L2: ldy #0
|
L2: ldy #0
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
|
|||||||
@@ -45,11 +45,11 @@
|
|||||||
|
|
||||||
|
|
||||||
_cbm_read:
|
_cbm_read:
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr1
|
stx ptr1+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr1+1 ; Save -size-1
|
stx ptr1 ; Save size with both bytes incremented separately.
|
||||||
|
|
||||||
jsr popax
|
jsr popax
|
||||||
sta ptr2
|
sta ptr2
|
||||||
@@ -92,9 +92,9 @@ _cbm_read:
|
|||||||
bne @L3
|
bne @L3
|
||||||
inc ptr3+1 ; ++bytesread;
|
inc ptr3+1 ; ++bytesread;
|
||||||
|
|
||||||
@L3: inc ptr1
|
@L3: dec ptr1
|
||||||
bne @L1
|
bne @L1
|
||||||
inc ptr1+1
|
dec ptr1+1
|
||||||
bne @L1
|
bne @L1
|
||||||
|
|
||||||
@L4: jsr CLRCH
|
@L4: jsr CLRCH
|
||||||
|
|||||||
@@ -39,11 +39,11 @@
|
|||||||
_cbm_write:
|
_cbm_write:
|
||||||
sta ptr3
|
sta ptr3
|
||||||
stx ptr3+1 ; Save size
|
stx ptr3+1 ; Save size
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr1
|
stx ptr1+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr1+1 ; Save -size-1
|
stx ptr1 ; Save size with both bytes incremented separately
|
||||||
|
|
||||||
jsr popax
|
jsr popax
|
||||||
sta ptr2
|
sta ptr2
|
||||||
@@ -69,9 +69,9 @@ _cbm_write:
|
|||||||
|
|
||||||
@L2: jsr BSOUT ; cbm_k_bsout (A);
|
@L2: jsr BSOUT ; cbm_k_bsout (A);
|
||||||
|
|
||||||
@L3: inc ptr1 ; --size;
|
@L3: dec ptr1 ; --size;
|
||||||
bne @L1
|
bne @L1
|
||||||
inc ptr1+1
|
dec ptr1+1
|
||||||
bne @L1
|
bne @L1
|
||||||
|
|
||||||
jsr CLRCH
|
jsr CLRCH
|
||||||
|
|||||||
@@ -106,9 +106,9 @@
|
|||||||
|
|
||||||
; Decrement the count
|
; Decrement the count
|
||||||
|
|
||||||
@L3: inc ptr2
|
@L3: dec ptr2
|
||||||
bne @L0
|
bne @L0
|
||||||
inc ptr2+1
|
dec ptr2+1
|
||||||
bne @L0
|
bne @L0
|
||||||
beq done ; Branch always
|
beq done ; Branch always
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
.proc rwcommon
|
.proc rwcommon
|
||||||
|
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2
|
stx ptr2+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2+1 ; Remember -count-1
|
stx ptr2 ; Save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; Get buf to ptr1, Y=0 by call
|
jsr popptr1 ; Get buf to ptr1, Y=0 by call
|
||||||
|
|
||||||
|
|||||||
@@ -83,9 +83,9 @@
|
|||||||
|
|
||||||
; Decrement count
|
; Decrement count
|
||||||
|
|
||||||
@L2: inc ptr2
|
@L2: dec ptr2
|
||||||
bne @L0
|
bne @L0
|
||||||
inc ptr2+1
|
dec ptr2+1
|
||||||
bne @L0
|
bne @L0
|
||||||
|
|
||||||
; Wrote all chars or disk full. Close the output channel
|
; Wrote all chars or disk full. Close the output channel
|
||||||
|
|||||||
@@ -17,22 +17,22 @@
|
|||||||
|
|
||||||
.proc _getcwd
|
.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
|
inx
|
||||||
sta ptr2
|
stx ptr2+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2+1
|
stx ptr2 ; Save size with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; Get buf to ptr1
|
jsr popptr1 ; Get buf to ptr1
|
||||||
|
|
||||||
; Copy __cwd to the given buffer checking the length
|
; Copy __cwd to the given buffer checking the length
|
||||||
|
|
||||||
; ldy #$00 is guaranteed by popptr1
|
; ldy #$00 is guaranteed by popptr1
|
||||||
loop: inc ptr2
|
loop: dec ptr2
|
||||||
bne @L1
|
bne @L1
|
||||||
inc ptr2+1
|
dec ptr2+1
|
||||||
beq overflow
|
beq overflow
|
||||||
|
|
||||||
; Copy one character, end the loop if the zero terminator is reached. We
|
; Copy one character, end the loop if the zero terminator is reached. We
|
||||||
|
|||||||
@@ -10,14 +10,14 @@
|
|||||||
|
|
||||||
_memcmp:
|
_memcmp:
|
||||||
|
|
||||||
; Calculate (-count-1) and store it into ptr3. This is some overhead here but
|
; Calculate a special count, and store it into ptr3. That is some overhead here,
|
||||||
; saves time in the compare loop
|
; but saves time in the compare loop
|
||||||
|
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr3
|
stx ptr3+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr3+1
|
stx ptr3 ; Save count with each byte incremented separately
|
||||||
|
|
||||||
; Get the pointer parameters
|
; Get the pointer parameters
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ _memcmp:
|
|||||||
; Loop initialization
|
; Loop initialization
|
||||||
|
|
||||||
;ldy #$00 ; Initialize pointer (Y=0 guaranteed by popptr1)
|
;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
|
; Head of compare loop: Test for the end condition
|
||||||
|
|
||||||
Loop: inx ; Bump low byte of (-count-1)
|
Loop: dex
|
||||||
beq BumpHiCnt ; Jump on overflow
|
beq BumpHiCnt ; Jump on end of inner count
|
||||||
|
|
||||||
; Do the compare
|
; Do the compare
|
||||||
|
|
||||||
@@ -50,10 +50,10 @@ Comp: lda (ptr1),y
|
|||||||
inc ptr2+1
|
inc ptr2+1
|
||||||
bne Loop ; Branch always (pointer wrap is illegal)
|
bne Loop ; Branch always (pointer wrap is illegal)
|
||||||
|
|
||||||
; Entry on low counter byte overflow
|
; Entry on inner loop end
|
||||||
|
|
||||||
BumpHiCnt:
|
BumpHiCnt:
|
||||||
inc ptr3+1 ; Bump high byte of (-count-1)
|
dec ptr3+1
|
||||||
bne Comp ; Jump if not done
|
bne Comp ; Jump if not done
|
||||||
jmp return0 ; Count is zero, areas are identical
|
jmp return0 ; Count is zero, areas are identical
|
||||||
|
|
||||||
@@ -67,4 +67,3 @@ NotEqual:
|
|||||||
Greater:
|
Greater:
|
||||||
ldx #$01 ; Make result positive
|
ldx #$01 ; Make result positive
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,17 @@
|
|||||||
; char* strncat (char* dest, const char* src, size_t n);
|
; char* strncat (char* dest, const char* src, size_t n);
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _strncat
|
.export _strncat
|
||||||
.import popax, popptr1
|
.import popax, popptr1
|
||||||
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
|
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
|
||||||
.macpack cpu
|
.macpack cpu
|
||||||
|
|
||||||
_strncat:
|
_strncat:
|
||||||
eor #$FF ; one's complement to count upwards
|
inx
|
||||||
sta tmp1
|
stx tmp2
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta tmp2
|
stx tmp1 ; save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; get src
|
jsr popptr1 ; get src
|
||||||
|
|
||||||
@@ -49,9 +49,9 @@ L2: sty ptr2
|
|||||||
L3: ldy #0
|
L3: ldy #0
|
||||||
ldx tmp1 ; low counter byte
|
ldx tmp1 ; low counter byte
|
||||||
|
|
||||||
L4: inx
|
L4: dex
|
||||||
bne L5
|
bne L5
|
||||||
inc tmp2
|
dec tmp2
|
||||||
beq L6 ; jump if done
|
beq L6 ; jump if done
|
||||||
L5: lda (ptr1),y
|
L5: lda (ptr1),y
|
||||||
sta (ptr2),y
|
sta (ptr2),y
|
||||||
|
|||||||
@@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
.proc _strncpy
|
.proc _strncpy
|
||||||
|
|
||||||
eor #$FF
|
inx
|
||||||
sta tmp1
|
stx tmp2
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta tmp2 ; Store -size - 1
|
stx tmp1 ; save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; get src
|
jsr popptr1 ; get src
|
||||||
jsr popax ; get dest
|
jsr popax ; get dest
|
||||||
@@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
; Copy src -> dest up to size bytes
|
; Copy src -> dest up to size bytes
|
||||||
|
|
||||||
ldx tmp1 ; Load low byte of ones complement of size
|
ldx tmp1
|
||||||
ldy #$00
|
ldy #$00
|
||||||
L1: inx
|
L1: dex
|
||||||
bne L2
|
bne L2
|
||||||
inc tmp2
|
dec tmp2
|
||||||
beq L9
|
beq L9
|
||||||
|
|
||||||
L2: lda (ptr1),y ; Copy one character
|
L2: lda (ptr1),y ; Copy one character
|
||||||
@@ -42,8 +42,8 @@ L2: lda (ptr1),y ; Copy one character
|
|||||||
|
|
||||||
; Fill the remaining bytes.
|
; Fill the remaining bytes.
|
||||||
|
|
||||||
L3: inx ; Counter low byte
|
L3: dex ; Counter low byte
|
||||||
beq L6 ; Branch on overflow
|
beq L6
|
||||||
L4: sta (ptr2),y ; Clear one byte
|
L4: sta (ptr2),y ; Clear one byte
|
||||||
L5: iny ; Bump pointer
|
L5: iny ; Bump pointer
|
||||||
bne L3
|
bne L3
|
||||||
@@ -52,7 +52,7 @@ L5: iny ; Bump pointer
|
|||||||
|
|
||||||
; Bump the counter high byte
|
; Bump the counter high byte
|
||||||
|
|
||||||
L6: inc tmp2
|
L6: dec tmp2
|
||||||
bne L4
|
bne L4
|
||||||
|
|
||||||
; Done, return dest
|
; Done, return dest
|
||||||
|
|||||||
@@ -15,17 +15,11 @@
|
|||||||
_strnicmp:
|
_strnicmp:
|
||||||
_strncasecmp:
|
_strncasecmp:
|
||||||
|
|
||||||
; Convert the given counter value in a/x from a downward counter into an
|
inx
|
||||||
; upward counter, so we can increment the counter in the loop below instead
|
stx ptr3+1
|
||||||
; of decrementing it. This adds some overhead now, but is cheaper than
|
tax
|
||||||
; executing a more complex test in each iteration of the loop. We do also
|
inx
|
||||||
; correct the value by one, so we can do the test on top of the loop.
|
stx ptr3 ; save count with each byte incremented separately
|
||||||
|
|
||||||
eor #$FF
|
|
||||||
sta ptr3
|
|
||||||
txa
|
|
||||||
eor #$FF
|
|
||||||
sta ptr3+1
|
|
||||||
|
|
||||||
; Get the remaining arguments
|
; Get the remaining arguments
|
||||||
|
|
||||||
@@ -40,8 +34,8 @@ _strncasecmp:
|
|||||||
|
|
||||||
; Start of compare loop. Check the counter.
|
; Start of compare loop. Check the counter.
|
||||||
|
|
||||||
Loop: inc ptr3
|
Loop: dec ptr3 ; decrement high byte
|
||||||
beq IncHi ; increment high byte
|
beq IncHi
|
||||||
|
|
||||||
; Compare a byte from the strings
|
; Compare a byte from the strings
|
||||||
|
|
||||||
@@ -79,7 +73,7 @@ L2: ldx tmp1
|
|||||||
|
|
||||||
; Increment hi byte
|
; Increment hi byte
|
||||||
|
|
||||||
IncHi: inc ptr3+1
|
IncHi: dec ptr3+1
|
||||||
bne Comp ; jump if counter not zero
|
bne Comp ; jump if counter not zero
|
||||||
|
|
||||||
; Exit code if strings are equal. a/x not set
|
; Exit code if strings are equal. a/x not set
|
||||||
|
|||||||
@@ -47,12 +47,12 @@ outdesc: ; Static outdesc structure
|
|||||||
|
|
||||||
out: jsr popax ; count
|
out: jsr popax ; count
|
||||||
sta ptr2
|
sta ptr2
|
||||||
eor #$FF
|
stx ptr2+1
|
||||||
sta outdesc+6
|
inx
|
||||||
txa
|
stx outdesc+7
|
||||||
sta ptr2+1
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta outdesc+7
|
stx outdesc+6
|
||||||
|
|
||||||
jsr popptr1 ; buf
|
jsr popptr1 ; buf
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ out: jsr popax ; count
|
|||||||
|
|
||||||
; Loop outputting characters
|
; Loop outputting characters
|
||||||
|
|
||||||
@L1: inc outdesc+6
|
@L1: dec outdesc+6
|
||||||
beq @L4
|
beq @L4
|
||||||
@L2: ldy tmp1
|
@L2: ldy tmp1
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
@@ -85,7 +85,7 @@ out: jsr popax ; count
|
|||||||
jsr _cputc
|
jsr _cputc
|
||||||
jmp @L1
|
jmp @L1
|
||||||
|
|
||||||
@L4: inc outdesc+7
|
@L4: dec outdesc+7
|
||||||
bne @L2
|
bne @L2
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|||||||
@@ -94,11 +94,12 @@ _read:
|
|||||||
; popax - fd, must be == to the above one
|
; popax - fd, must be == to the above one
|
||||||
; return -1+__oserror or number of bytes read
|
; return -1+__oserror or number of bytes read
|
||||||
|
|
||||||
eor #$ff
|
inx
|
||||||
sta ptr1
|
stx ptr1+1
|
||||||
txa
|
tax
|
||||||
eor #$ff
|
inx
|
||||||
sta ptr1+1 ; -(# of bytes to read)-1
|
stx ptr1 ; save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popax
|
jsr popax
|
||||||
sta ptr2
|
sta ptr2
|
||||||
stx ptr2+1 ; buffer ptr
|
stx ptr2+1 ; buffer ptr
|
||||||
@@ -152,9 +153,9 @@ _read:
|
|||||||
beq @done ; yes, we're done
|
beq @done ; yes, we're done
|
||||||
jmp __mappederrno ; no, we're screwed
|
jmp __mappederrno ; no, we're screwed
|
||||||
|
|
||||||
@L3: inc ptr1 ; decrement the count
|
@L3: dec ptr1 ; decrement the count
|
||||||
bne @L0
|
bne @L0
|
||||||
inc ptr1+1
|
dec ptr1+1
|
||||||
bne @L0
|
bne @L0
|
||||||
|
|
||||||
@done:
|
@done:
|
||||||
|
|||||||
@@ -50,16 +50,15 @@ LINEDIST = $20 ; Offset in video RAM between two lines
|
|||||||
ldx #>load_addr
|
ldx #>load_addr
|
||||||
sta load
|
sta load
|
||||||
stx load+1
|
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
|
bnz L2
|
||||||
inc count+1
|
dec count+1
|
||||||
bze L3
|
bze L3
|
||||||
L2: jsr GETCHAR ; (doesn't change .Y)
|
L2: jsr GETCHAR ; (doesn't change .Y)
|
||||||
sta (load),y
|
sta (load),y
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
sta ptr3
|
sta ptr3
|
||||||
stx ptr3+1 ; save count as result
|
stx ptr3+1 ; save count as result
|
||||||
|
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2
|
stx ptr2+1
|
||||||
txa
|
tax
|
||||||
eor #$FF
|
inx
|
||||||
sta ptr2+1 ; remember -count-1
|
stx ptr2 ; save count with each byte incremented separately
|
||||||
|
|
||||||
jsr popptr1 ; get buf
|
jsr popptr1 ; get buf
|
||||||
jsr popax ; get fd and discard
|
jsr popax ; get fd and discard
|
||||||
@@ -51,9 +51,9 @@ next:
|
|||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
L1: inc ptr2
|
L1: dec ptr2
|
||||||
bne L2
|
bne L2
|
||||||
inc ptr2+1
|
dec ptr2+1
|
||||||
beq L9
|
beq L9
|
||||||
L2: ldy #0
|
L2: ldy #0
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
|
|||||||
@@ -1433,17 +1433,20 @@ unsigned g_typeadjust (unsigned lhs, unsigned rhs)
|
|||||||
|
|
||||||
/* Note that this logic is largely duplicated by ArithmeticConvert. */
|
/* Note that this logic is largely duplicated by ArithmeticConvert. */
|
||||||
|
|
||||||
/* Before we apply the integral promotions, we check if both types are unsigned char.
|
/* Before we apply the integral promotions, we check if both types are the same character type.
|
||||||
** If so, we return unsigned int, rather than int, which would be returned by the standard
|
** If so, we return that type, rather than int, which would be returned by the standard
|
||||||
** rules. This is only a performance optimization and does not affect correctness, as
|
** rules. This is only a performance optimization allowing the use of unsigned and/or char
|
||||||
** the flags are only used for code generation, and not to determine types of other
|
** operations; it does not affect correctness, as the flags are only used for code generation,
|
||||||
** expressions containing this one. All unsigned char bit-patterns are valid as both int
|
** and not to determine types of other expressions containing this one. For codgen, CF_CHAR
|
||||||
** and unsigned int and represent the same value, so either signed or unsigned int operations
|
** means the operands are char and the result is int (unless CF_FORCECHAR is also set, in
|
||||||
** can be used. This special case part is not duplicated by ArithmeticConvert.
|
** which case the result is char). This special case part is not duplicated by
|
||||||
|
** ArithmeticConvert.
|
||||||
*/
|
*/
|
||||||
if ((lhs & CF_TYPEMASK) == CF_CHAR && (lhs & CF_UNSIGNED) &&
|
if ((lhs & CF_TYPEMASK) == CF_CHAR && (rhs & CF_TYPEMASK) == CF_CHAR &&
|
||||||
(rhs & CF_TYPEMASK) == CF_CHAR && (rhs & CF_UNSIGNED)) {
|
(lhs & CF_UNSIGNED) == (rhs & CF_UNSIGNED)) {
|
||||||
return const_flag | CF_UNSIGNED | CF_INT;
|
/* 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. */
|
/* Apply integral promotions for types char/short. */
|
||||||
@@ -3111,9 +3114,26 @@ void g_asr (unsigned flags, unsigned long val)
|
|||||||
switch (flags & CF_TYPEMASK) {
|
switch (flags & CF_TYPEMASK) {
|
||||||
case CF_CHAR:
|
case CF_CHAR:
|
||||||
if (flags & CF_FORCECHAR) {
|
if (flags & CF_FORCECHAR) {
|
||||||
if ((flags & CF_UNSIGNED) != 0 && val < 8) {
|
val &= 7;
|
||||||
while (val--) {
|
if ((flags & CF_UNSIGNED) != 0) {
|
||||||
AddCodeLine ("lsr a");
|
/* 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;
|
return;
|
||||||
} else if (val <= 2) {
|
} else if (val <= 2) {
|
||||||
@@ -3267,9 +3287,21 @@ void g_asl (unsigned flags, unsigned long val)
|
|||||||
if (flags & CF_CONST) {
|
if (flags & CF_CONST) {
|
||||||
switch (flags & CF_TYPEMASK) {
|
switch (flags & CF_TYPEMASK) {
|
||||||
case CF_CHAR:
|
case CF_CHAR:
|
||||||
if ((flags & CF_FORCECHAR) != 0 && val <= 6) {
|
if ((flags & CF_FORCECHAR) != 0) {
|
||||||
while (val--) {
|
val &= 7;
|
||||||
AddCodeLine ("asl a");
|
/* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1100,7 +1100,7 @@ static unsigned Opt_tosxorax (StackOpData* D)
|
|||||||
|
|
||||||
|
|
||||||
static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
|
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;
|
CodeEntry* X;
|
||||||
cmp_t Cond;
|
cmp_t Cond;
|
||||||
@@ -1119,9 +1119,8 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
|
|||||||
D->Rhs.A.Flags |= LI_REMOVE;
|
D->Rhs.A.Flags |= LI_REMOVE;
|
||||||
|
|
||||||
} else if ((D->Lhs.A.Flags & LI_DIRECT) != 0) {
|
} else if ((D->Lhs.A.Flags & LI_DIRECT) != 0) {
|
||||||
|
/* If the lhs is direct (but not stack relative), encode compares with lhs,
|
||||||
/* If the lhs is direct (but not stack relative), encode compares with lhs
|
** effectively reversing the order (which doesn't matter for == and !=).
|
||||||
** effectively reverting the order (which doesn't matter for ==).
|
|
||||||
*/
|
*/
|
||||||
Cond = FindBoolCmpCond (BoolTransformer);
|
Cond = FindBoolCmpCond (BoolTransformer);
|
||||||
Cond = GetRevertedCond (Cond);
|
Cond = GetRevertedCond (Cond);
|
||||||
@@ -1138,7 +1137,6 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer)
|
|||||||
D->Lhs.A.Flags |= LI_REMOVE;
|
D->Lhs.A.Flags |= LI_REMOVE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* We'll do reverse-compare */
|
/* We'll do reverse-compare */
|
||||||
Cond = FindBoolCmpCond (BoolTransformer);
|
Cond = FindBoolCmpCond (BoolTransformer);
|
||||||
Cond = GetRevertedCond (Cond);
|
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);
|
X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI);
|
||||||
InsertEntry (D, X, D->IP++);
|
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);
|
RemoveRemainders (D);
|
||||||
|
|
||||||
/* We changed the sequence */
|
/* 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)
|
static unsigned Opt_a_tosicmp (StackOpData* D)
|
||||||
/* Replace tosicmp with CMP */
|
/* Replace tosicmp with CMP */
|
||||||
{
|
{
|
||||||
@@ -1236,7 +1218,7 @@ static unsigned Opt_a_tosicmp (StackOpData* D)
|
|||||||
}
|
}
|
||||||
InsertEntry (D, X, D->IP++);
|
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) {
|
if (D->Rhs.A.LoadEntry->OPC == OP65_JSR) {
|
||||||
/* opc (sp),y */
|
/* opc (sp),y */
|
||||||
X = NewCodeEntry (OP65_CMP, AM65_ZP_INDY, "sp", 0, D->OpEntry->LI);
|
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);
|
InsertEntry (D, X, D->IP-3);
|
||||||
|
|
||||||
} else {
|
} 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 &&
|
if ((RI = GetLastChangedRegInfo (D, &D->Lhs.A)) != 0 &&
|
||||||
RegValIsKnown (RI->Out.RegA) &&
|
RegValIsKnown (RI->Out.RegA) &&
|
||||||
(RI->Out.RegA & 0xFF) == 0) {
|
(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);
|
InsertEntry (D, X, D->OpIndex + 1);
|
||||||
} else {
|
} 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);
|
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);
|
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)
|
static unsigned Opt_a_tosne (StackOpData* D)
|
||||||
/* Optimize the toseqax sequence */
|
/* Optimize the tosneax sequence */
|
||||||
{
|
{
|
||||||
return Opt_a_toscmpbool (D, "boolne");
|
return Opt_a_toscmpbool (D, "boolne");
|
||||||
}
|
}
|
||||||
@@ -1317,7 +1283,7 @@ static unsigned Opt_a_tosne (StackOpData* D)
|
|||||||
|
|
||||||
|
|
||||||
static unsigned Opt_a_tosuge (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");
|
return Opt_a_toscmpbool (D, "booluge");
|
||||||
}
|
}
|
||||||
@@ -1325,7 +1291,7 @@ static unsigned Opt_a_tosuge (StackOpData* D)
|
|||||||
|
|
||||||
|
|
||||||
static unsigned Opt_a_tosugt (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");
|
return Opt_a_toscmpbool (D, "boolugt");
|
||||||
}
|
}
|
||||||
@@ -1333,7 +1299,7 @@ static unsigned Opt_a_tosugt (StackOpData* D)
|
|||||||
|
|
||||||
|
|
||||||
static unsigned Opt_a_tosule (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");
|
return Opt_a_toscmpbool (D, "boolule");
|
||||||
}
|
}
|
||||||
@@ -1341,7 +1307,7 @@ static unsigned Opt_a_tosule (StackOpData* D)
|
|||||||
|
|
||||||
|
|
||||||
static unsigned Opt_a_tosult (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");
|
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[] = {
|
static const OptFuncDesc FuncTable[] = {
|
||||||
{ "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN },
|
{ "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN },
|
||||||
{ "staspidx", Opt_staspidx, REG_NONE, OP_NONE },
|
{ "staspidx", Opt_staspidx, REG_NONE, OP_NONE },
|
||||||
@@ -1379,11 +1347,11 @@ static const OptFuncDesc FuncTable[] = {
|
|||||||
|
|
||||||
static const OptFuncDesc FuncRegATable[] = {
|
static const OptFuncDesc FuncRegATable[] = {
|
||||||
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
||||||
{ "tosgeax", Opt_a_tosge, REG_NONE, OP_NONE },
|
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
||||||
{ "tosgtax", Opt_a_tosgt, REG_NONE, OP_NONE },
|
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
||||||
{ "tosicmp", Opt_a_tosicmp, REG_NONE, OP_NONE },
|
{ "tosicmp", Opt_a_tosicmp, REG_NONE, OP_NONE },
|
||||||
{ "tosleax", Opt_a_tosle, REG_NONE, OP_NONE },
|
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
||||||
{ "tosltax", Opt_a_toslt, REG_NONE, OP_NONE },
|
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
|
||||||
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
|
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
|
||||||
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
||||||
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */
|
|||||||
IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */
|
IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */
|
||||||
IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */
|
IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */
|
||||||
IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */
|
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 */
|
/* Map the name of a warning to the intstack that holds its state */
|
||||||
typedef struct WarnMapEntry WarnMapEntry;
|
typedef struct WarnMapEntry WarnMapEntry;
|
||||||
@@ -92,6 +93,7 @@ static WarnMapEntry WarnMap[] = {
|
|||||||
{ &WarnUnusedLabel, "unused-label" },
|
{ &WarnUnusedLabel, "unused-label" },
|
||||||
{ &WarnUnusedParam, "unused-param" },
|
{ &WarnUnusedParam, "unused-param" },
|
||||||
{ &WarnUnusedVar, "unused-var" },
|
{ &WarnUnusedVar, "unused-var" },
|
||||||
|
{ &WarnReturnType, "return-type" },
|
||||||
};
|
};
|
||||||
|
|
||||||
Collection DiagnosticStrBufs;
|
Collection DiagnosticStrBufs;
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ extern IntStack WarnUnknownPragma; /* - unknown #pragmas */
|
|||||||
extern IntStack WarnUnusedLabel; /* - unused labels */
|
extern IntStack WarnUnusedLabel; /* - unused labels */
|
||||||
extern IntStack WarnUnusedParam; /* - unused parameters */
|
extern IntStack WarnUnusedParam; /* - unused parameters */
|
||||||
extern IntStack WarnUnusedVar; /* - unused variables */
|
extern IntStack WarnUnusedVar; /* - unused variables */
|
||||||
|
extern IntStack WarnReturnType; /* - control reaches end of non-void function */
|
||||||
|
|
||||||
/* Forward */
|
/* Forward */
|
||||||
struct StrBuf;
|
struct StrBuf;
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define SQP_KEEP_NONE 0x00
|
#define SQP_KEEP_NONE 0x00
|
||||||
#define SQP_KEEP_TEST 0x01U
|
#define SQP_KEEP_TEST 0x01U
|
||||||
#define SQP_KEEP_EAX 0x02U
|
#define SQP_KEEP_EAX 0x02U
|
||||||
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */
|
#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -654,8 +654,8 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
|
|||||||
** environment returning int, output a warning if we didn't see a return
|
** environment returning int, output a warning if we didn't see a return
|
||||||
** statement.
|
** statement.
|
||||||
*/
|
*/
|
||||||
if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc) {
|
if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc && IS_Get (&WarnReturnType)) {
|
||||||
Warning ("Control reaches end of non-void function");
|
Warning ("Control reaches end of non-void function [-Wreturn-type]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is the main function in a C99 environment returning an int, let
|
/* If this is the main function in a C99 environment returning an int, let
|
||||||
|
|||||||
@@ -117,14 +117,6 @@ $(WORKDIR)/endless.$1.$2.prg: endless.c | $(WORKDIR)
|
|||||||
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
|
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
|
||||||
$(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(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,
|
# these need reference data that can't be generated by a host-compiled program,
|
||||||
# in a useful way
|
# in a useful way
|
||||||
$(WORKDIR)/limits.$1.$2.prg: limits.c $(ISEQUAL) | $(WORKDIR)
|
$(WORKDIR)/limits.$1.$2.prg: limits.c $(ISEQUAL) | $(WORKDIR)
|
||||||
|
|||||||
1044
test/val/binlit.c
1044
test/val/binlit.c
File diff suppressed because it is too large
Load Diff
@@ -7,24 +7,24 @@
|
|||||||
|
|
||||||
struct ImageStruct
|
struct ImageStruct
|
||||||
{
|
{
|
||||||
uint8_t _imageData;
|
uint8_t _imageData;
|
||||||
#if !defined(NO_COLOR)
|
#if !defined(NO_COLOR)
|
||||||
uint8_t _color;
|
uint8_t _color;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ImageStruct Image;
|
typedef struct ImageStruct Image;
|
||||||
|
|
||||||
struct CharacterStruct
|
struct CharacterStruct
|
||||||
{
|
{
|
||||||
// character coordinates
|
// character coordinates
|
||||||
uint8_t _x;
|
uint8_t _x;
|
||||||
uint8_t _y;
|
uint8_t _y;
|
||||||
|
|
||||||
// _status decides whether the character is active
|
// _status decides whether the character is active
|
||||||
uint8_t _status;
|
uint8_t _status;
|
||||||
|
|
||||||
Image* _imagePtr;
|
Image* _imagePtr;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct CharacterStruct Character;
|
typedef struct CharacterStruct Character;
|
||||||
@@ -53,20 +53,20 @@ Character bombs[BOMBS_NUMBER];
|
|||||||
|
|
||||||
uint16_t test1(void)
|
uint16_t test1(void)
|
||||||
{
|
{
|
||||||
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
|
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
|
||||||
{
|
{
|
||||||
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*8;
|
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*8;
|
||||||
}
|
}
|
||||||
return GHOST_MIN_SLOWDOWN;
|
return GHOST_MIN_SLOWDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t test2(void)
|
uint16_t test2(void)
|
||||||
{
|
{
|
||||||
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
|
if((loop<MAX_GHOST_LOOP) && (ghostLevel<MAX_GHOST_LEVEL))
|
||||||
{
|
{
|
||||||
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*16;
|
return INITIAL_GHOST_SLOWDOWN-(uint16_t)level*256-ghostLevel*16;
|
||||||
}
|
}
|
||||||
return GHOST_MIN_SLOWDOWN;
|
return GHOST_MIN_SLOWDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t res = 0;
|
uint16_t res = 0;
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
|
/* bug #1348, wrongly optimized integer promotion in comparison */
|
||||||
/* bug#1348, wrongly optimized integer promotion in comparison */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int notrandtab[] = {
|
static const int notrandtab[] = {
|
||||||
0xffff, 0x7fff, 0x3fff, 0x1fff,
|
0xffff, 0x7fff, 0x3fff, 0x1fff,
|
||||||
0x0fff, 0x07ff, 0x03ff, 0x01ff,
|
0x0fff, 0x07ff, 0x03ff, 0x01ff,
|
||||||
0x00ff, 0x007f, 0x003f, 0x001f,
|
0x00ff, 0x007f, 0x003f, 0x001f,
|
||||||
0x000f, 0x0007, 0x0003, 0x0001
|
0x000f, 0x0007, 0x0003, 0x0001
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned char notrandcount = 0;
|
static unsigned char notrandcount = 0;
|
||||||
|
|
||||||
int notrand(void)
|
static int notrand(void)
|
||||||
{
|
{
|
||||||
return notrandtab[notrandcount & 0x0f];
|
return notrandtab[notrandcount & 0x0f];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char n1, n2;
|
static unsigned char n1, n2;
|
||||||
unsigned char i, ii, s;
|
static unsigned char i, ii, s;
|
||||||
unsigned char err = 0;
|
static unsigned char err = 0;
|
||||||
|
|
||||||
unsigned char cmptab[] = {
|
static const unsigned char cmptab[] = {
|
||||||
0xff, 0x7f, 0x3f, 0x1f,
|
0xff, 0x7f, 0x3f, 0x1f,
|
||||||
0x0f, 0x07, 0x03, 0x01,
|
0x0f, 0x07, 0x03, 0x01,
|
||||||
0x80, 0x40, 0x20, 0x10,
|
0x80, 0x40, 0x20, 0x10,
|
||||||
@@ -40,13 +39,14 @@ int main(void)
|
|||||||
if ((notrand() & 0xffu) > s) {
|
if ((notrand() & 0xffu) > s) {
|
||||||
n2 = 1;
|
n2 = 1;
|
||||||
}
|
}
|
||||||
printf("%5d>%3d %d(%02x) %d(%02x) %s\n",
|
printf("%5d > %3d %u(%02x) %u(%02x) %s\n",
|
||||||
notrandtab[notrandcount & 0x0f], s,
|
notrandtab[i], s,
|
||||||
n1, (notrand() & 0xff),
|
n1, (notrand() & 0xff),
|
||||||
n2, (notrand() & 0xffu),
|
n2, (notrand() & 0xffu),
|
||||||
n1 == n2 ? "=" : "!="
|
n1 == n2 ? "=" : "!=");
|
||||||
);
|
if (n1 != n2) {
|
||||||
if (n1 != n2) err = 1;
|
err = 1;
|
||||||
|
}
|
||||||
notrandcount++;
|
notrandcount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
134
test/val/rand.c
134
test/val/rand.c
@@ -28,83 +28,83 @@ static uint32_t seed;
|
|||||||
|
|
||||||
int ref_rand()
|
int ref_rand()
|
||||||
{
|
{
|
||||||
uint16_t output;
|
uint16_t output;
|
||||||
/* seed follows the LCG sequence * 0x01010101 + 0xB3B3B3B3 */
|
/* seed follows the LCG sequence * 0x01010101 + 0xB3B3B3B3 */
|
||||||
seed = seed * 0x01010101UL + 0xB3B3B3B3UL;
|
seed = seed * 0x01010101UL + 0xB3B3B3B3UL;
|
||||||
/* output uses the top two bytes (reversed) XOR with bottom two bytes */
|
/* output uses the top two bytes (reversed) XOR with bottom two bytes */
|
||||||
{
|
{
|
||||||
uint16_t s0 = (seed >> 0) & 0xFF;
|
uint16_t s0 = (seed >> 0) & 0xFF;
|
||||||
uint16_t s1 = (seed >> 8) & 0xFF;
|
uint16_t s1 = (seed >> 8) & 0xFF;
|
||||||
uint16_t s2 = (seed >> 16) & 0xFF;
|
uint16_t s2 = (seed >> 16) & 0xFF;
|
||||||
uint16_t s3 = (seed >> 24) & 0xFF;
|
uint16_t s3 = (seed >> 24) & 0xFF;
|
||||||
uint16_t o0 = s3 ^ s1;
|
uint16_t o0 = s3 ^ s1;
|
||||||
uint16_t o1 = s2 ^ s0;
|
uint16_t o1 = s2 ^ s0;
|
||||||
output = o0 | (o1 << 8);
|
output = o0 | (o1 << 8);
|
||||||
}
|
}
|
||||||
return (int)(output & 0x7FFF);
|
return (int)(output & 0x7FFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ref_srand(int ax)
|
void ref_srand(int ax)
|
||||||
{
|
{
|
||||||
uint32_t s = (unsigned int)ax;
|
uint32_t s = (unsigned int)ax;
|
||||||
seed = s | (s << 16); /* low 16 bits is convenient filler for high 16 bits */
|
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 */
|
ref_rand(); /* one pre-call "shuffles" the first rand() result so it isn't too predictable */
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
unsigned int i,j;
|
unsigned int i,j;
|
||||||
int a,b;
|
int a,b;
|
||||||
|
|
||||||
/* test that startup state is equivalent to srand(1) */
|
/* test that startup state is equivalent to srand(1) */
|
||||||
{
|
{
|
||||||
//srand(1); // implied
|
//srand(1); // implied
|
||||||
ref_srand(1);
|
ref_srand(1);
|
||||||
for (j=0; j<SUBTESTS; ++j)
|
for (j=0; j<SUBTESTS; ++j)
|
||||||
{
|
{
|
||||||
a = rand();
|
a = rand();
|
||||||
b = ref_rand();
|
b = ref_rand();
|
||||||
if (a != b)
|
if (a != b)
|
||||||
{
|
{
|
||||||
printf("failed startup seed at test %d. rand()=%d reference=%d\n",j,a,b);
|
printf("failed startup seed at test %d. rand()=%d reference=%d\n",j,a,b);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test every power of 2 seed */
|
/* test every power of 2 seed */
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
srand(1<<i);
|
srand(1<<i);
|
||||||
ref_srand(1<<i);
|
ref_srand(1<<i);
|
||||||
for (j=0; j<SUBTESTS; ++j)
|
for (j=0; j<SUBTESTS; ++j)
|
||||||
{
|
{
|
||||||
a = rand();
|
a = rand();
|
||||||
b = ref_rand();
|
b = ref_rand();
|
||||||
if (a != b)
|
if (a != b)
|
||||||
{
|
{
|
||||||
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
|
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test a sampling of seeds*/
|
/* test a sampling of seeds*/
|
||||||
for (i = 0; i < 32768UL; i += TESTINC)
|
for (i = 0; i < 32768UL; i += TESTINC)
|
||||||
{
|
{
|
||||||
srand(i);
|
srand(i);
|
||||||
ref_srand(i);
|
ref_srand(i);
|
||||||
for (j=0; j<SUBTESTS; ++j)
|
for (j=0; j<SUBTESTS; ++j)
|
||||||
{
|
{
|
||||||
a = rand();
|
a = rand();
|
||||||
b = ref_rand();
|
b = ref_rand();
|
||||||
if (a != b)
|
if (a != b)
|
||||||
{
|
{
|
||||||
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
|
printf("failed seed %d at test %d. rand()=%d reference=%d\n",(1<<i),j,a,b);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user