DSPRelated.com
Forums

problem with log( ) implementation

Started by Safa Ouerghi November 16, 2011
Good morning,
I'm trying to implement the function log() on a DSP blackfin using the assembly language. I found this C code:
[code]
int fxlog(int x) {
int t,y;

y=0xa65af;
if(x<0x00008000) x<<, y-=0xb1721;
if(x<0x00800000) x<<= 8, y-=0x58b91;
if(x<0x08000000) x<<= 4, y-=0x2c5c8;
if(x<0x20000000) x<<= 2, y-=0x162e4;
if(x<0x40000000) x<<= 1, y-=0x0b172;
t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
x=0x80000000-x;
y-=x>>15;
return y;
}
[\code]

so i tried to convert it to assembly using the 16.16 format.

[code]
.section L1_data_a;
.byte4 _x[2]={0x360000,0x22};
.byte4 _val[12]={0xb1721,0x58b91,0x2c5c8,0x162e4,0x0b172,0x067cd,0x03920,0x01e27,0x00f85,0x007e1,0x003f8,0x001fe};
.section L1_code;
.global _log;

_log:

I0.h=_val;
I0.l=_val;
//I0;
//L0H;
I3.H=_x;//variable x
I3.L=_x;
//***initialisation des registres***

R0.l= 0x65AF ; //y0=0xa65af
R0.h=0xA ;

R1.l=0x8000 ;// lim1 de x
R1.H=0x0;

R2.H=0x80 ; //lim2 de x
R2.L=0x0;

R3.H=0x800 ;//lim3 de x
R3.L=0x0;

R4.H=0x2000 ;//lim4 de x
R4.L=0x0;

R5.H=0x4000 ;//lim5 de x
R5.L=0x0;
R6=[I3++];//charger la valeur de x de 32 bits

R7=[I0++];//charger la valeur ln(x) qu'on va soustraire de y

cc=R6
if !cc jump _case2;

R6=R6<<16;

R0=R0-R7 (ns); //R7 contient la valeur de y

_case2:

cc=R6 if !cc jump _case3;

R6=R6<<8;

R7=[I0++];

R0=R0-R7(ns); //R7 contient la valeur de y

_case3:
cc=R6 if !cc jump _case4;

R6=R6<<4;

R7=[I0++];

R0=R0-R7(ns); //R7 contient la valeur de y

_case4:

cc=R6 if !cc jump _case5;

R6=R6<<2;

R7=[I0++];

R0=R0-R7(ns); //R7 contient la valeur de y

_case5:

cc=R6 if !cc jump _rest;

R6=R6<<1;

R7=[I0++];

R0=R0-R7(ns); //R7 contient la valeur de y

_rest:

nop;

R1=R6>>1;//x>>1
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _op2;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);
_op2:

R1=R6>>2;
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _op3;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);

_op3:
R1=R6>>3;
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _op4;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);

_op4:
R1=R6>>4;
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _op5;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);

_op5:
R1=R6>>5;
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _op6;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);

_op6:
R1=R6>>6;
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _op7;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);

_op7:
R1=R6>>7;
R2=R1+R6; //valeur de t dans R2
cc=BITTST(R2,31);
if cc jump _linearisation;
R6=R2;
R7=[I0++];
R0=R0-R7 (ns);

_linearisation:
nop;
R4.H=0x8000 ;//0x800000000 dans R4
R4.L=0x0;

R6=R4-R6 (ns);
R6=R6>>15;
R0=R0-R6 (ns);

rts;
_log.end:
[\code]

The results are not those expected.Please help me

Sincerely,
syrine
Howdy Safa,

The first question is what were you expecting? If you input ints for C
and use fractions for assembler you will see some difference.

You should be able to printf in C for every step that you can debug with
assembler. So you can watch the registers and compare every step with
what you expect. If the difference starts at some point you can then
determine why, and fix your code.

If the C code works (you should verify that with several values useful to
your problem) then you have an ideal situation - you can put in the exact
same values and follow every step of the way. If it's the first step, it
will take a while to debug the whole thing, more likely it's in the middle
some where and just finding where the difference between what you want and
what you have is the major debuggin chore. Once you find the problem,
fixing it is pretty easy.

Patience, persistence, truth,
Dr. mike

