Il set di opcode del 6510 (processore del C64) non comprende in modo nativo l'operazione di moltiplicazione e divisione. Su codebase64 sono disponibili algoritmi per il calcolo e' ho provato ad usare quello piu' semplice (8 bit * 8 bit = 8 bit) usando sia la sintassi di Acme che di KickAss (anche come promemoria)
Il risultato viene salvato nell'accumulatore e quindi spostato in una variabile
KickAss
--------------
*=$c000
//sys 49152
lda #$00
beq enterLoop
doAdd:
clc
adc num1
loop:
asl num1
enterLoop:
lsr num2
bcs doAdd
bne loop
end:
sta num3
rts
num1: .byte 7
num2: .byte 3
num3: .byte 0
--------------
Acme
--------------
; Moltiplicazione 8bit*8bit=8bit
!source "./stdlib/stdlib.a"
!to "fixed.prg", cbm
!sl "fixed.map"
!cpu 6510
!ct pet
*=$c000
;sys 49152
lda #$00
beq enterLoop
doAdd:
clc
adc num1
loop:
asl num1
enterLoop:
lsr num2
bcs doAdd
bne loop
end:
sta num3
rts
num1: !by 7
num2: !by 3
num3: !by 0
Visualizzazione post con etichetta ACME. Mostra tutti i post
Visualizzazione post con etichetta ACME. Mostra tutti i post
lunedì 23 luglio 2018
mercoledì 8 giugno 2016
Mandelbrot su C64 in Assembler
Frugando su internet ho trovato la versione in Assembler di Mandelbrot per C64 compresa nel progetto Resurrection (sotto cartella Mandelbrot)
Il codice e' ben commentato ed il risultato e' in modalita' testo
Il tempo di calcolo su VICE in emulazione del tempo reale del C64 risulta essere di 90 secondi con 26 iterazioni per punto
Il codice e' compilabile con il crosscompiler ACME e necessita della libreria stdlib
----------------------------------------------------------------
;Mandelbrot test code
!source "../stdlib/stdlib.a"
!to "Mandelbrot.prg", cbm
!sal
!sl "Mandelbrot.map"
!svl "Mandelbrot.lbl"
!cpu 6510
!ct pet
!source "../stdlib/BASICEntry80d.a"
!macro OutputFAC {
jsr $bddd ; Convert FAC#1 to ASCII String. Kills FAC#2
jsr $b487 ; Set Up String
jsr $ab21 ; Output String
}
LDFAC = $bba2
STFAC = $bbd4
SUBFAC = $b850
DIVFAC = $bb0f
CMPFAC = $bc5b
MULFAC = $ba28
ADDFAC = $b867
SETFAC = $b391
!macro LoadFAC .addr {
lda #<.addr
ldy #>.addr
jsr LDFAC
}
!macro StoreFAC .addr {
ldx #<.addr
ldy #>.addr
jsr STFAC
}
!macro SubMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr SUBFAC
}
!macro SubFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+SubMemFAC Temp
}
!macro DivMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr DIVFAC
}
!macro DivFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+DivMemFAC Temp
}
!macro CmpFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+CmpMemFAC Temp
}
!macro CmpMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr CMPFAC
}
!macro MulMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr MULFAC
}
!macro AddMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr ADDFAC
}
!macro SetFAC_Y {
lda #0
jsr SETFAC
}
kMaxIterations = 26
!zn
*=BASICEntry
cld
jsr CINT
; Speed testing for some FP ops. As we can see even some simple operations are very slow
!if 0 {
sei
.tl1
lda #0
sta VIC2BorderColour
+MACROWaitForRaster 64
inc VIC2BorderColour
+LoadFAC xmin
inc VIC2BorderColour
+SubMemFAC xmax
inc VIC2BorderColour
+DivFACMem ScrW
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
+MulMemFAC xs
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
jmp .tl1
}
; The main Mandelbrot code.
;xs=(xmax-xmin)/40.0;
+LoadFAC xmin
+SubMemFAC xmax
+DivFACMem ScrW
+StoreFAC xs
;ys=(ymax-ymin)/24.0;
+LoadFAC ymin
+SubMemFAC ymax
+DivFACMem ScrH
+StoreFAC ys
;for (y=0;y<24;y++) {
lda #0
sta y
.l1
; for (x=0;x<40;x++) {
lda #0
sta x
.l2
; p=xmin+(x*xs);
ldy x
+SetFAC_Y
+MulMemFAC xs
+AddMemFAC xmin
+StoreFAC p
; q=ymin+(y*ys);
ldy y
+SetFAC_Y
+MulMemFAC ys
+AddMemFAC ymin
+StoreFAC q
; xtemp=0;
; x0=0;
; y0=0;
ldy #0
+SetFAC_Y
+StoreFAC x0
+StoreFAC y0
; i=0;
lda #0
sta i
.while
; while (((x0*x0)+(y0*y0))<4 && ++i<kMaxIterations) {
; i check, first, simple integer check
lda i
cmp #kMaxIterations
bcc .ltkMaxIterations
jmp .escape
.ltkMaxIterations
; mul check
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+AddMemFAC Temp2
+CmpFACMem Escape
bcc .lt4
jmp .escape
.lt4
;++i
inc i
; xtemp = (x0*x0) - (y0*y0) + p
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+SubMemFAC Temp2
+AddMemFAC p
+StoreFAC xtemp
; y0=(2 * x0 * y0) +q;
+LoadFAC x0
+MulMemFAC y0
+StoreFAC Temp2
ldy #2
+SetFAC_Y
+MulMemFAC Temp2
+AddMemFAC q
+StoreFAC y0
; x0=xtemp;
+LoadFAC xtemp
+StoreFAC x0
; }
jmp .while
.escape
; Range check to adjust for printable characters
lda i
; lsr ; Potential for shit adjustment, change kMaxIterations to accomodate
cmp #26 ; Letters in the alphabet!
bcc .okChar
lda #' '
jmp .rawOut
.okChar
clc
adc #64
.rawOut
jsr CHROUT
; Finish for loops
inc x
lda x
cmp #40
beq .ol2
jmp .l2
.ol2
inc y
lda y
cmp #24 ; MPi: TOOD: Keep the last line clear for an IRQ scrolling message
beq .ol1
jmp .l1
.ol1
.flash
; inc VIC2BorderColour
jmp .flash
; C64 Floating point values
; MPi: TODO: Must update the assembler to create these
xmin !by $82, $a0, $00, $00, $00 ; -2.5
xmax !by $81, $40, $00, $00, $00 ; 1.5
ymin !by $81, $c0, $00, $00, $00 ; -1.5
ymax !by $81, $40, $00, $00, $00 ; 1.5
ScrW !by $86, $20, $00, $00, $00 ; 40
ScrH !by $85, $40, $00, $00, $00 ; 24
Escape !by $83, $00, $00, $00, $00 ; 4
; Float storage
Temp = *
Temp2 = * + 5
xs = * + 10
ys = * + 15
p = * + 20
q = * + 25
xtemp = * + 30
x0 = * + 35
y0 = * + 40
; Bytes
x = * + 45
y = * + 46
i = * + 47
Il codice e' ben commentato ed il risultato e' in modalita' testo
Il tempo di calcolo su VICE in emulazione del tempo reale del C64 risulta essere di 90 secondi con 26 iterazioni per punto
Il codice e' compilabile con il crosscompiler ACME e necessita della libreria stdlib
----------------------------------------------------------------
;Mandelbrot test code
!source "../stdlib/stdlib.a"
!to "Mandelbrot.prg", cbm
!sal
!sl "Mandelbrot.map"
!svl "Mandelbrot.lbl"
!cpu 6510
!ct pet
!source "../stdlib/BASICEntry80d.a"
!macro OutputFAC {
jsr $bddd ; Convert FAC#1 to ASCII String. Kills FAC#2
jsr $b487 ; Set Up String
jsr $ab21 ; Output String
}
LDFAC = $bba2
STFAC = $bbd4
SUBFAC = $b850
DIVFAC = $bb0f
CMPFAC = $bc5b
MULFAC = $ba28
ADDFAC = $b867
SETFAC = $b391
!macro LoadFAC .addr {
lda #<.addr
ldy #>.addr
jsr LDFAC
}
!macro StoreFAC .addr {
ldx #<.addr
ldy #>.addr
jsr STFAC
}
!macro SubMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr SUBFAC
}
!macro SubFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+SubMemFAC Temp
}
!macro DivMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr DIVFAC
}
!macro DivFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+DivMemFAC Temp
}
!macro CmpFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+CmpMemFAC Temp
}
!macro CmpMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr CMPFAC
}
!macro MulMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr MULFAC
}
!macro AddMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr ADDFAC
}
!macro SetFAC_Y {
lda #0
jsr SETFAC
}
kMaxIterations = 26
!zn
*=BASICEntry
cld
jsr CINT
; Speed testing for some FP ops. As we can see even some simple operations are very slow
!if 0 {
sei
.tl1
lda #0
sta VIC2BorderColour
+MACROWaitForRaster 64
inc VIC2BorderColour
+LoadFAC xmin
inc VIC2BorderColour
+SubMemFAC xmax
inc VIC2BorderColour
+DivFACMem ScrW
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
+MulMemFAC xs
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
jmp .tl1
}
; The main Mandelbrot code.
;xs=(xmax-xmin)/40.0;
+LoadFAC xmin
+SubMemFAC xmax
+DivFACMem ScrW
+StoreFAC xs
;ys=(ymax-ymin)/24.0;
+LoadFAC ymin
+SubMemFAC ymax
+DivFACMem ScrH
+StoreFAC ys
;for (y=0;y<24;y++) {
lda #0
sta y
.l1
; for (x=0;x<40;x++) {
lda #0
sta x
.l2
; p=xmin+(x*xs);
ldy x
+SetFAC_Y
+MulMemFAC xs
+AddMemFAC xmin
+StoreFAC p
; q=ymin+(y*ys);
ldy y
+SetFAC_Y
+MulMemFAC ys
+AddMemFAC ymin
+StoreFAC q
; xtemp=0;
; x0=0;
; y0=0;
ldy #0
+SetFAC_Y
+StoreFAC x0
+StoreFAC y0
; i=0;
lda #0
sta i
.while
; while (((x0*x0)+(y0*y0))<4 && ++i<kMaxIterations) {
; i check, first, simple integer check
lda i
cmp #kMaxIterations
bcc .ltkMaxIterations
jmp .escape
.ltkMaxIterations
; mul check
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+AddMemFAC Temp2
+CmpFACMem Escape
bcc .lt4
jmp .escape
.lt4
;++i
inc i
; xtemp = (x0*x0) - (y0*y0) + p
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+SubMemFAC Temp2
+AddMemFAC p
+StoreFAC xtemp
; y0=(2 * x0 * y0) +q;
+LoadFAC x0
+MulMemFAC y0
+StoreFAC Temp2
ldy #2
+SetFAC_Y
+MulMemFAC Temp2
+AddMemFAC q
+StoreFAC y0
; x0=xtemp;
+LoadFAC xtemp
+StoreFAC x0
; }
jmp .while
.escape
; Range check to adjust for printable characters
lda i
; lsr ; Potential for shit adjustment, change kMaxIterations to accomodate
cmp #26 ; Letters in the alphabet!
bcc .okChar
lda #' '
jmp .rawOut
.okChar
clc
adc #64
.rawOut
jsr CHROUT
; Finish for loops
inc x
lda x
cmp #40
beq .ol2
jmp .l2
.ol2
inc y
lda y
cmp #24 ; MPi: TOOD: Keep the last line clear for an IRQ scrolling message
beq .ol1
jmp .l1
.ol1
.flash
; inc VIC2BorderColour
jmp .flash
; C64 Floating point values
; MPi: TODO: Must update the assembler to create these
xmin !by $82, $a0, $00, $00, $00 ; -2.5
xmax !by $81, $40, $00, $00, $00 ; 1.5
ymin !by $81, $c0, $00, $00, $00 ; -1.5
ymax !by $81, $40, $00, $00, $00 ; 1.5
ScrW !by $86, $20, $00, $00, $00 ; 40
ScrH !by $85, $40, $00, $00, $00 ; 24
Escape !by $83, $00, $00, $00, $00 ; 4
; Float storage
Temp = *
Temp2 = * + 5
xs = * + 10
ys = * + 15
p = * + 20
q = * + 25
xtemp = * + 30
x0 = * + 35
y0 = * + 40
; Bytes
x = * + 45
y = * + 46
i = * + 47
----------------------------------------------------------------
lunedì 12 gennaio 2015
Potenza di calcolo Arduino Yun vs ACME Terra vs MacBook
Un amico usa normalmente per acquisizione delle schede Terra ACME ed sostanzialmente mi ha lanciato una sfida se fosse piu' performante nel calcolo puro la sua Terra o la mia YUN
Il terreno di battaglia e' stato scelto con l'elaborazione dello script in Python per la creazione di un insieme di Mandelbrot
Lo script nel dettaglio e' il seguente
--------------------------------------------------
from PIL import Image
from PIL import ImageDraw
# drawing area
xa = -2.0
xb = 1.0
ya = -1.5
yb = 1.5
maxIt = 255 # max iterations allowed
# image size
imgx = 512
imgy = 512
image = Image.new("RGB", (imgx, imgy))
for y in range(imgy):
zy = y * (yb - ya) / (imgy - 1) + ya
for x in range(imgx):
zx = x * (xb - xa) / (imgx - 1) + xa
z = zx + zy * 1j
c = z
for i in range(maxIt):
if abs(z) > 2.0: break
z = z * z + c
image.putpixel((x, y), (i % 4 * 64, i % 8 * 32, i % 16 * 16))
image.save("mandel.bmp", "BMP")
--------------------------------------------------
Su Arduino Yun e' stato necessario installare il pacchetto python-imaging-library.
Su Terra si e' presentato un problema inatteso. I repository di EmDebian (Embedded Debian) non sono piu' disponibili per cui il programma e' stato fatto girare eliminando i riferimenti alle librerie grafiche (dando quindi un piccolo vantaggio a Terra)
Alla fine il risultato e' stato meno definitivo di quanto creduto
Terra ha impiegato 11 minuti e 35 secondi contro i 14 minuti e 52 secondi di Yun (per confronto un MacBook i5 impiega 6.1 secondi)....considerando che Arduino Yun costa circa 62 Euro in confronto ai 199 euro di Terra Kit la mia scelta e' piu' orientata verso la Yun (con circa 200 euro si iniziano a comprare dei portatili completi come i ChromeBook)
Il terreno di battaglia e' stato scelto con l'elaborazione dello script in Python per la creazione di un insieme di Mandelbrot
Lo script nel dettaglio e' il seguente
--------------------------------------------------
from PIL import Image
from PIL import ImageDraw
# drawing area
xa = -2.0
xb = 1.0
ya = -1.5
yb = 1.5
maxIt = 255 # max iterations allowed
# image size
imgx = 512
imgy = 512
image = Image.new("RGB", (imgx, imgy))
for y in range(imgy):
zy = y * (yb - ya) / (imgy - 1) + ya
for x in range(imgx):
zx = x * (xb - xa) / (imgx - 1) + xa
z = zx + zy * 1j
c = z
for i in range(maxIt):
if abs(z) > 2.0: break
z = z * z + c
image.putpixel((x, y), (i % 4 * 64, i % 8 * 32, i % 16 * 16))
image.save("mandel.bmp", "BMP")
--------------------------------------------------
Su Arduino Yun e' stato necessario installare il pacchetto python-imaging-library.
Su Terra si e' presentato un problema inatteso. I repository di EmDebian (Embedded Debian) non sono piu' disponibili per cui il programma e' stato fatto girare eliminando i riferimenti alle librerie grafiche (dando quindi un piccolo vantaggio a Terra)
Alla fine il risultato e' stato meno definitivo di quanto creduto
Terra ha impiegato 11 minuti e 35 secondi contro i 14 minuti e 52 secondi di Yun (per confronto un MacBook i5 impiega 6.1 secondi)....considerando che Arduino Yun costa circa 62 Euro in confronto ai 199 euro di Terra Kit la mia scelta e' piu' orientata verso la Yun (con circa 200 euro si iniziano a comprare dei portatili completi come i ChromeBook)
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...