Add overflow and underflow checking for floats
This commit is contained in:
parent
84648fbd88
commit
93174c8e68
|
@ -38,8 +38,7 @@ There are still several open areas, but most targets have been reached. The cur
|
||||||
|
|
||||||
### Runtime
|
### Runtime
|
||||||
|
|
||||||
* No INF and NaN support for floats
|
* No NaN support for floats
|
||||||
* Underflow in float multiply and divide not checked
|
|
||||||
* Basic zero page variables not restored on stop/restore
|
* Basic zero page variables not restored on stop/restore
|
||||||
|
|
||||||
### Optimizing
|
### Optimizing
|
||||||
|
|
107
include/crt.c
107
include/crt.c
|
@ -2474,6 +2474,22 @@ W1:
|
||||||
|
|
||||||
__asm faddsub
|
__asm faddsub
|
||||||
{
|
{
|
||||||
|
lda #$ff
|
||||||
|
cmp tmp + 4
|
||||||
|
beq INF
|
||||||
|
cmp tmp + 5
|
||||||
|
bne nINF
|
||||||
|
INF:
|
||||||
|
lda accu + 3
|
||||||
|
ora #$7f
|
||||||
|
sta accu + 3
|
||||||
|
lda #$80
|
||||||
|
sta accu + 2
|
||||||
|
lda #$00
|
||||||
|
sta accu + 0
|
||||||
|
sta accu + 1
|
||||||
|
rts
|
||||||
|
nINF:
|
||||||
sec
|
sec
|
||||||
lda tmp + 4
|
lda tmp + 4
|
||||||
sbc tmp + 5
|
sbc tmp + 5
|
||||||
|
@ -2542,6 +2558,8 @@ fas_aligned:
|
||||||
inc tmp + 4
|
inc tmp + 4
|
||||||
fas_done:
|
fas_done:
|
||||||
lda tmp + 4
|
lda tmp + 4
|
||||||
|
cmp #$ff
|
||||||
|
beq INF
|
||||||
lsr
|
lsr
|
||||||
ora accu + 3
|
ora accu + 3
|
||||||
sta accu + 3
|
sta accu + 3
|
||||||
|
@ -2677,6 +2695,17 @@ W1:
|
||||||
sta accu + 3
|
sta accu + 3
|
||||||
rts
|
rts
|
||||||
W2:
|
W2:
|
||||||
|
lda accu + 3
|
||||||
|
eor tmp + 3
|
||||||
|
and #$80
|
||||||
|
sta accu + 3
|
||||||
|
|
||||||
|
lda #$ff
|
||||||
|
cmp tmp + 4
|
||||||
|
beq INF
|
||||||
|
cmp tmp + 5
|
||||||
|
beq INF
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
sta tmp + 6
|
sta tmp + 6
|
||||||
sta tmp + 7
|
sta tmp + 7
|
||||||
|
@ -2707,16 +2736,28 @@ W5:
|
||||||
W3: and #$7f
|
W3: and #$7f
|
||||||
sta tmp + 8
|
sta tmp + 8
|
||||||
|
|
||||||
lda accu + 3
|
|
||||||
eor tmp + 3
|
|
||||||
and #$80
|
|
||||||
sta accu + 3
|
|
||||||
|
|
||||||
lda tmp + 4
|
lda tmp + 4
|
||||||
sbc #$7e
|
|
||||||
|
|
||||||
clc
|
|
||||||
adc tmp + 5
|
adc tmp + 5
|
||||||
|
bcc W7
|
||||||
|
|
||||||
|
sbc #$7f
|
||||||
|
bcs INF
|
||||||
|
cmp #$ff
|
||||||
|
bne W8
|
||||||
|
INF:
|
||||||
|
lda accu + 3
|
||||||
|
ora #$7f
|
||||||
|
sta accu + 3
|
||||||
|
lda #$80
|
||||||
|
sta accu + 2
|
||||||
|
lda #$00
|
||||||
|
sta accu + 0
|
||||||
|
sta accu + 1
|
||||||
|
rts
|
||||||
|
W7:
|
||||||
|
sbc #$7e
|
||||||
|
bcc ZERO
|
||||||
|
W8:
|
||||||
lsr
|
lsr
|
||||||
ora accu + 3
|
ora accu + 3
|
||||||
sta accu + 3
|
sta accu + 3
|
||||||
|
@ -2729,6 +2770,13 @@ W3: and #$7f
|
||||||
lda tmp + 6
|
lda tmp + 6
|
||||||
sta accu
|
sta accu
|
||||||
rts
|
rts
|
||||||
|
ZERO:
|
||||||
|
lda #0
|
||||||
|
sta accu
|
||||||
|
sta accu + 1
|
||||||
|
sta accu + 2
|
||||||
|
sta accu + 3
|
||||||
|
rts
|
||||||
}
|
}
|
||||||
|
|
||||||
__asm inp_binop_mul_f32
|
__asm inp_binop_mul_f32
|
||||||
|
@ -2754,6 +2802,12 @@ W1:
|
||||||
and #$80
|
and #$80
|
||||||
sta accu + 3
|
sta accu + 3
|
||||||
|
|
||||||
|
lda tmp + 5
|
||||||
|
beq INF
|
||||||
|
lda tmp + 4
|
||||||
|
cmp #$ff
|
||||||
|
beq INF
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
sta tmp + 6
|
sta tmp + 6
|
||||||
sta tmp + 7
|
sta tmp + 7
|
||||||
|
@ -2804,12 +2858,29 @@ W4:
|
||||||
and #$7f
|
and #$7f
|
||||||
sta tmp + 8
|
sta tmp + 8
|
||||||
|
|
||||||
lda tmp + 5
|
lda tmp + 4
|
||||||
eor #$7f
|
sbc tmp + 5
|
||||||
adc tmp + 4
|
bcc W5
|
||||||
sec
|
|
||||||
sbc #1
|
|
||||||
|
|
||||||
|
clc
|
||||||
|
adc #$7f
|
||||||
|
bcs INF
|
||||||
|
cmp #$ff
|
||||||
|
bne W6
|
||||||
|
INF:
|
||||||
|
lda accu + 3
|
||||||
|
ora #$7f
|
||||||
|
sta accu + 3
|
||||||
|
lda #$80
|
||||||
|
sta accu + 2
|
||||||
|
lda #$00
|
||||||
|
sta accu + 1
|
||||||
|
sta accu + 0
|
||||||
|
rts
|
||||||
|
W5:
|
||||||
|
adc #$7f
|
||||||
|
bcc ZERO
|
||||||
|
W6:
|
||||||
lsr
|
lsr
|
||||||
ora accu + 3
|
ora accu + 3
|
||||||
sta accu + 3
|
sta accu + 3
|
||||||
|
@ -2822,6 +2893,16 @@ W4:
|
||||||
lda tmp + 6
|
lda tmp + 6
|
||||||
sta accu
|
sta accu
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
ZERO:
|
||||||
|
lda #$00
|
||||||
|
sta accu + 3
|
||||||
|
sta accu + 2
|
||||||
|
sta accu + 1
|
||||||
|
sta accu + 0
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma bytecode(BC_BINOP_MUL_F32, inp_binop_mul_f32)
|
#pragma bytecode(BC_BINOP_MUL_F32, inp_binop_mul_f32)
|
||||||
|
|
|
@ -199,3 +199,37 @@ float sqrt(float f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isinf(float f)
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
lda #$00
|
||||||
|
sta accu + 1
|
||||||
|
asl f + 2
|
||||||
|
lda f + 3
|
||||||
|
rol
|
||||||
|
eor #$ff
|
||||||
|
beq W1
|
||||||
|
lda #$01
|
||||||
|
W1:
|
||||||
|
eor #$01
|
||||||
|
sta accu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isfinite(float f)
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
lda #$00
|
||||||
|
sta accu + 1
|
||||||
|
asl f + 2
|
||||||
|
lda f + 3
|
||||||
|
rol
|
||||||
|
eor #$ff
|
||||||
|
beq W1
|
||||||
|
lda #$01
|
||||||
|
W1:
|
||||||
|
sta accu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ float log10(float f);
|
||||||
float pow(float p, float q);
|
float pow(float p, float q);
|
||||||
float sqrt(float f);
|
float sqrt(float f);
|
||||||
|
|
||||||
|
bool isinf(float f);
|
||||||
|
bool isfinite(float f);
|
||||||
|
|
||||||
#pragma intrinsic(fabs)
|
#pragma intrinsic(fabs)
|
||||||
#pragma intrinsic(floor)
|
#pragma intrinsic(floor)
|
||||||
#pragma intrinsic(ceil)
|
#pragma intrinsic(ceil)
|
||||||
|
|
183
include/stdio.c
183
include/stdio.c
|
@ -259,105 +259,114 @@ int nformf(const sinfo * si, char * str, float f, char type)
|
||||||
else if (si->sign)
|
else if (si->sign)
|
||||||
sp[d++] = '+';
|
sp[d++] = '+';
|
||||||
|
|
||||||
int exp = 0;
|
if (isinf(f))
|
||||||
|
|
||||||
char fdigits = si->precision != 255 ? si->precision : 6;
|
|
||||||
|
|
||||||
if (f != 0.0)
|
|
||||||
{
|
{
|
||||||
while (f >= 1000.0)
|
sp[d++] = 'I';
|
||||||
{
|
sp[d++] = 'N';
|
||||||
f /= 1000;
|
sp[d++] = 'F';
|
||||||
exp += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (f < 1.0)
|
|
||||||
{
|
|
||||||
f *= 1000;
|
|
||||||
exp -= 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (f >= 10.0)
|
|
||||||
{
|
|
||||||
f /= 10;
|
|
||||||
exp ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
char digits = fdigits + 1;
|
|
||||||
bool fexp = type == 'e';
|
|
||||||
|
|
||||||
if (type == 'g')
|
|
||||||
{
|
|
||||||
if (exp > 3 || exp < 0)
|
|
||||||
fexp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fexp)
|
|
||||||
{
|
|
||||||
while (exp < 0)
|
|
||||||
{
|
|
||||||
f /= 10.0;
|
|
||||||
exp++;
|
|
||||||
}
|
|
||||||
digits = fdigits + exp + 1;
|
|
||||||
|
|
||||||
float r = 0.5;
|
|
||||||
for(char i=1; i<digits; i++)
|
|
||||||
r /= 10.0;
|
|
||||||
f += r;
|
|
||||||
if (f >= 10.0)
|
|
||||||
{
|
|
||||||
f /= 10.0;
|
|
||||||
fdigits--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float r = 0.5;
|
int exp = 0;
|
||||||
for(char i=0; i<fdigits; i++)
|
|
||||||
r /= 10.0;
|
char fdigits = si->precision != 255 ? si->precision : 6;
|
||||||
f += r;
|
|
||||||
if (f >= 10.0)
|
if (f != 0.0)
|
||||||
{
|
{
|
||||||
f /= 10.0;
|
while (f >= 1000.0)
|
||||||
exp ++;
|
{
|
||||||
|
f /= 1000;
|
||||||
|
exp += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (f < 1.0)
|
||||||
|
{
|
||||||
|
f *= 1000;
|
||||||
|
exp -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (f >= 10.0)
|
||||||
|
{
|
||||||
|
f /= 10;
|
||||||
|
exp ++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
char digits = fdigits + 1;
|
||||||
|
bool fexp = type == 'e';
|
||||||
|
|
||||||
char pdigits = digits - fdigits;
|
if (type == 'g')
|
||||||
|
|
||||||
if (digits > 20)
|
|
||||||
digits = 20;
|
|
||||||
|
|
||||||
if (pdigits == 0)
|
|
||||||
sp[d++] = '0';
|
|
||||||
|
|
||||||
for(char i=0; i<digits; i++)
|
|
||||||
{
|
|
||||||
if (i == pdigits)
|
|
||||||
sp[d++] = '.';
|
|
||||||
int c = (int)f;
|
|
||||||
f -= (float)c;
|
|
||||||
f *= 10.0;
|
|
||||||
sp[d++] = c + '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fexp)
|
|
||||||
{
|
|
||||||
sp[d++] = 'E';
|
|
||||||
if (exp < 0)
|
|
||||||
{
|
{
|
||||||
sp[d++] = '-';
|
if (exp > 3 || exp < 0)
|
||||||
exp = -exp;
|
fexp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fexp)
|
||||||
|
{
|
||||||
|
while (exp < 0)
|
||||||
|
{
|
||||||
|
f /= 10.0;
|
||||||
|
exp++;
|
||||||
|
}
|
||||||
|
digits = fdigits + exp + 1;
|
||||||
|
|
||||||
|
float r = 0.5;
|
||||||
|
for(char i=1; i<digits; i++)
|
||||||
|
r /= 10.0;
|
||||||
|
f += r;
|
||||||
|
if (f >= 10.0)
|
||||||
|
{
|
||||||
|
f /= 10.0;
|
||||||
|
fdigits--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sp[d++] = '+';
|
{
|
||||||
|
float r = 0.5;
|
||||||
|
for(char i=0; i<fdigits; i++)
|
||||||
|
r /= 10.0;
|
||||||
|
f += r;
|
||||||
|
if (f >= 10.0)
|
||||||
|
{
|
||||||
|
f /= 10.0;
|
||||||
|
exp ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sp[d++] = exp / 10 + '0';
|
|
||||||
sp[d++] = exp % 10 + '0';
|
char pdigits = digits - fdigits;
|
||||||
|
|
||||||
|
if (digits > 20)
|
||||||
|
digits = 20;
|
||||||
|
|
||||||
|
if (pdigits == 0)
|
||||||
|
sp[d++] = '0';
|
||||||
|
|
||||||
|
for(char i=0; i<digits; i++)
|
||||||
|
{
|
||||||
|
if (i == pdigits)
|
||||||
|
sp[d++] = '.';
|
||||||
|
int c = (int)f;
|
||||||
|
f -= (float)c;
|
||||||
|
f *= 10.0;
|
||||||
|
sp[d++] = c + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fexp)
|
||||||
|
{
|
||||||
|
sp[d++] = 'E';
|
||||||
|
if (exp < 0)
|
||||||
|
{
|
||||||
|
sp[d++] = '-';
|
||||||
|
exp = -exp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sp[d++] = '+';
|
||||||
|
|
||||||
|
sp[d++] = exp / 10 + '0';
|
||||||
|
sp[d++] = exp % 10 + '0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d < si->width)
|
if (d < si->width)
|
||||||
|
|
|
@ -707,6 +707,59 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
|
||||||
nexp->mDecValue = ndec;
|
nexp->mDecValue = ndec;
|
||||||
exp = nexp;
|
exp = nexp;
|
||||||
}
|
}
|
||||||
|
else if (exp->mType == EX_CONSTANT && exp->mDecType != dtype)
|
||||||
|
{
|
||||||
|
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTANT);
|
||||||
|
nexp->mDecType = dtype;
|
||||||
|
|
||||||
|
if (dtype->mType == DT_TYPE_INTEGER || dtype->mType == DT_TYPE_ENUM || dtype->mType == DT_TYPE_BOOL)
|
||||||
|
{
|
||||||
|
Declaration* ndec = new Declaration(exp->mDecValue->mLocation, DT_CONST_INTEGER);
|
||||||
|
ndec->mBase = dtype;
|
||||||
|
ndec->mSize = dtype->mSize;
|
||||||
|
|
||||||
|
if (exp->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
|
ndec->mInteger = exp->mDecValue->mInteger;
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_FLOAT)
|
||||||
|
ndec->mInteger = int64(exp->mDecValue->mNumber);
|
||||||
|
else
|
||||||
|
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Illegal integer constant initializer");
|
||||||
|
|
||||||
|
nexp->mDecValue = ndec;
|
||||||
|
}
|
||||||
|
else if (dtype->mType == DT_TYPE_FLOAT)
|
||||||
|
{
|
||||||
|
Declaration* ndec = new Declaration(exp->mDecValue->mLocation, DT_CONST_FLOAT);
|
||||||
|
ndec->mBase = dtype;
|
||||||
|
ndec->mSize = dtype->mSize;
|
||||||
|
|
||||||
|
if (exp->mDecValue->mType == DT_CONST_INTEGER)
|
||||||
|
ndec->mNumber = double(exp->mDecValue->mInteger);
|
||||||
|
else if (exp->mDecValue->mType == DT_CONST_FLOAT)
|
||||||
|
ndec->mNumber = exp->mDecValue->mNumber;
|
||||||
|
else
|
||||||
|
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Illegal float constant initializer");
|
||||||
|
|
||||||
|
nexp->mDecValue = ndec;
|
||||||
|
}
|
||||||
|
else if (dtype->mType == DT_TYPE_POINTER)
|
||||||
|
{
|
||||||
|
if (exp->mDecValue->mType == DT_CONST_ADDRESS)
|
||||||
|
;
|
||||||
|
else
|
||||||
|
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Illegal pointer constant initializer");
|
||||||
|
|
||||||
|
nexp = exp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Illegal constant initializer");
|
||||||
|
nexp = exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
exp = nexp;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return exp;
|
return exp;
|
||||||
|
|
Loading…
Reference in New Issue