Assembly Language Core for Xojo

Xojo does in fact have a goto instruction and labels. I used this to advantage when I coded a PIC microcontroller emulator. Similar to what you have done, all of the PIC instruction codes were coded as Xojo methods. This allowed the writing of PIC assembly language code directly in the Xojo code editor and then running it. There’s a short description of the project, which I submitted in the summer 2018 Just Code Challenge. Here’s a link, and it has a link for downloading the project.

Here is example assembly code that makes use of Xojo’s goto instruction and labels:

  'Volder's CORDIC rectangular to polar routine in PIC assembly language.
  'It is assumed that inputs are 12 bit positive integers 0..4095.
  'Hence the vector is in the first quadrant.
  
  
  'The following XOJO housekeeping code sets up the various PIC registers.
  dim xH,xL,yH,yL,angleH,angleL,index,count,tL,tH,vL,vH,kScale As UInt8
  'dim deltaSum As Double
  'Lookup table values with angles in degrees. Tables probably have more entries than necessary for 16 bit resolution
  dim LU_AngleInt() As Integer = array(26,14,7,3,1,0,0,0,0,0,0,0,0,0)
  dim LU_AngleFrac() As Integer = Array(144,9,32,147,202,229,114,57,28,14,7,4,2,1)
  
  
  dim nTable As UInt8 = UBound(LU_AngleFrac)
  
  'Initialize x and y variables
  xH=x\256 'High byte of x coordinate
  xL=x mod 256 'Low byte of x coordinate
  yH=y\256 'High byte of y coordinate
  yL=y mod 256 'Low byte of y coordinate
  
  '*************************************
  
  'Start of ASM code
  
  'CORDIC ATAN2 function
  '
  'On entry, the 12 bit (0..4095) values of x and y should be in xL,xH,yL,yH
  'The upper 4 bits of xH and yH must be Zero.
  'On completion, the angle (in degrees) is in AngleH and AngleL
  'The integer part is in AngleH, and the fractional part is in AngleL
  'The radius (magnitude) is in yH,yL (integer), and xH (fraction).
  
  
  clrf angleH
  clrf angleL
  'Check for all Zero input combinations
  movf xL,w
  iorwf xH,w
  iorwf yL,w
  iorwf yH,w
  btfsc status,z
  if noSkip then Return 999 'This is an error code indicating that both x an y are zero
  'check if y=0
  movf yH,w
  iorwf yL,w
  btfsc status,z
  if noSkip then Return 0 'Angle is zero if y=0
  'check for x=0
  movlw 90
  movwf angleH
  movf xH,w
  iorwf xL,w
  btfsc status,z
  if noSkip then Return 90 'Angle is 90 degrees if x=0
  movlw 45
  movwf angleH
  
  ' Scale up x and y to improve resolution
  movlw 15
  movwf kScale
  
  ScaleXY:
  
  decf kScale,f
  clc
  rlf xL,f 'shift xH and yH left
  rlf xH,f
  clc
  rlf yL,f
  rlf yH,f
  movf xH,w
  iorwf yH,w
  andlw &hF0
  btfsc status,z
  if noSkip then goto ScaleXY
  
  'xH and yH are now normalized
  'initialize calc loop
  'calc x and y initial values
  'save old x, as it will be overwritten
  movf xH,w 
  movwf vH
  movf xL,w
  movwf vL
  'calc x=x+y
  addwf yL,w 
  movwf xL
  btfsc status,c
  incf xH,f
  movf yH,w
  addwf xH,f
  'calc y=y-x
  movf vL,w
  subwf yL,f 
  btfss status,c
  decf yH,f
  movf vH,w
  subwf yH,f
  clrf index 'Loop counter and lookup table index
  
  MainLoop:
  
  'shift x and y values
  movf index,w
  movwf count
  'calc x y shift
  movf yH,w
  movwf tH
  movf yL,w
  movwf tL
  movf xH,w
  movwf vH
  movf xL,w
  movwf vL
  btfss yH,7 'check for negative y
  if noSkip then goto ShiftLoop
  comf tH,f
  comf tL,f
  incf tL,f
  btfsc status,z
  incf tH,f
  
  ShiftLoop:
  
  clc
  rrf vH,f
  rrf vL,f
  clc
  rrf tH,f
  rrf tL,f
  clc
  decfsz count,f
  if noSkip then goto ShiftLoop
  
  'calc new xH and yH
  btfsc yH,7
  if noSkip then goto NewXYcalc
  'y=y+/-yH>>index
  comf vH,f
  comf vL,f
  incf vL,f
  btfsc status,z
  incf vH,f
  
  NewXYcalc:
  
  movf vL,w
  addwf yL,f
  btfsc status,c
  incf yH,f
  movf vH,w
  addwf yH,f
  'x=x+y>>index
  movf tL,w
  addwf xL,f 
  btfsc status,c
  incf xH,f
  movf tH,w
  addwf xH,f
  ' Sum Angle from lookup table
  movf index,w
  call_Lkp LU_AngleFrac
  movwf tL
  movf index,w
  call_Lkp LU_AngleInt
  movwf tH
  btfss yH,7
  if noSkip then goto AddSum
  comf tH,f
  comf tL,f
  incf tL,f
  btfsc status,z
  incf tH,f
  
  AddSum:
  
  movf tL,w
  addwf angleL,f
  btfsc status,c
  incf angleH,f
  movf tH,w
  addwf angleH,f
  'if result is Zero, then we are done
  incf index,f
  movlw nTable+1
  subwf index,w
  btfss status,z
  if noSkip then goto MainLoop
  '
  'The result of the preceding steps is to rotate the vector to the x axis. The rotated angle
  'is the required polar angle, and the final x value is proportional to the required magnitude.
  'The magnitude will be high by a factor of 1.6467743... which is the product of the cosine values
  'in the lookup table. to get the true magnitude value we must scale it back by multiplying by
  '1/1.6467743 or 0.607247753539552. Since we only need 16 bit precision, we can pick the simplest
  'fixed shift and add routine that gives a sufficiently precise result. Multiplying by 17/28
  'gives 0.6071428571 which is in error by 0.0172% which is probably good enough. However, we can
  'improve the accuracy by truncating the summation after 4 terms and adding the final term twice.
  'This gives a correction of 0.60725402832 for an error of 0.001%
  
  'We use a repeating fraction multiply algorithm with parameters m=17, n=5, p=3 (for 17/28 factor)
  'First multiply by m, then shift right n bits, then repeatedly shift right p bits and add to the
  'n shifted value.
  
  'start by multiplying by 17 (actually 17/4, in order to scale values to a safe range;
  'the factor 4 will be removed later)
  
  clc
  rrf xH,w
  movwf tH
  rrf xL,w
  movwf tL
  movlw 3
  movwf count
  
  MpyLoop1:
  
  clc 'bcf status,c
  rrf tH,f
  rrf tL,f
  decfsz count,f
  if noSkip then goto MpyLoop1
  movf xL,w
  addwf tL,f
  btfsc status,c
  incf tH,f
  movf xH,w
  addwf tH,f
  
  movf tH,w 'copy back from t to x
  movwf xH
  movf tL,w
  movwf xL
  'end of 17/4 scale
  
  'repeating shift/add loop
  movlw 4
  movwf index
  
  MpyLoop2:
  
  movlw 3
  movwf count
  
  MpyLoop3:
  
  clc 'bcf status,c
  rrf tH,f
  rrf tL,f
  decfsz count,f
  if noSkip then goto MpyLoop3
  movf tL,w
  addwf xL,f
  btfsc status,c
  incf xH,f
  movf tH,w
  addwf xH,f
  decfsz index,f
  if noSkip then goto MpyLoop2
  
  movf tL,w
  addwf xL,f
  btfsc status,c
  incf xH,f
  movf tH,w
  addwf xH,f
  
  'Finally shift x into y regs
  clrf yH
  clrf yL
  
  ScaleLoop:
  
  clc
  rlf xL,f
  rlf xH,f
  rlf yL,f
  rlf yH,f
  decfsz kScale,f
  if noSkip then goto ScaleLoop
  nop
  
  AllDone:
  nop
  
  'End of asm code.
  '****************************************
  
  'The magnitude value is converted to a type double, and stored as a property.
  magnitudeCORDIC=(yH*256+yL+xH/255)
  
  'The angle is converted to a type double, and stored as a property.
  angleCORDIC = angleL/256+angleH
  
  return 1 'Error code Indicates valid result

This worked well in my situation, because these PIC processors have no conditional jump instructions, just conditional skips. So all I had to do for compatibility is have the skip instruction set or clear a flag bit, and then the following line that has the goto instruction is simply prefixed with “If noskip then”

1 Like