On Wed, 16 Nov 2011, Safa Ouerghi wrote:

> Good morning,
> I'm trying to implement the function log() on a DSP blackfin using the assembly language. I found this C code:
> [code]
> int fxlog(int x) {
> int t,y;
>
> y=0xa65af;
> if(x<0x00008000) x<<, y-=0xb1721;
> if(x<0x00800000) x<<= 8, y-=0x58b91;
> if(x<0x08000000) x<<= 4, y-=0x2c5c8;
> if(x<0x20000000) x<<= 2, y-=0x162e4;
> if(x<0x40000000) x<<= 1, y-=0x0b172;
> t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
> t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
> t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
> t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
> t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
> t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
> t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
> x=0x80000000-x;
> y-=x>>15;
> return y;
> }
> [\code]
>
> so i tried to convert it to assembly using the 16.16 format.
>
> [code]
> .section L1_data_a;
> .byte4 _x[2]={0x360000,0x22};
> .byte4 _val[12]={0xb1721,0x58b91,0x2c5c8,0x162e4,0x0b172,0x067cd,0x03920,0x01e27,0x00f85,0x007e1,0x003f8,0x001fe};
> .section L1_code;
> .global _log;
>
> _log:
>
> I0.h=_val;
> I0.l=_val;
> //I0;
> //L0H;
> I3.H=_x;//variable x
> I3.L=_x;
> //***initialisation des registres***
>
> R0.l= 0x65AF ; //y0=0xa65af
> R0.h=0xA ;
>
> R1.l=0x8000 ;// lim1 de x
> R1.H=0x0;
>
> R2.H=0x80 ; //lim2 de x
> R2.L=0x0;
>
> R3.H=0x800 ;//lim3 de x
> R3.L=0x0;
>
> R4.H=0x2000 ;//lim4 de x
> R4.L=0x0;
>
> R5.H=0x4000 ;//lim5 de x
> R5.L=0x0;
> R6=[I3++];//charger la valeur de x de 32 bits
>
> R7=[I0++];//charger la valeur ln(x) qu'on va soustraire de y
>
> cc=R6 >
> if !cc jump _case2;
>
> R6=R6<<16;
>
> R0=R0-R7 (ns); //R7 contient la valeur de y
>
> _case2:
>
> cc=R6 > if !cc jump _case3;
>
> R6=R6<<8;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _case3:
> cc=R6 > if !cc jump _case4;
>
> R6=R6<<4;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _case4:
>
> cc=R6 > if !cc jump _case5;
>
> R6=R6<<2;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _case5:
>
> cc=R6 > if !cc jump _rest;
>
> R6=R6<<1;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _rest:
>
> nop;
>
> R1=R6>>1;//x>>1
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op2;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
> _op2:
>
> R1=R6>>2;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op3;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op3:
> R1=R6>>3;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op4;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op4:
> R1=R6>>4;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op5;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op5:
> R1=R6>>5;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op6;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op6:
> R1=R6>>6;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op7;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op7:
> R1=R6>>7;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _linearisation;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _linearisation:
> nop;
> R4.H=0x8000 ;//0x800000000 dans R4
> R4.L=0x0;
>
> R6=R4-R6 (ns);
> R6=R6>>15;
> R0=R0-R6 (ns);
>
> rts;
> _log.end:
> [\code]
>
> The results are not those expected.Please help me
>
> Sincerely,
> syrine
Syrine,

You forgot to post the link to the original C code, which seem to be found at
this address:

http://www.quinapalus.com/efunc.html

I tried to test it, I mean the C code; and it seem to be working as expected:

For 65536, which is 1.0 in Q32.16, it returns 0, and for 178,145, which is
the Euler's number in Q32.16, it returns 65537 - pretty close to 1.0 in Q32.16.

You use index register I0 to load the y constants that are stored into an
array; that means that your code loads them _sequentially_, but now imagine
that your code jumps after an appropriate cc has been computed, what would
happen than?

Correct; not the value that is needed for the step after the jump; on the
contrary, a value that _was_ needed on the _previous_ step (provided that there
were no jump) would be loaded. You have to correct the way your code processes
these constants.

Rgds,

Andrew

