The
CDSPk2
Processor
Register model, hardware accelerator, and
instruction set


Register Model:
The CDSPk2 is a derivative of the CDSP family's basic architecture.
Following is an architectural description applicable to the CDSPk2
customization option.
The r0, r1, r2 and r3 registers are 2x32 bits wide, accommodating
32bit fixed point complex numbers. Each of the two fixed point real
numbers composing the complex number is represented in two's complement
format with 1 bit allocated for the sign and 31 bits for the fractional
part (see the number format Appendix for more details). In most cases,
arithmetic operations inside the CDSP are performed in complex numbers
format; however there are some nononsense exceptions when the contents
of these registers is interpreted as an integer number by discarding
the imaginary part and considering the real part as a 32bit integer
instead of a fixed point number (one such case is when using a register
as a loop counter).
The r4, r5, r6, and r7 registers are data ports for the integrated
Butterfly/MAC unit; they are all 32bit fixed point complex registers.
The "psr" register is the processor status register; it is 32 bits wide
(see following sections).
The "dsr" register is a special 32bit dynamic shift amount register
(see following sections).
Index register x0 is the DataROM pointer; it is 13 bits wide (for 8KW
DataROM).
Index registers x1, x2, and x3 are the RAM pointers; they are 13 bits
wide (for 8KW offset addresses).
Index base registers b0, b1, b2, and b3, limit registers L0, L1, L2,
and L3, and increment registers n0, n1, n2, and n3 are used by the
various indexed addressing modes; they have the same width as their
corresponding DataROM/RAM index registers (see following sections).
The bar (base address register) is used in the biased addressing modes
(see following sections). It is 16 bits wide (for a 64KW RAM).
The pcr (program counter register) is the instruction pointer. It is 14
bits wide (for 16KW CodeROM).
The rsr (return from subroutine register) holds the return address of
the last subroutine call; it is the programmer's responsibility to save
it (stack it) if nested calls are needed. It has the width of the pcr.
Ports p and q are the processor communication ports; each port is
implemented as a pair of unidirectional data paths, one for data input
and one for data output, i.e. the processor actually hosts a pin, a
pout, a qin, and a qout port. Each of these ports is 32 bits wide.
Port k is the control and synchronization port (it's also implemented
as a pair of unidirectional data paths). It logically groups together a
number of processor status and control bits.
Figure 1: CDSPk2 Registers (Programming Model)
Addressing Modes:
The instruction set is based on the twooperand model, one of them residing in a processor register, and the other residing in memory: RAM or DataROM (the CodeROM cannot be accessed as data). Most of the twooperand instructions follow this model, while most of the oneoperand instructions operate on the internal registers only. These rules generate a highly orthogonal instruction set; however, some specialpurpose instructions make exception from these rules (see following sections).
Following is a detailed description of the various addressing modes, accompanied by a number of relevant assembler examples.
Implied addressing:
This mode is used by instructions that either have no operand, or the
operand is implicitly specified by the instruction itself. Although the
basic processor instruction set only uses this mode for the "nop" and
"brk" control instruction, it is a useful option when implementing
applicationspecific instructions.
Assembler syntax example:
nop; no operation (dummy instruction)
Direct addressing:
This mode specifies the data to be accessed by an instruction via its
address embedded in the instruction code. Both RAM and DataROM can be
accessed via this addressing mode. Depending on the operand type, the
assembler generates the correct instruction code format (RAM/DataROM
reference).
Assembler syntax example:
.cst k0: 123; declare a constant, allocate a DataROM address for it, and define it as being 123
.var v0; declare a variable and allocate a RAM address for it.
lda r0,k0; r0 will be loaded with 123 (the k0 constant's address is supplied in the opcode)
lda r1,v0; r1 will be loaded with v0 (the contents of the RAM location where v0 is allocated)
Remark:
The processor doesn't support in hardware the usual "immediate"
addressing mode; the assembler is responsible for converting the usual
assembler syntax specifying the immediate addressing mode into the
processor's DataROM direct addressing mode (a DataROM access is
inferred from the "immediate" mode):
lda r0,0.12:0.34 ;r0 will be loaded with the complex number 0.12+i*0.34
;The assembler actually allocates an address in the DataROM,
;places the 0.12+i*0.34 complex constant in that location,
;and includes its address in the opcode.
Indexed addressing:
This mode specifies the data to be accessed by an instruction via its
address held in an index register. Both RAM and DataROM can be accessed
via this addressing mode. Depending on which index register is used to
point to the data, either the RAM or the DataROM is targeted.
Assembler syntax example:
lda r0,@x0; the DataROM location pointed by x0 is loaded into r0: r0 = DataROM[x0]
lda r1,@x1; the RAM location pointed by x1 is loaded into r1: r1 = RAM[x1]
Remark:
The index addressing mode is complemented with a number of related
features designed to enhance data access on typical DSP applications
(see following sections).
Indexed addressing variations:
The four index registers are featured with the following addressing
modes options:
Index register x0 DataROM pointer is featured with
postincrement and postdecrement options. Register n0 is used as a
signed variable increment/decrement. Wraparound functionality is
provided. The following wrapping algorithm is used: first the data is
accessed via the postincrement or postdecrement mode; then the x0
index register is compared with the L0 limit register: if the values
match the index register is initialized with the b0 base register, else
it is incremented/decremented with the signed number in the increment
register n0.
Index registers x1, x2 and x3 RAM pointers are featured with the
postincrement, postdecrement, and bitreversed addressing modes.
Wraparound functionality is provided for the postincrement and
postdecrement modes by means of the related base (b2, b3) and limit
(L2, L3) registers; the wrapping algorithm is the same as described for
the x0 index register.
The bitreversed mode updates the index registers (x) using the
corresponding increment (n) and limit registers (L) according to the
following algorithm: first (n)'s bitreversed representation is added
to (x)'s bitreversed representation, and the carry of this addition is
memorized (CY); then the result of this addition is bitreversed back
to the proper order and loaded into (x); finally, if there was a carry
(CY) then the corresponding limit register (L) is added to the index
register (x) in order to provide the final result.
Assembler syntax example:
lda r0,@x0+ ;r0 = DataROM[x0], x0 = (x0 == L0 ? b0 : x0+=n0);
lda r1,@x1 ;r1 = RAM[x1], x1 = (x1 == L1 ? b1 : x1=n1);
lda r2,@x2* ;r2 = RAM[x2], x2 = BitRev(BRSum=BitRev(x2)+BitRev(n2)), x2+=CY(BRSum)?L2:0;
Remark 1:
The relation between the index registers' limit (L) and base (b)
corresponding registers depends on the sign of the increment: it is up
to the programmer to ensure that for a positive increment L>b, while
for a negative increment L<b (here the increment stands for the
resulting amount by which the index register is updated, i.e. for a
negative "n" register and a postdecrement option, the resulting
increment is a positive number).
Remark 2:
The index registers have an associated "scan address space" when used
with the postincrement or postdecrement addressing modes, as defined
by their associated base (b) and limit (L) registers. Because the x
index registers are only checked for equality against their
corresponding limit register L in order to provide them with
wraparound functionality, they will not wrap back to their base
address b if they pass over their limit address L without hitting it.
In order to guarantee that the wraparound will consistently take
place, it is necessary to have (Lb) a multiple of the x index
registers' increment n, and x must be initialized with b. For example,
a valid configuration will be x3InitialValue=b3=10, n3=3, L3=22; this
will result in the following address space: {10, 13, 16, 19, 22}.
Biased addressing:
The bar register is a special purpose pointer that can be used to bias
both direct and indexed addressing modes, but only in conjunction with
RAM accessing (DataROM accesses cannot be biased). All the previously
discussed RAM addressing modes (and variations) have both the biased
and nonbiased options.
Biased direct addressing mode:
When the bar register is used in conjunction with direct addressing,
the address supplied in the opcode is used as an offset (relative to
the bar) for accessing the data. This allows for a small addressfield
in the operation code, while still enabling access to a large address
space by using a wide bar register. The address offset is interpreted a
signed number that is added to the bar register in order to provide the
final data address.
Assembler syntax example:
.var @10 v10 ;declare a variable by specifying it's address to be 10 (RAM location).
lda r1,bar:v10 ;r1 = RAM[bar+10] // (v0 is interpreted as an offset; it can be seen as a local variable).
Biased indexed addressing mode:
When the bar register is used in conjunction with the index addressing
modes, the address held in the index registers is used as an offset
(relative to the bar) when accessing the data. The index register is
interpreted as a signed number that is added to the bar register in
order to provide the final data address.
Assembler syntax example:
ldx.ptr x1,10 ;load index register x1 with 10.
ldx.ptr x2,20 ;load index register x2 with 20.
lda r1,@bar:x1 ;load memory location RAM[bar+10] into r1.
lda r2,@bar:x2+ ;load memory location RAM[bar+20] into r2, then update x2.
Indirect addressing:
This is not a true addressing mode, but rather an addressing mode
modifier: a small group of instructions interpret their operand as the
address of the data they need to access. This modifier applies only to
the RAM addressing modes (direct and index variations, both biased and
unbiased). It is a convenient way of reducing the number of bits that
are required to provide a branch target address (by specifying a RAM
location that contains the branch address instead of specifying the
CodeROM address itself). This scheme also allows for calculatedaddress
branches, and makes possible the creation of returnaddress stacks in
RAM.
Assembler syntax example:
.var VariableBranchAddr ; a number representing a CodeROM addr has to be placed in this var.
bri @VariableBranchAddr ; the branch's CodeROM target address is now taken from this variable.
Instruction Set:
Table 1 lists the CDSPk2 instruction set, together with the addressing modes applicable to each instruction.
Notations used in the instruction set table:
r  complex general purpose registers (r0  r3) and the registermapped
Butterfly/MAC unit (r4  r7)
x  index registers (x0  x3)
p  communication ports (the assembler names for the p and q DSP ports
are p0 and respectively p1)
t  memory operand, using any of the available addressing modes
(immediate, direct, indexed variations)
j  jump (and subroutine call) CodeROM address
N  immediate addressing mode (this is a pseudo addressing mode; the
assembler converts it to direct mode)
R  register operand
D  direct addressing mode
X index addressing mode (and the index variations)
J  jump (and subroutine calls) CodeROM addressing mode
Instruction Name  Mnemonic  Description  Addr. Modes  Remarks 
No Operation  nop  pcr++   X   
Logic AND  and r,t  Re[r] &= Re[t], Im[r] &= Im[t]; pcr++  N D X  1 
Logic Inclusive OR  ior r,t  Re[r] = Re[t], Im[r] = Im[t]; pcr++  N D X  1 
Logic Exclusive OR  xor r,t  Re[r] ^= Re[t], Im[r] ^= Im[t]; pcr++  N D X  1 
Addition  add r,t  r += t; pcr++  N D X  2 
Subtraction  sub r,t  r = t; pcr++  N D X  2 
Reverse Subtraction  sbx r,t  r = tr; pcr++  N D X  3 
Load dsr Dynamic Shift Register  lds.dsr t  dsr = Re[t], pcr++  N D X  4 
Dynamic Shift Left Arithmetic Reg  sla.dyn r,r  Re[r] <<<= dsr, Im[r] <<<= dsr; pcr++  R  4,5 
Dynamic Shift Left Arithmetic Location  sla.dyn r,t  Re[r] = Re[t] <<< dsr, Im[r] = Im[t] <<< dsr; pcr++  D X  4,5 
Shift Left Logic Register  sll.n r,r  Re[r] <<= n, Im[r] <<= n; pcr++ // n=1,2  R  2,5 
Shift Left Logic Location  sll.n r,t  Re[r] = Re[t] << n, Im[r] = Im[t] << n; pcr++  D X  2,5 
Shift Right Logic Register  srl.n r,r  Re[r] >>= n, Im[r] >>= n; pcr++  R  5 
Shift Right Logic Location  srl.n r,t  Re[r] = Re[t] >> n, Im[r] = Im[t] >> n; pcr++  D X  5 
Shift Right Arithmetic Register  sra.n r,r  Re[r] >>>= n, Im[r] >>>= n; pcr++  R  5 
Shift Right Arithmetic Location  sra.n r,t  Re[r] = Re[t]>>>n, Im[r] = Im[t]>>>n; pcr++  D X  5 
Swap Im with Re Register  sir r,r  Re[r] <> Im[r]; pcr++  R   
Swap Im with Re Location  sir r,t  Re[r] = Im[t], Im[r] = Re[t]; pcr++  D X   
Load Accumulator  lda r,t  r = t; pcr++  N D X   
Store Accumulator  sta r t  t = r; pcr++  D X   
Load Processor Status Register  lds.psr t  psr = t; pcr++  N D X  6 
Store Processor Status Register  sts.psr t  t = psr; pcr++  N D X  6 
Test if Equal  teq r,t  Cmpf &= (r == t); pcr++ // Internal flag  N D X  7 
Test if Not Equal  tne r,t  Cmpf &= (r != t); pcr++  N D X  7 
Test if Greater  tgr r,t  Cmpf &= (Re[r] > Re[t]); pcr++  N D X  7 
Test if Greater or Equal  tge r,t  Cmpf &= (Re[r]>= Re[t]); pcr++  N D X  7 
Test if Smaller  tsm r,t  Cmpf &= (Re[r] < Re[t]); pcr++  N D X  7 
Test if Smaller or Equal  tse r,t  Cmpf &= (Re[r] <= Re[t]); pcr++  N D X  7 
Test by Bitwise AND  tbw r,t  Cmpf &= Bool(r & t); pcr++  N D X  7,8 
Branch if True  brt j  Cmpf ? pcr = j : pcr++  J  9 
Branch if False  brf j  Cmpf ? pcr++ : pcr = j  J  9 
Branch Always  bra j  pcr = j  J   
Branch Indirect  bri @t  pcr = RAM[t]  D X  10 
Cycle  cyc r,@t  Re[r] , Im[r] , Re[r] ? pcr = RAM[t] : pcr++  D X  11 
Hardware Repeat  rpt r,@t  D x  12  
Jump to Subroutine  jsr j  rsr = ++pcr; pcr = j  J  13 
Store rsr register  sts.rsr t  t = rsr; pcr++  D X   
Load bar register  lds.bar t  bar = t; pcr++  N D X   
Store bar register  sts.bar t  t = bar; pcr++  D X   
Add to bar register  add.bar t  bar += t; pcr++  N D X  14 
Load comm output port  lds.com p,t  pout = t; pcr++  N D X  15 
Store comm input port  sts.com p,t  t = pin; pcr++  D X  15 
Load control output port  ctl t  kout = t; pcr++  N D X  15 
Hardware Directed Break  brk    16  
Wait for Condition  wai t  N D X  17  
Register transfer to index pointer  xfr.ptr x,r  x.ptr = Re[r]; pcr++  R  18 
Load index pointer  ldx.ptr x,t  x.ptr = Re[t]; pcr++  N D X  19 
Store index pointer  stx.ptr x t  Re[t] = x.ptr; pcr++  D X  19 
Load index increment  ldx.inc x,t  x.inc = Re[t]; pcr++  N D X  19 
Load index base  ldx.bas x,t  x.bas = Re[t]; pcr++  N D X  19 
Load index limit  ldx.lim x,t  x.lim = Re[t]; pcr++  N D X  19 
Writeback buffer flush  fls.wbb    20 
Table 1: CDSPk2 instruction set
The assembly numbers' format
The number formats that the assembler recognizes are based on the
fixedpoint representation and on the integer representation of binary
numbers.
Since fixedpoint representation is restricted to the [1,1) interval,
and the integer number representation is overlapping with this interval
on "1", the assembler cannot make the distinction between integer and
fractional representation for the 1 special case.
The following convention is introduced: all decimal integer numbers
(1, 0, and +1 included) will be considered to be to be 32bit wide
integers (signed or unsigned), while all fractional numbers within the
(1,+1) open interval (without 0) will be considered to be 32bit wide
signed fixed point numbers. The 0 (zero) special case does not require
special treatment because it has the same representation for both
fixedpoint and integer numbers. The assembler issues error messages if
a fractional number is outside the (1,1) open interval, thus not
allowing to use the "1" special case as a fractional number.
Fixedpoint 1.0 can be used in the source file by writing its explicit
binary representation (i.e. 0x80000000 for 32bit fixed point numbers).
Positive integers may be represented using hexadecimal notation.
Hexadecimal numbers will always be coded as 32bit unsigned integers.
Complex numbers are written as a colonseparated pair of fixedpoint or
integer numbers (no type mixing).
Assembler example
lda r0,1.0 ; 1.0 will be coded as integer: 0xFFFFFFFF, and NOT as a fixedpoint number
lda r0,1 ; load real part of r0 with 0xFFFFFFFF and the imaginary part with 0x00000000
lda r0,256 ; load real part of r0 with 0x00000100 and the imaginary part with 0x00000000
lda r1,0x100:0x10 ; load real part of r0 with 0x00000100 and the imaginary part with 0x00000010
lda r2,0.5 ; load real part of r0 with 0x40000000 and the imaginary part with 0x00000000
lda r3,0.5:0.25 ; load real part of r0 with 0x40000 000and the imaginary part with 0x20000000
Some instructions need to reinterpret their arguments' type. For
example, a complex processor register will have to be interpreted as
integer when used as a loop counter in a looping instruction; also, an
integer index register will have to be stored in a complex
representation in the complex memory area.
Deriving an integer number from a fixedpoint complex number (for
example when using a complex register as a loop counter) is
accomplished by first neglecting the imaginary part of the complex
number, and then interpreting the bits in the real part of the number
in a straightforward way as an integer number: the sign bit becomes
the integer's MSB, and the fixedpoint number's LSB becomes the
integer's LSB. This way of interpreting a complex operand as an integer
is common to all the instructions that need to derive integer arguments
(both signed and unsigned) from complex numbers.
When a complex representation has to be derived from an integer number
(for example when storing integer pointer registers into memory), the
reverse approach is taken: the bits of the integer number are
signextended, then they are interpreted in a straightforward way as a
fixedpoint, 1 sign bit number; the resulting fixed point number is
considered to be the real part of a complex number for which the
imaginary part is zero. (for example, if one stores index register x1=1
into the complex RAM area, a complex number having the imaginary part
zero and the real part with only the LSB set to 1 is actually stored).
Table 1 Remarks:
and r0, INT64_High:INT64_Low
sbx r0,0
[NonTestInstruction]
tge r0,0.1
tse r0,0.2
brt ValueIsIn01to02
ValueIsOutside01to02:
[r0 < 0.1 or r0 > 0.2]
bra Continue
ValueIsIn01to02:
[0.1 <= r0 <= 0.2]
Continue:
[NonTestInstruction]
tbw r0,1
brt Bit_b0_of_r0_set
Bit_b0_of_r0_reset:
[...]
bra Continue
Bit_b0_of_r0_set:
[...]
Continue:
SubrStart:
.var TMP_ReturnAddress
sts.rsr TMP_ReturnAddress
[SubroutineBody]
bri @TMP_ReturnAddress
.var TMP_LoopingAddress
lda r2,&Loop
sta r2 TMP_LoopingAddress
lda r2,LoopCount
Loop:
[LoopBody]
cyc r2,@TMP_LoopingAddress
.var TMP_LoopEndingAddressFollowing is a description of some special "rpt" cases: singleinstruction "rpt" loops are allowed; branch instructions are allowed in the oneinstruction slot following the "rpt" instruction, and they are allowed to target both an outside loop address and an inner loop address (including the last loop instruction); if the last instruction in a loop is a branch or "jsr", it will be executed and the loop counter decremented; in the case of "jsr" the saved return address (in the "rsr" register) is the "next" program address to be executed: either the beginning of the loop, or the instruction following "jsr", depending on whether the loop has ended or not (i.e. depending on the value of the loop counter).
lda r2, &LoopEndingAddress
sta r2 TMP_LoopEndingAddress
lda r2 RepeatCount
add r2 1
rpt r2 @TMP_LoopEndingAddress
nop
LoopStartAddress:
[FirstInstructionInTheLoop]
[...]
LoopEndingAddress:
[LastInstructionInTheLoop]
.var Stack[StackSize]
ldx.inc x1,1
ldx.ptr x1, &Stack
jsr SubrEntry
[RestOfTheProgram]
SubrEntry:
sts.rsr @x1+
[SubroutineBody]
nop @x1
bri @x1
wai INT_ControlPortCondition
ConditionMet:
The Butterfly/MAC module
Figure 2: Butterfly/MAC Module Block Diagram
Porocessor Status Register (PSR)
b1,b0  select the functionality of the "s" adder: 0:s1+s2, 1:s1s2, 2:s2s1  
b3,b2  select the functionality of the "d" adder: 0:d1+d2, 1:d1d2, 2:d2d1  
b5,b4  select the "a" multiplexor output: 0:<zero>, 1:r4, 2:s3  
b7,b6  select the "b" multiplexor output: 0:<zero>, 1:r4, 2:s3  
b8  select the output shift amount for the "s" and "d" adders: 0:no shift, 1:shift right by 1  
b9  enables rounding logic in the "s" and "d" adders  
b10  enable automatic loading of r4 with the values that are loaded into r5  
b12,b11  select the action that will be triggered by the loading of r7 with a value: 0:no action, 1: load r6 with the same value as r7, 2: if r7 was loaded via an index addressing mode then load r6 from DataROM via @x0+ indexed addressing, else r6 will become undefined; also, loading register r7 with a value always triggers automatic loading (updating) of the internal MAC "a", "b", "q" ,"r" and "L" registers  
b14,b13  select the complex multiplier operation: 0:r6*r7, 1:Conjugate(r6)*r7, 2:r6*Conjugate(r7), 3:Re(r6)*Re(r7), Im(r6)*Im(r7) 