> Subject: problem with log( ) implementation
> Posted by: "Safa Ouerghi" s...@yahoo.com safa.ouerghi
> Date: Wed Nov 16, 2011 5:55 am ((PST))
>
> Good morning,
> I'm trying to implement the function log() on a DSP blackfin using the
> assembly language. I found this C code:
> [code]
> int fxlog(int x) {
> int t,y;
>
> y=0xa65af;
> if(x<0x00008000) x<<, y-=0xb1721;
> if(x<0x00800000) x<<= 8, y-=0x58b91;
> if(x<0x08000000) x<<= 4, y-=0x2c5c8;
> if(x<0x20000000) x<<= 2, y-=0x162e4;
> if(x<0x40000000) x<<= 1, y-=0x0b172;
> t=x+(x>>1); if((t&0x80000000)==0) x=t,y-=0x067cd;
> t=x+(x>>2); if((t&0x80000000)==0) x=t,y-=0x03920;
> t=x+(x>>3); if((t&0x80000000)==0) x=t,y-=0x01e27;
> t=x+(x>>4); if((t&0x80000000)==0) x=t,y-=0x00f85;
> t=x+(x>>5); if((t&0x80000000)==0) x=t,y-=0x007e1;
> t=x+(x>>6); if((t&0x80000000)==0) x=t,y-=0x003f8;
> t=x+(x>>7); if((t&0x80000000)==0) x=t,y-=0x001fe;
> x=0x80000000-x;
> y-=x>>15;
> return y;
> }
> [\code]
>
> so i tried to convert it to assembly using the 16.16 format.
>
> [code]
> .section L1_data_a;
> .byte4 _x[2]={0x360000,0x22};
> .byte4 _val[12]={0xb1721,0x58b91,0x2c5c8,0x162e4,0x0b172,0x067cd,0x03920,0x01e27,0x00f85,0x007e1,0x003f8,0x001fe};
> .section L1_code;
> .global _log;
>
> _log:
>
> I0.h=_val;
> I0.l=_val;
> //I0;
> //L0H;
> I3.H=_x;//variable x
> I3.L=_x;
> //***initialisation des registres***
>
> R0.l= 0x65AF ; //y0=0xa65af
> R0.h=0xA ;
>
> R1.l=0x8000 ;// lim1 de x
> R1.H=0x0;
>
> R2.H=0x80 ; //lim2 de x
> R2.L=0x0;
>
> R3.H=0x800 ;//lim3 de x
> R3.L=0x0;
>
> R4.H=0x2000 ;//lim4 de x
> R4.L=0x0;
>
> R5.H=0x4000 ;//lim5 de x
> R5.L=0x0;
> R6=[I3++];//charger la valeur de x de 32 bits
>
> R7=[I0++];//charger la valeur ln(x) qu'on va soustraire de y
>
> cc=R6 >
> if !cc jump _case2;
>
> R6=R6<<16;
>
> R0=R0-R7 (ns); //R7 contient la valeur de y
>
> _case2:
>
> cc=R6 > if !cc jump _case3;
>
> R6=R6<<8;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _case3:
>
> cc=R6 > if !cc jump _case4;
>
> R6=R6<<4;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _case4:
>
> cc=R6 > if !cc jump _case5;
>
> R6=R6<<2;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _case5:
>
> cc=R6 > if !cc jump _rest;
>
> R6=R6<<1;
>
> R7=[I0++];
>
> R0=R0-R7(ns); //R7 contient la valeur de y
>
> _rest:
>
> nop;
>
> R1=R6>>1;//x>>1
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op2;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
> _op2:
>
> R1=R6>>2;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op3;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op3:
> R1=R6>>3;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op4;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op4:
> R1=R6>>4;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op5;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op5:
> R1=R6>>5;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op6;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op6:
> R1=R6>>6;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _op7;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _op7:
> R1=R6>>7;
> R2=R1+R6; //valeur de t dans R2
> cc=BITTST(R2,31);
> if cc jump _linearisation;
> R6=R2;
> R7=[I0++];
> R0=R0-R7 (ns);
>
> _linearisation:
> nop;
> R4.H=0x8000 ;//0x800000000 dans R4
> R4.L=0x0;
>
> R6=R4-R6 (ns);
> R6=R6>>15;
> R0=R0-R6 (ns);
>
> rts;
> _log.end:
> [\code]
>
> The results are not those expected.Please help me
>
> Sincerely,
> syrine
>