b16,b15  select the multiplier output scaler: the scaling factors are subject to customization  
b17  select the r4_out and r5_out multiplexors' output: 0:r4_in/r5_in, 1:q/r  
b18  select the r6_out and r7_out multiplexors' output: 0:r6_in/r7_in 1:multiplier's output  
b19  select the MAC muxL multiplexor output; 0:r6_in, 1:L register  
b20  by writing a "1" into this bit the a, b, q, r, and L internal registers are cleared, and also the MACsaturationaccumulation and s3ord3bignumbersaccumulation status bits are cleared; this bit is always read as 0  
b21  enable ALU saturation functionality associated with the add, sub, sbx, sll instructions  
b23  DataRAM writeback buffer empty flag bit.  
b24,b25  real and imaginary s3ord3bignumberaccumulation flags. These bits are reactualized whenever r7 is loaded with a value: they are set when the s3 or d3 outputs (the real and imaginary parts respectively) are outside the [0.5,0.5) fixedpoint interval, and they are reset via psr bit b20. Thus these bits behave as accumulator bits.  
b29,b28  real and imaginary part MACsaturationaccumulation flags; these flags are readonly bits, and they accumulate the MACsaturationoccurred condition each time r7 is loaded with a value  
b31,b30  ALU real and imaginary part saturation flags; these flag bits are readonly, and are set/reset by the ALU after some arithmetic operations 
Butterfly/MAC Remarks
FFT Inner Loop Assembler Example
The key element in performing the FFT algorithm is repetitive butterfly calculation. The following example assumes a maximum 3stage pipelined multiplier and singlecycle "s" and "d" modules. The x2 and x3 index registers are assumed to be programmed in bitreverse operation mode, and x0 ConstantsROM pointer is assumed to fetch the twiddle factors in the necessary order; the psr is assumed to be programmed for FFT operation (i.e. b10 set and b12b11 set to mode 2, see psr bits); also, the x2 pointer is assumed to point onestep behind x3 (inside each loop it is used to store the previous butterfly calculation results).
lda r5,@x3*; r4in <= Ram[x3], r5in <= Ram[x3], // load the first of the butterfly input data
x3 <= BitReverseInc(x3); // and move the x3 pointer to next input data
lda r7,@x3*; a <= r4in, b <= r5in // load a and b registers from r4 and r5 inputs
q <= s3, r <= d3, // save the previous step's calculation results
r6in <= DataRom[x0], r7in <= Ram[x3], // load the second of the butterfly input data
// and the butterfly coefficient
x0++, x3 <= BitReverseInc(x3); // move x0 to next coef and x3 to next input
sta r4, @x2*; Ram[x2] <= r4out, x2 <= BitReverseInc(x2); // store the saved previous calculation's
sta r5, @x2*; Ram[x2] <= r5out, x2 <= BitReverseInc(x2); // results (x2 pointer is one step behind x3)
Memory Model:
The memory model plays an essential role in the CDSP functionality. Since the processor makes no distinction between integer and fixedpoint complex number words, it is only the memory organization that permits transparent usage of all instructions with both data types: the linear addressing space of both RAM and DataROM is divided in two separate regions, one for fixedpoint complex numbers, and one for integer numbers. (each of these two regions can be further divided into a simple precision area and an extended precision area if needed). The functionality of these regions is defined as follows.
The Extended Precision Memory
Since the processor uses internally the extended precision representation for numbers, the operations on extended precision memory areas will not generate precisionrelated problems. The extendedprecision, integer to complex and complex to integer conversions obey the following guidelines:
For both RAM and DataROM, when an 32bit integer number word is read by a complex operand(s) instruction, the binary pattern of the integer word is copied in the real part of the complex operand (and will be interpreted according to the fixedpoint representation of signed numbers), while the imaginary part of the complex operand is generated adhoc as zero.
Assembler example:
.var @IntegerArea IntVar ; declare IntVar inside the integer numbers RAM area
lda r0,IntVar ; the IntVar is loaded in the real part of r0 and will be interpreted as a
; fixedpoint number; the imaginary part is loaded with zero.
For RAM writes, when a fixedpoint complex number word is stored in the integer RAM area, its imaginary part is discarded and its real part is stored in RAM; the bit pattern of its real part will be interpreted as a 32bit integer real number.
Assembler example:
.var @IntegerArea IntVar ; declare IntVar inside the integer numbers RAM area
sta r0 IntVar ; the imaginary part of r0 is discarded and the fixedpoint real part of r0
; that is stored in memory will be interpreted as an integer number.
For both RAM read/write and DataROM read accesses, when an integer memory word is accessed by an integer operand(s) instruction, the word is used by the instruction asis; also, when a fixedpoint complex memory word is accessed by a fixedpoint complex operand(s) instruction, the word is used by the instruction asis.
The Simple Precision Memory
If simpleprecision memory areas are needed, there will be a precision loss when converting an extended precision number to simple precision (because the conversion will simply eliminate the least significant bits from the original extended precision number).
Remark
Because this conversion keeps the most significant bits of the numbers,
it only works on the fixedpoint representation; it cannot be applied
to binary numbers that represent integers (there is no trivial way to
store a number held in a register and that is representing an integer
into a simle precision memory area, because this operation would loose
the least significant bits of the integer number).