  ; Pro ulozeni promennych do spravnych registru

  ; Ulozeni z SRAM
; Save_X_to_A	; Pracuje s XH,XL,A_SE,A_3,A_2,A_1
; Save_X_to_B	; Pracuje s XH,XL,B_SE,B_3,B_2,B_1

  ; Ulozeni do SRAM
; Save_A_to_X	; Pracuje s XH,XL,A_SE,A_3,A_2,A_1
; Save_B_to_X	; Pracuje s XH,XL,B_SE,B_3,B_2,B_1

  ; Ulozeni z flash pameti (napr. konstanty)
; Save_Z_to_A	; Pracuje s ZH,ZL,A_SE,A_3,A_2,A_1
; Save_Z_to_B	; Pracuje s ZH,ZL,B_SE,B_3,B_2,B_1

; Pouzije se k tomu ukazatel X, do nehoz se nahraje adresa, na ktere je ulozen
; exponent se znamenkem. Dalsi musi byt MSB bity. Pripadne nahlidnout do kodu

  ; Ulozeni promenne A do promenne xn (SRAM)
; Save_A_to_x0	; Ulozi promennou A do x0 (SRAM)
; Save_B_to_x0	; B -> x0 (SRAM)
; Save_A_to_x1	; A -> x1
; Save_B_to_x1	; B -> x1
; Save_A_to_x2	; A -> x2
; Save_B_to_x2	; B -> x2
; Save_A_to_x3	; A -> x3
; Save_B_to_x3	; B -> x3
; Save_A_to_x4	; A -> x4
; Save_B_to_x4	; B -> x4

; Save_x0_to_A	; x0 -> A
; Save_x0_to_B	; x0 -> B
; Save_x1_to_A	; x0 -> A
; Save_x1_to_B	; x0 -> B
; Save_x2_to_A	; x0 -> A
; Save_x2_to_B	; x0 -> B
; Save_x3_to_A	; x0 -> A
; Save_x3_to_B	; x0 -> B
; Save_x4_to_A	; x0 -> A
; Save_x4_to_B	; x0 -> B

; Operace s floatem. Pouziva se vetsina registru, ktere jsou zde definovany.
  ; Nema cenu vypisovat.
; float_A_to_B		; A=B
; float_B_to_A		; B=A

; float_A_div_B		; A=A/B
; float_one_div_B	; B=1/B
; float_A_mul_B		; A=A*B
; float_A_minus_B	; A=A-B
; float_A_plus_B	; A=A+B
; float_A_div2		; A=A/2 = A*0.5 ; Rychlejsi nez A/B
; float_B_div2		; B=B/2 = B*0.5
; float_A_mul2		; A=A*2
; float_B_mul2		; B=B*2

; float_SQRT_A		; A=-/^(A)^ (druha odmocnina)

  ; Pomocne funkce, ktere vyuzivaji vyse uvedene podprogramy
; float_operation_prepare_ApB
; ADD_A_B
; SUB_A_B
; SUB_B_A
; load_MSB_to_mantis

  ; Prevod floatu do desitkove soustavy
; calc_float2dec_20	; Pouziva float cislo A, takze je nutny pripadny presun
  ; vysledku do teto promenne

  ; Pomocne funkce, ktere vyuziva calc_float2dec_20
; Add_byte_to_dec_num_20

  ; Prevod celeho cisla do floatu
; Convert_8bit_unsigned_to_float	; Prevede 8bitove neznamenkove cislo
  ; do floatu jako A. Jako vstupni registr je Mg
; Convert_8bit_unsigned_to_float_A	; ==||==
; Convert_8bit_unsigned_to_float_B	; To same, ale cislo se ulozi do B

; Convert_8bit_signed_to_float		; To same, ale pro znamenkova cisla
; Convert_8bit_signed_to_float_A
; Convert_8bit_signed_to_float_B

; Convert_16bit_signed_to_float		; Pro 16. bitova cisla
; Convert_16bit_signed_to_float_A	; pouziva M2:M1
; Convert_16bit_signed_to_float_B

; Convert_16bit_unsigned_to_float
; Convert_16bit_unsigned_to_float_A	; Analogie, ale pro 16. bitova cisla
; Convert_16bit_unsigned_to_float_B

; Convert_24bit_unsigned_to_float_A	; 24 bitove cisla ; pouziva M3:M1
; Convert_24bit_unsigned_to_float_B

;.EQU D_start_20_SRAM = $0060	; DEFINOVAT, od ktere cati SRAM lze pracovat s Dp9 az
  ; Dn10. Vhodne napr. na pocatku hlavniho programu! Jinak odkomentovat

.DEF Mg = R16	; Jakykoli od R16~R31

.DEF B_SE = R15	; float B - znamenko a exponent
.DEF B_3 = R14	; float B - hornich 8 bitu
.DEF B_2 = R13	; float B - "strednich" 8 bitu
.DEF B_1 = R12	; float B - spodnich 8 bitu

  ; Nyni to same, ale pro float A
.DEF A_SE = R11
.DEF A_3 = R10	; Nejvyssich 8 bitu
.DEF A_2 = R9
.DEF A_1 = R8	; Nejnizsich 8 bitu

  ; Pro matematicke operace
  ; Registry R0 a R1 pouziva intrukce MUL pro ulozeni vysledku. Proto je
  ; nevhodne tyto registry pouzivat jako "odkladaci"
.DEF M1 = R2
.DEF M2 = R3
.DEF M3 = R4
.DEF M4 = R5
  ; M1 ~ M4 staci pro scitani a odcitani
.DEF M5 = R6
.DEF M6 = R7
  ; M1 ~ M6 - pro nasobeni (vysledek nelze "rovnou" ukladat do A.
  ; S registry A_3 az A_1 se pracuje neustale a je zapotrebi, aby jejich obsah
  ; byl stale "originalni"

  ; Pripadne by se dala pouzit pamet SRAM, ale to by na vykonu moc nepridalo

.MESSAGE "Ignore warning type: Rxy is already assigned to 'xyzabc'!"
.MESSAGE "in file float_operation.asm"

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Save_X_to_A:
	LD A_SE,X+
	LD A_3,X+
	LD A_2,X+
	LD A_1,X+
	RET
; *-----------------------------------------*
Save_X_to_B:
	LD B_SE,X+
	LD B_3,X+
	LD B_2,X+
	LD B_1,X+
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Save_A_to_X:
	ST X+,A_SE
	ST X+,A_3
	ST X+,A_2
	ST X+,A_1
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Save_B_to_X:
	ST X+,B_SE
	ST X+,B_3
	ST X+,B_2
	ST X+,B_1
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Save_Z_to_A:
	LPM A_SE,Z+
	LPM A_3,Z+
	LPM A_2,Z+
	LPM A_1,Z+
	RET
; *-----------------------------------------*
Save_Z_to_B:
	LPM B_SE,Z+
	LPM B_3,Z+
	LPM B_2,Z+
	LPM B_1,Z+
	RET

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Save_A_to_x0:
	STS float_extra_variables_SRAM,A_SE
	STS float_extra_variables_SRAM+1,A_3
	STS float_extra_variables_SRAM+2,A_2
	STS float_extra_variables_SRAM+3,A_1
	RET

Save_B_to_x0:
	STS float_extra_variables_SRAM,B_SE
	STS float_extra_variables_SRAM+1,B_3
	STS float_extra_variables_SRAM+2,B_2
	STS float_extra_variables_SRAM+3,B_1
	RET

Save_A_to_x1:
	STS float_extra_variables_SRAM+4,A_SE
	STS float_extra_variables_SRAM+5,A_3
	STS float_extra_variables_SRAM+6,A_2
	STS float_extra_variables_SRAM+6,A_1
	RET

Save_B_to_x1:
	STS float_extra_variables_SRAM+4,B_SE
	STS float_extra_variables_SRAM+5,B_3
	STS float_extra_variables_SRAM+6,B_2
	STS float_extra_variables_SRAM+7,B_1
	RET

Save_A_to_x2:
	STS float_extra_variables_SRAM+8,A_SE
	STS float_extra_variables_SRAM+9,A_3
	STS float_extra_variables_SRAM+10,A_2
	STS float_extra_variables_SRAM+11,A_1
	RET

Save_B_to_x2:
	STS float_extra_variables_SRAM+8,B_SE
	STS float_extra_variables_SRAM+9,B_3
	STS float_extra_variables_SRAM+10,B_2
	STS float_extra_variables_SRAM+11,B_1
	RET


Save_A_to_x3:
	STS float_extra_variables_SRAM+12,A_SE
	STS float_extra_variables_SRAM+13,A_3
	STS float_extra_variables_SRAM+14,A_2
	STS float_extra_variables_SRAM+15,A_1
	RET

Save_B_to_x3:
	STS float_extra_variables_SRAM+12,B_SE
	STS float_extra_variables_SRAM+13,B_3
	STS float_extra_variables_SRAM+14,B_2
	STS float_extra_variables_SRAM+15,B_1
	RET

Save_A_to_x4:
	STS float_extra_variables_SRAM+16,A_SE
	STS float_extra_variables_SRAM+17,A_3
	STS float_extra_variables_SRAM+18,A_2
	STS float_extra_variables_SRAM+19,A_1
	RET

Save_B_to_x4:
	STS float_extra_variables_SRAM+16,B_SE
	STS float_extra_variables_SRAM+17,B_3
	STS float_extra_variables_SRAM+18,B_2
	STS float_extra_variables_SRAM+19,B_1
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Save_x0_to_A:
	LDS A_SE,float_extra_variables_SRAM
	LDS A_3,float_extra_variables_SRAM+1
	LDS A_2,float_extra_variables_SRAM+2
	LDS A_1,float_extra_variables_SRAM+3
	RET

Save_x0_to_B:
	LDS B_SE,float_extra_variables_SRAM
	LDS B_3,float_extra_variables_SRAM+1
	LDS B_2,float_extra_variables_SRAM+2
	LDS B_1,float_extra_variables_SRAM+3
	RET

Save_x1_to_A:
	LDS A_SE,float_extra_variables_SRAM+4
	LDS A_3,float_extra_variables_SRAM+5
	LDS A_2,float_extra_variables_SRAM+6
	LDS A_1,float_extra_variables_SRAM+6
	RET

Save_x1_to_B:
	LDS B_SE,float_extra_variables_SRAM+4
	LDS B_3,float_extra_variables_SRAM+5
	LDS B_2,float_extra_variables_SRAM+6
	LDS B_1,float_extra_variables_SRAM+7
	RET

Save_x2_to_A:
	LDS A_SE,float_extra_variables_SRAM+8
	LDS A_3,float_extra_variables_SRAM+9
	LDS A_2,float_extra_variables_SRAM+10
	LDS A_1,float_extra_variables_SRAM+11
	RET

Save_x2_to_B:
	LDS B_SE,float_extra_variables_SRAM+8
	LDS B_3,float_extra_variables_SRAM+9
	LDS B_2,float_extra_variables_SRAM+10
	LDS B_1,float_extra_variables_SRAM+11
	RET


Save_x3_to_A:
	LDS A_SE,float_extra_variables_SRAM+12
	LDS A_3,float_extra_variables_SRAM+13
	LDS A_2,float_extra_variables_SRAM+14
	LDS A_1,float_extra_variables_SRAM+15
	RET

Save_x3_to_B:
	LDS B_SE,float_extra_variables_SRAM+12
	LDS B_3,float_extra_variables_SRAM+13
	LDS B_2,float_extra_variables_SRAM+14
	LDS B_1,float_extra_variables_SRAM+15
	RET

Save_x4_to_A:
	LDS A_SE,float_extra_variables_SRAM+16
	LDS A_3,float_extra_variables_SRAM+17
	LDS A_2,float_extra_variables_SRAM+18
	LDS A_1,float_extra_variables_SRAM+19
	RET

Save_x4_to_B:
	LDS B_SE,float_extra_variables_SRAM+16
	LDS B_3,float_extra_variables_SRAM+17
	LDS B_2,float_extra_variables_SRAM+18
	LDS B_1,float_extra_variables_SRAM+19
	RET

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_A_to_B:	; Zkopiruje float A do B
	MOV B_SE,A_SE
	MOV B_3,A_3
	MOV B_2,A_2
	MOV B_1,A_1

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_B_to_A:	; Zkopiruje flaot B do A
	MOV A_SE,B_SE
	MOV A_3,B_3
	MOV A_2,B_2
	MOV A_1,B_1

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_A_div_B:
  ; Postup vypoctu: B=1/B ; A=A*B (prakticky se deje toto:
  ; A=A/B)
	RCALL float_one_div_B
	RCALL float_A_mul_B
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_one_div_B:	; B=1/B
  ; Nejprve se zkontroluje, zda nedelime nulou -> to by pak nemelo ledacos
  ; smysl
	MOV Mg,B_SE	; bohuzel B_SE je v takove casti pameti (R0~R15), ke
  ; ktere nema CPI pristup (ma pristup jen k R16~R31). Proto se musi pouzit
  ; registr Mg, ktery je v te pameti, ke ktere ma CPI pristup
	CLT	; T-bit = 0
	BLD Mg,7	; zbavime se znamenka

  ; Kontrolni algoritmy
  ; Kontrola na nulu:
	CPI Mg,0b01000000
	BRNE one_div_B_Test_for_1	; Pokud neni nula, test na |1|
one_div_B_zero:
	LDI Mg,0b00111111	; Cislo exponentu je maximalni. Znamenko se
  ; prida casem
	BST B_SE,7	; "Natahneme" znamenkovy bit
	BLD Mg,7	; Vlozime do Mg na stejnou pozici
	MOV B_SE,Mg	; A ulozime znamenko s exponentem
	LDI Mg,$FF	; do Mg se ulozi 0b11111111
	MOV B_3,Mg
	MOV B_2,Mg
	MOV B_1,Mg	; A vsechny registry jsou zaplneny jednickama. To snad
  ; musi kazdemu dojit, ze je to proste hodne :D
	RET	; Co taky vic resit

  ; VLOZIT KONTROLNI ALGORITMY NA NULU A JEDNUCKU! 1/0 -> NEKONECNO! 1/1=1
  ; KONTROLA PRO 1eXY, protoze, jinak konecny algoritmus fail


one_div_B_Test_for_1:	; Zjistime, jestli neni nahodou cislo napriklad 1eX
  ; Protoze pokud ano, muzeme si usetrit spoustu vypoctu
	CLR M1	; Smaze se obsah M1 (zatim neni vyuzit)
	CP B_3,M1	; V podstate porovnavame B_3 s nulou (jeste nebyla
  ; provedena "prvni" rotace
	BRNE one_div_B_Continue_normally	; Pokud si nebyly rovny -> skok

	CP B_2,M1	; pripadne se porovnaji dalsi
	BRNE one_div_B_Continue_normally

	MOV M2,Mg	; Zaloha Mg -> pro pripad, ze je zde opravdu cislo 1
	LDI Mg,0b00000100	; Spodni 2 bity pujdou "pryc", takze po jejich
  ; smazani by se cislo "tvarilo" jako 1eX. Takze ma smysl pocitat, jen
  ; v pripade, ze Nejnizsi bajt je vetsi, nebo roven teto hodnote
	CP B_1,Mg	; A pripadne posledni
	BRSH one_div_B_Continue_normally
  ; Takze ted je jasne, ze je vysledek 1eX. Pokud je ale exponent nula, pak
  ; je reseni jeste jednodussi.
  ; No a pokud slo o jednicku, pak vysledek je taky jednicka. A ma to znamenko,
  ; jake ma B. A protoze B je v podstate svuj vlastni vysledek, nemusime uz
  ; provadet zadne operace
	MOV Mg,M2	; Obnova Mg
	CPI Mg,0b00000000	; porovnani exponentu s 0 (1e0 = 1)
	BRNE one_div_B_Test_for_1eX	; Pokud nebyl exponent nula, pak se
  ; pouze zmeni znamenko
	RET	; Pokud ale byl exponent nula, pak B je vlastne svuj vlastni
  ; vysledek -> RET
one_div_B_Test_for_1eX:
	CLT	; T-bit = 0
	SBRS B_SE,6	; test znamenka -> kdyz 1 -> nasl. instrukce se
  ; preskoci a T-bit zustane v 0 -> T-bit se pak zkopiruje do B_SE,6
	SET

	BLD B_SE,6	; Provede se zmena znamenka
	RET

one_div_B_Continue_normally:
  ; V podstate se provede 2x rotace
  ; vpravo, coz bude mit za nasledek ztraty dvou spodnich bitu


  ; Provede se rotace B vpravo a to 2x -> viz. "load_MSB_to_mantis"
	SEC	; C do "1"
	ROR B_3
	ROR B_2
	ROR B_1
	; A jeste jedou
	LSR B_3	; posuv vpravo, na MSB se automaticky "hodi" 0
	ROR B_2
	ROR B_1

  ; Operace v podstate 1/B -> citatel bude 1, jmenovatel je B ->
  ; -> pro citatel budou pouzity registry M3,M2 a M1 (od MSB po LSB).
	LDI Mg,0b01000000	; aby bylo "desetinna carka" na stejnem miste
  ; jako u cisla B
  	MOV M3,Mg
	CLR M2
	CLR M1


  ; mezivysledky se ukladaji do M6:M4 (od MSB po LSB)

	LDI Mg,23	; Pocita, kolik kroku jsme jiz udelali.V podstate staci
  ; pouze 23 kroku, i kdyz je mantisa 24bitova, ale jeden bit se "ztrati" pri
  ; rotacich (kdyz se na prvni pozici nahrava MSB bit).
  ; Tato hodnota udava, na ktere pozici se ma zacit!

  ; Algoritmus vypoctu je analogicky stejny jako u desitkove soustavy. Vyhoda
  ; binarni soustavy je v tom, ze pokud delime dve cisla, tak se celkem
  ; jednoduse zjisti, kolikrat se dane cislo do daneho radu vejde -> pokud je
  ; citatel mensi jak jmenovatel, pak bude vysledek 1 a vypocita se zbytek.
  ; V opacnem pripade je vysledek 0. Nejlepsi je: vzit si papir a vyzkouset
  ; pro desitkovou soustavu a pote pro binarni soustavu a pak se reverzne
  ; podivat na tento algoritmus
odB_Calc_mantis:
  ; Zjisti, jestli je B (B_3:B_1) mensi, nez citatel (M3:M1). Resp. jestli se
  ; B "vleze" do M3:M1
	CP B_3,M3	; Porovnani hornich 8. bitu
	BRLO odB_Cm_1	; Pokud je B mensi jak M (test MSB bitu), pak je jasne,
  ; ze vysledny bit je "1" (B se "vleze" do M3:M1)

  ; Pokud to neni jasne z MSB, pak se musi zkontrolovat dalsich 8 bitu. ALE
  ; pozor! Ma to smysl, jen pokud byly MSB rovny. V opacnem pripade je jasne,
  ; ze B je vetsi a neni co resit -> vysledny bit je "0"
	BRNE odB_Cm_0	; Pokud si nejsou B_3,M3 rovny -> B se nevleze do M3:M1
  ; -> vysledny bit je "0"

  ; Takze pokud si bylo hornich 8 bitu rovno, pak se otestuji dalsi bity
	CP B_2,M2
	BRLO odB_Cm_1	; A zase. Pokud bylo B mensi -> jiste se "vleze" do
  ; M3:M1 -> vysledny bit je "1"
	BRNE odB_Cm_0	; A pokud nebyl mensi, kontrola nerovnosti -> pripadny
  ; skok

	CP B_1,M1	; Porovnani nejmensich bitu
	BRLO odB_Cm_1	; Pokud je B mensi -> vleze se -> "1"
	BREQ odB_Cm_1	; Pokud je B rovno -> stale se vleze (mozny zpusob
  ; urychlit vypocet, ale program se o neco zvetsi -> vzhledem k tomu, ze
  ; jsou obe cisla stejne -> vysledny bit je 1, ale zbytek uz bude nula ->
  ; nemusi se dal nic resit, proste zbytek jsou nuly -> "jen" zapsat a je hotovo)


  ; V opacnem pripade se B nevleze. Vzhledem k tomu, ze PC "pujde" na dalsi
  ; radek -> nemusime dal nic resit
odB_Cm_0:	; B je vetsi jak M3:M1 -> vysledny bit je "0"
	CLT	; T-bit se nastavi do 0 -> pak se bude zapisovat do vysledku
  ; ted se musi provest rotace M3:M1 vlevo
	LSL M1
	ROL M2
	ROL M3

	RJMP odB_Cm_write_byte	; Zapsat vysledny bit

odB_Cm_1:	; B je mensi jak M3:M1 -> vysledny bit je "1"
	SET	; T-bit se nastavi do 1 -> pak se zapise do vysledku
  
  ; Jeste se musi provest nasledujici operace: M3:M1=M3:M1-B
  ; Pokud jsme tady, pak M3:M1 je rovno, nebo vetsi jak B -> vysledek musi byt
  ; kladny
	SUB M1,B_1
	SBC M2,B_2
	SBC M3,B_3

  ; rotace M3:M1
	LSL M1
	ROL M2
	ROL M3

odB_Cm_write_byte:	; Zapis bitu na spravne misto
  ; Prvne se musi zjisti, do ktere pametove bunky se ma zapsat (M6,M5,M4)
  ; a az pote se vypocita pozice prislusneho bitu
	CPI Mg,16	; Porovnani soucasne pozice s cislem 16
	BRLO odB_Cm_write_byte_test_8_15	; Pokud je cislo pozice mensi
  ; jak 16 (tzn. rozhodne se nebude zapisovat do nejvyssi pametove bunky), tak
  ; se musi zjistit, zda se bude zapisovat do nasledujici bunky, nebo az do
  ; dalsi)
odB_Cm_write_byte_16_23:	; Pokud se PC dostane sem, pak chceme urcite
  ; zapisovat do nejvyssi bunky -> M6. Ted jen zjistit na kterou konkretni
  ; pozici
	MOV R0,Mg	; Do R0 si ulozime honodtu Mg (zaloha), bude pak
  ; zapotrebi
	MOV R1,M6	; Do R1 se ulozi puvodni hodnota registru M6 (potrebuje
  ; podprogram "odB_Cm_write_byte_to_R1"

	SUBI Mg,16	; Od aktualni hodnoty odecteme 16 -> tim ziskame cislo
  ; 0~7 -> pozice bitu
	RCALL odB_Cm_write_byte_to_R1	; Timto se zapise dany bit na "spravne"
  ; misto
	MOV M6,R1	; A do M6 se ulozi vysledek
	MOV Mg,R0	; A obnova Mg
	RJMP odB_Cm_test_for_end	; A test, zda neni tento vypocet
  ; posledni (dalsi zpresnovani vysledku by uz nemelo smysl, protoze lze ulozit
  ; jen 24 bitu do mantisy, ale zde se provedla 2x rotace -> 22 bitu je
  ; efektivnich (ma symsl opravdu provest)

odB_Cm_write_byte_test_8_15:	; Zjisti se, zda se nebude zapisovat do
  ; nasledujici bunky (M5)
	CPI Mg,8
	BRLO odB_Cm_write_byte_test_0_7	; Pokud je Mg mensi jak 8 -> pak se
  ; bude zapisovat do posledniho bloku
odB_Cm_write_byte_8_15:
  ; Pokud bylo Mg vetsi jak 7 -> dostaneme se sem -> analogie s vysse uvedenym
	MOV R0,Mg
	MOV R1,M5
	SUBI Mg,8
	RCALL odB_Cm_write_byte_to_R1
	MOV M5,R1
	MOV Mg,R0
	RJMP odB_Cm_test_for_end
odB_Cm_write_byte_test_0_7:	; Zde uz neni co testovat -> jina moznost neni
  ; Mg nemusime zalohovat -> nabyva hodnot 0~7 -> neni potreba nic odecitat
	MOV R1,M4
	RCALL odB_Cm_write_byte_to_R1
	MOV M4,R1	; A ulozeni aktualni hodnoty
;	RJMP odB_Cm_test_for_end	; Zbytecne, PC si tam "dojde" sam

odB_Cm_test_for_end:	; test, zda jsme jiz neudalali maximalni pocet kroku
  ; (kterych ma smysl delat - 22. ALE: prvni krok je vzdy nula -> takze o jeden vic)
	CPI Mg,0	; Pokud bude rovno 1 -> zbytecne pocitat vetsi presnost
  ; -> efektivne se pouzije jen 22 bitu
	BREQ odB_Cm_save_to_mantis	; Pokud se udela potrebny pocet kroku
  ; -> ulozit z docasnych registru do B

  ; V opacnem pripade se vypocet bude zpresnovat dal a odecte se pocet kroku
  ; o 1
	DEC Mg	; pocet kroku -1
	RJMP odB_Calc_mantis	; A provede se cely algoritmus znovu

odB_Cm_save_to_mantis:
  ; ted je v M6:M4 ulozena vysledna hodnota. Preulozit do B_3:B_1
	MOV B_3,M6
	MOV B_2,M5
	MOV B_1,M4
  ; Provest patricnou rotaci. Pro kontrolu. hned druhy bit MUSI byt "1". Je to
  ; diky plovouci carce, takze jmenovatel nikdy nemuze byt vetsi jak 2 -> tzn.
  ; minimalni teoreticky vysledek je 1/2 -> 0.5 -> 0.1b. Cim vice se bude
  ; jmenovatel blizit k jednicce, tim se bude i samotny vysledek blizit
  ; k jednicce, ale jedicky nemuze byt nikdy dosazeno (uz jen proto, ze spodni
  ; dva bity jsou smazany). Navic kontrola na jednicku je na pocatku algoritmu

  ; Prvni rotace
	LSL B_1
	ROL B_2
	ROL B_3
  ; Druha rotace
	LSL B_1
	ROL B_2
	ROL B_3

odB_Calc_exp:	; Vypocet exponentu
  ; Ted vyresit epxonent. Diky plovouci carce se toho hodne zjednodusuje.
  ; Pokud byl exponent kladny, tak ted bude zaporny a naopak. Pokud byl kladny,
  ; tak se jeho absolutni hodnota zvetsi a naopak.
  ; Jediny problem nastava pri "prechodu" z -1 do 0 a z 0 do -1

  ; Vzhledem k tomu, ze se nemeni znamenka (pouze znamenko exponentu) a zvysuje
  ; se, nebo snizuje se samotny epxonent, nemusi se zase toho tolik resit.
  ; Staci zjistit znamenko exponentu
	MOV Mg,B_SE	; Zaloha B_SE do Mg (pozdeji se bude pracovat s Mg)
	CLT
	BLD Mg,7	; timto se odstrani znamenko cisla

	SBRC B_SE,6	; Test na znamenko exp.
	RJMP odB_Exp_minus	; Pokud byl nastaven bit v "0" toto se preskoci
odB_Exp_plus:	; bit byl nastaven v nule -> zvysit abs. hodnotu a zmen. znam.
  ; jak bylo napsano vyse, problem nastava pri prechodu z -1 do 0 -> kontrola
	CPI Mg,0b01000001	; porovnani s hodnotou exponentu "-1"
	BREQ odB_Exp_plus_exception	; pokud tomu tak opravdu je -> skok

  ; V opacnem pripade staci zvysit abs. hodnotu B_SE
	INC B_SE	; Nepocita se s pretecenim. Stejne by vysledek nebyl
  ; spravny a cely algoritmus by to akorat zpomalovalo a vysledek by stejne
  ; nebyl dosazen. Navic by se muselo pracovat s opravdu velkymi, nebo extreme
  ; malymi cisly
	SET	; T-bit = 1
	BLD B_SE,6	; Znamenko = - (1)
	RET

odB_Exp_plus_exception:	; musi se do exponentu nahrat 0
	LDI Mg,0b00000000
	BST B_SE,7	; Stahneme si znamenkovy bit do T-bitu
	BLD Mg,7	; A tento bit zkopirujeme do Mg na tu samou pozici
	MOV B_SE,Mg	; A do B_SE se ulozi vysledek
	RET	; Konec

odB_Exp_minus:	; bit nastaven v jednicce -> snizit abs. hodnotu a zmen. znam.
	CPI Mg,0b00000000	; Porovnani s nulou
	BREQ odB_Exp_minus_exception

  ; V opacnem pripade staci odecist jednicku
	DEC B_SE
	CLT	; T-bit = 0
	BLD B_SE,6	; Nastaveni znamenka na + (0)
	RET

odB_Exp_minus_exception:
  ; exponent 0 -> musi se nahrat -1
	LDI Mg,0b01000001
	BST B_SE,7
	BLD Mg,7
	MOV B_SE,Mg
	RET
; *-----------------------------------------*
odB_Cm_write_byte_to_R1:	; Do registru R1 se prida vysledek
	CPI Mg,7	; Kontrola na horni bit
	BRNE odB_Cm_wb2R1_6	; Pokud se nema zapisovat do horniho bitu ->
  ; -> test na dalsi bit

  ; Pokud se dostaneme sem, pak se dany bit ma zkopirovat do R1
	BLD R1,7	; Na pozici R7 se zkopiruje dany bit
	RET	; Tim tato operace konci, je zbytecne se zabyvat dalsimi
  ; moznostmi. Na druhou stranu se timto prikazem o neco zvetsi kod
odB_Cm_wb2R1_6:
	CPI Mg,6
	BRNE odB_Cm_wb2R1_5
	BLD R1,6
	RET
odB_Cm_wb2R1_5:
	CPI Mg,5
	BRNE odB_Cm_wb2R1_4
	BLD R1,5
	RET
odB_Cm_wb2R1_4:
	CPI Mg,4
	BRNE odB_Cm_wb2R1_3
	BLD R1,4
	RET
odB_Cm_wb2R1_3:
	CPI Mg,3
	BRNE odB_Cm_wb2R1_2
	BLD R1,3
	RET
odB_Cm_wb2R1_2:
	CPI Mg,2
	BRNE odB_Cm_wb2R1_1
	BLD R1,2
	RET
odB_Cm_wb2R1_1:
	CPI Mg,1
	BRNE odB_Cm_wb2R1_0
	BLD R1,1
	RET
odB_Cm_wb2R1_0:	; Jina moznost neni pripustna -> "natvrdo" nastavime nulty bit
	BLD R1,0
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_A_mul_B:
  ; Nejdrive se otestuje, zda neni A, nebo B nula. V tom pripade je vysledek
  ; predem jasny a nemusi se nic pocitat
	MOV Mg,A_SE	; Zkopirujeme si exponent se znamenkem do Mg
  ; Odstranime znamenko
	CLT	; T-bit do 0
	BLD Mg,7	; a na pozici MSB (znamenka) se zapise nula -> nyni
  ; znamenko nerozhoduje
	CPI Mg,0b01000000	; porovnani s nulou
	BRNE float_A_mul_B_test_B_for_zero
  ; Pokud je A nula, pak i vysledek je nula -> nic se nemusi resit. Vysledek
  ; je ve sve podstate v A, takze neni potreba nic delat
	RET
float_A_mul_B_test_B_for_zero:
	MOV Mg,B_SE
	BLD Mg,7
	CPI Mg,0b01000000
	BRNE float_A_mul_B_calc	; Pokud ani B neni nula, tak se bude muset
  ; holt pocitat

  ; V opacnem pripade staci pouze nahrat exponent B do A
	MOV A_SE,B_SE
	RET	; A konec

float_A_mul_B_calc:
  ; Zjisti se, jake bude vysledne znamenko (kdyz se nasobi dve cisla, tak jsou
  ; pouze 4 moznosti. 1) +A*+B ; 2) +A*-B ; 3) -A*+B ; 4) -A*-B
	SBRS A_SE,7	; Test znamenka u A
	RJMP fAmB_A_is_positive	; pokud bylo znamenko 0, pak se jedna o kladne
  ; cislo
fAmB_A_is_negative:
	SBRS B_SE,7	; To same jako vyse, ale pro cislo B
	RJMP fAmB_An_Bp	; Pokud je B kladne -> skok na navesi
fAmB_An_Bn:	; -A * -B -> vysledne znamenko je +
	RCALL MUL_A_B	; Vynasobi A s B
  ; Vysledne znamenko je + -> 0 -> nemusime uz nic delat. V exponentu je
  ; "defaultne" znamenko nula
	RET
fAmB_An_Bp:	; -A * +B -> -
	RCALL MUL_A_B
	SET	; T-bit do 1
	BLD A_SE,7	; Nastavi se znamenko na -
	RET
fAmB_A_is_positive:
	SBRS B_SE,7
	RJMP fAmB_Ap_Bp
fAmB_Ap_Bn:	; +A * -B -> -
	RCALL MUL_A_B
	SET
	BLD A_SE,7
	RET
fAmB_Ap_Bp:	; +A * +B -> +
	RCALL MUL_A_B	; Vynasobi A s B
  ; Vysledne znamenko je + -> 0 -> nemusime uz nic delat. V exponentu je
  ; "defaultne" znamenko nula
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
MUL_A_B:
	RCALL load_MSB_to_mantis	; To same jako u scitani
  ; Ted se musi vycistit registry, do kterych se prubezne budou ukladat
  ; mezivysledky
	CLR M1	; zde je na pozici 0 LSB pro vysledek
	CLR M2
	CLR M3
	CLR M4
	CLR M5
	CLR M6	; zde je na pozici 7 MSB pro vysledek
	CLR Mg	; Pro pripad, ze bude potreba prenos do vyssiho radu 

  ; Vzorec je nasledujici: (vypocet je rozdelen do 9. casti)
  ; A*B = (2^16*A3 + 2^8*A2 + A1)*(2^16*B3 + 2^8*B2 + B1) =
  ; = 2^32*A3*B3 +	1. cast
  ; + 2^24*A3*B2 +	2. cast
  ; + 2^16*A3*B1 +	3. cast
  ; 
  ; + 2^24*A2*B3 +	4. cast
  ; + 2^16*A2*B2 +	5. cast
  ; + 2^8 *A2*B1 +	6. cast
  ;
  ; + 2^16*A1*B3 +	7. cast
  ; + 2^8 *A1*B2 +	8. cast
  ; +      A1*B1	9. cast
  ;---------------
  ; V podstate 2^n zadavaji rad, kam dana osmice bitu patri. Takze pokud je
  ; zaklad 2^16, pak se spodnich 8 bitu vysledku pricte k M3 a hornich 8 bitu
  ; se pricte do M4. Zaroven se musi hlidat C (prenos do vyssich radu). To by
  ; se pak musela pricit jednicka do M5. A i tady se musi hlidat C atd. atd.
  ; "Graficky" je to zobrazeno nize:
  ;
  ;  Reg.| hodnoty jednotlivych bitu
  ; ------------------
  ; | M6 | 2^40 ~ 2^47
  ; >----<
  ; | M5 | 2^32 ~ 2^39
  ; >----<
  ; | M4 | 2^24 ~ 2^31
  ; >----<
  ; | M3 | 2^16 ~ 2^23
  ; >----<
  ; | M2 | 2^8  ~ 2^15
  ; >----<
  ; | M1 | 2^0  ~ 2^7

  ; Pozn.: vysledky z nasobeni dvou osmibitovych cisel budou v R1:R0

  ; 1. cast A3*B3 -> LSB uslozit do M5
	MUL A_3,B_3	; Vynasobi A_3 s B_3. "C" (Carry, prenos), nemusime
  ; resit. Maximalni cisla, ktera se mohou nasobit jsou 255*255=65025 -> 0xFE01
  ; -> na to R1:R0 musi stacit :) (principielne: maximalni hodnota je 0xFFFF,
  ; coz odpovida cislu: 65635 a to nelze nasobenim dvou 8. bitovych cisel
  ; dosahnout)

	ADD M5,R0	; spodnich 8 bitu se prida do M5 (vysledek je v radu
  ; 2^32)
	ADD M6,R1	; a hornich 8 bitu jsme hodili do M6
  ; Zatim jsme C nemuseli resit, protoze registry M5 a M6 byly prazdne, takze
  ; ani nebylo mozne, aby k prenosu do vyssiho radu doslo. To vsak plati pouze
  ; pro zapisovani do "cistych" registru

  ; 2. cast A3*B2 -> M4
	MUL A_3,B_2	; Vynasobeni A3 s B2
	ADD M4,R0	; spodnich 8 bitu se zapise do M4 -> biz tabulka.
  ; Zapisuje se do "cisteho" registru, takze nemusime resit prenos. Jen pro
  ; upresneni uvedu, ze ADD vypocita vysledek a pokud je vysledek vetsi nez je
  ; kapacita registru (8 bitu), pak C nastavi do 1 (preteceni). Narozdil od ADC
  ; ktery vypocte coucet, prida C a teprve pak vyhodnoti, zda doslo k preteceni
  ; To je vhodne, kdyz secteme dve cisla a potrebujeme pricitat dalsi cisla,
  ; ktera jsou o rad vys
	ADD M5,R1	; Do M5 prictem obsah R1 (hornich 8 bitu z nasobeni).
  ; Protoze ale mohlo dojit k preteceni, tak se musi pripadny C zapsat do M6
	ADC M6,Mg	; Jinymi slovy: do M6 pridej C a Mg. A protoze Mg je
  ; nula, tak se logicky a matematicky prida jen C. A je to!

  ; 3. cast A3*B1 -> M3 (proste uz jen analogie k predchozimu)
	MUL A_3,B_1
	ADD M3,R0	; M3 zatim "cisty"
	ADC M4,R1
	ADC M5,Mg	; A pripadne pridej C
	ADC M6,Mg	; A pokud by nahodou nastalo preteceni u M5 -> musi se
  ; to promitnout do M6

  ; 4. cast A2*B3 -> M4
	MUL A_2,B_3
	ADD M4,R0
	ADC M5,R1
	ADC M6,Mg

  ; 5. cast A2*B2 -> M3
	MUL A_2,B_2
	ADD M3,R0
	ADC M4,R1
	ADC M5,Mg
	ADC M6,Mg

  ; 6. cast A2*B1 -> M2
	MUL A_2,B_1
	ADD M2,R0
	ADC M3,R1
	ADC M4,Mg
	ADC M5,Mg
	ADC M6,Mg

  ; 7. cast A1*B3 -> M3
	MUL A_1,B_3
	ADD M3,R0
	ADC M4,R1
	ADC M5,Mg
	ADC M6,Mg

  ; 8. cast A1*B2 -> M2
	MUL A_1,B_2
	ADD M2,R0
	ADC M3,R1
	ADC M4,Mg
	ADC M5,Mg
	ADC M6,Mg

  ; 9. cast A1*B1 -> M1
	MUL A_1,B_1
	ADD M1,R0
	ADC M2,R1
	ADC M3,Mg
	ADC M4,Mg
	ADC M5,Mg
	ADC M6,Mg
  ; Tak, ted by mel byt vysledek v M6:M1. Zbyva zjistit, kde se nachazi "prvni"
  ; jednicka, protoze vysledek se pak zapisuje do mantisy a prave prvni
  ; jednicka se vynechava.

  ; Ma to zase jedno velke ALE. Pokud doslo k preteceni, pak je na nejvyssim
  ; bite 1, takze se zadna rotace vlastne delat nemusi. ALE: kvuli preteceni
  ; se vypocet exponentu trochu zkomplikuje (vysledny exponent bude o rad vetsi,
  ; nez kdyby nedoslo k preteceni). Takze toto se musi podchytit. A pokud mozno
  ; co nejdrive a problem vyresit co nejefektivneji, protoze cas vypoctu je celkem
  ; zasadni vec.
  	CLR Mg	; Defaultne tedy bude Mg v nule
	SBRC M6,7	; Kontrola MSB bitu
	LDI Mg,0b00001111	; Pokud ale doslo k preteceni -> 1. bit je v jednicce ->
  ; -> Mg se nastavi na nenulovou hodnotu

MUL_A_B_Find_MSB:	; Najde prvni jednicku a zacne ukladat data do mantisy
  ; Idea je nasledujici: Pokud neni nalezena v M6 na pozici 7 jednicka, pak se
  ; provede rotace LVEVO M1 az M6 a opet se hleda jednicka. Az bude jednicka
  ; nalezena, tak se provede jeste jeda rotace VLEVO (tim se "zbavime" prvni
  ; jednicky a M4 az M6 lze pak primo zapsat do mantisy).
	SBRC M6,7	; Kontrola nejvyssiho bitu
	RJMP MUL_A_B_Save_to_mantis	; Pokud byla nalezena jednicka, tak se
  ; pokracuje jeste jednou rotaci a pak se ulozi data do mantisy A

  ; V opacnem pripade se musi provest rotace vlevo
	LSL M1	; Musi se zacit od nejnizsich registru	; Posun vlevo. Na LSB
  ; se dosadi 0
	ROL M2	; v zavislosti, zda byla v M1,7 1, nebo nula, bude tato hodnota
  ; ulozena na LSB M2
	ROL M3	; Atd.
	ROL M4
	ROL M5
	ROL M6
	RJMP MUL_A_B_Find_MSB	; A zkontroluje se, zda neni na M6,7 jednicka

MUL_A_B_Save_to_mantis:
  ; Super, takze jednicka byla nalezena. Takze se provede jeste jedna rotace
	LSL M1
	ROL M2
	ROL M3
	ROL M4
	ROL M5
	ROL M6
  ; A ted ulozit vysledky to mantisy A
	MOV A_3,M6
	MOV A_2,M5
	MOV A_1,M4
  ; A vypocet exponentu
	MOV M1,A_SE	; zkopiruje se A_SE do M1
	MOV M2,B_SE	; zkopiruje se B_SE do M2
	CLT	; T-bit do 0
  ; Zbavime se znamenka cisla jako takoveho
	BLD M1,7
	BLD M2,7
  ; Ted se musi vyresit problem s exponenty. V zasade jsou 4 moznosti
  ; Ea+ Eb+ ; Ea+ Eb- ; Ea- Eb+ ; Ea- Eb-
  ; A v kazdem pripade se musi resit ten problem s pretecenim :(
MUL_A_B_Test_exp:
	SBRS M1,6	; test znamenka exponentu u M1 (V podstate A_SE)
  ; (1 -> - ; 0 -> +)
	RJMP MUL_A_B_Eap	; Ea+ -> skok na dane navesti
MUL_A_B_Ean:	; V opacnem pripade musi byt znamenko zaporne -> Ea-
	SBRS M2,6	; test znamenka exponentu u M2 (zase - B_SE)
	RJMP MUL_A_B_Ean_Ebp	; Eb+ -> skok na dane navesti
MUL_A_B_Ean_Ebn:	; Ea- Eb-
	BLD M1,6	; Zbavime se znamenka exponentu
	BLD M2,6
	ADD M1,M2	; Soucet abs. hodnoty
	SET	; T-bit do 1
	BLD M1,6	; Nastavi se exponent na zaporny
	MOV A_SE,M1	; A vysledny exponent se zkopiruje do A_SE
	SBRS Mg,1	; Kontrola LSB u Mg -> pokud neni 0 -> pak se musi resit
  ; problem s pretecenim
MUL_A_B_Ean_Ebn_end:
	RET	; A hotovo	; Pokud byl LSB v 0 -> nic se nemusi dal resit

  ; Takze pokud se dostaneme sem, pak se musi vyresit problem s pretecenim.
	DEC A_SE	; Tim se snizi hodnota zaporneho exp. -> cislo se de-facto
  ; zvetsi

  ; Vsechno vypada dobre, ale je tu problem. A to za podminky, ze exponent byl
  ; "-1" a po odecteni ma byt v exponentu "0" a ne "-0". Musi byt osetren
  ; i tento pripad
	MOV Mg,A_SE	; prikaz CPI neumi pracovat s registry R0~R15
	CLT	; T-bit = 0
	BLD Mg,7	; Odstrani se znamenko
	CPI Mg,0b01000000	; Porovnani s "nulou"
	BRNE MUL_A_B_Ean_Ebn_end	; Pokud neni vysledek exponentu "nula"
  ; pak uz neni co resit

  ; Pokud se dostaneme sem, tak vlastne pouze staci smazat exp. znamenko
	BLD A_SE,6	; Znamenko exponentu bude kladne -> vse OK (T-bit je
  ; uz nula -> viz. vyse)
	RET	; A hotovo


MUL_A_B_Ean_Ebp:	; Ea- Eb+
	BLD M1,6	; Zbavime se znamenka u exponentu
	CP M2,M1	; porovnani
	BRSH MUL_A_B_Ean_Ebp_M2_minus_M1	; Pokud jen kladny exponent roven,
  ; nebo vetsi jak zaporny (abs. hodnota), tak staci odecist M2-M1
MUL_A_B_Ean_Ebp_M1_minus_M2:
  ; V opacnem pripade se take udela rozdil, ale vysledek bude zaporny,
  ; takze se musi pridat znamenko -
	SUB M1,M2	; M1 = M1-M2
	SET	; T-bit 1
	BLD M1,6	; Nastavi se zaporne znamenko u exponentu
	MOV A_SE,M1
	SBRS Mg,1	; Kontrola LSB u Mg -> pokud neni 0 -> pak se musi resit
  ; problem s pretecenim
MUL_A_B_Ean_Ebp_M1_minus_M2_end:
	RET

	DEC A_SE	; zaporna hodnota exp. se zmensi -> cislo se de-facto
  ; zvetsi

  ; Jeste kontrola "nuly"
	MOV Mg,A_SE	; prikaz CPI neumi pracovat s registry R0~R15
	CLT	; T-bit = 0
	BLD Mg,7	; Odstrani se znamenko
	CPI Mg,0b01000000	; Porovnani s "nulou"
	BRNE MUL_A_B_Ean_Ebp_M1_minus_M2_end	; Pokud neni vysledek exponentu
  ; "nula" pak uz neni co resit

  ; Pokud se dostaneme sem, tak vlastne pouze staci smazat exp. znamenko
	BLD A_SE,6	; Znamenko exponentu bude kladne -> vse OK (T-bit je
  ; uz nula -> viz. vyse)
	RET	; A hotovo


MUL_A_B_Ean_Ebp_M2_minus_M1:
	SUB M2,M1	; M2 = M2-M1
	MOV A_SE,M2	; Znamenko se nemusi nastavovat. Uz je nula
	SBRS Mg,1	; Test LSB - Pokud bude 1 -> preskoci se dalsi
  ; instrukce (Test na preteceni)
	RET
  ; Vysledek bude kladny -> proste se pricte jednicka
	INC A_SE	; Zvyseni exponentu o 1
	RET

MUL_A_B_Eap:	; Ea+
	SBRS M2,6
	RJMP MUL_A_B_Eap_Ebp	; Eb+ -> skok
MUL_A_B_Eap_Ebn:	; Ea+ Eb-
	BLD M2,6	; zbavime se exp. znamenka u M2 (B_SE)
	CP M1,M2
	BRSH MUL_A_B_Eap_Ebn_M1_minus_M2	; Pokud bude kladna cast rovna, nebo
  ; vetsi jak zaporna, pak staci pouze odecist M1-M2

  ; V opacnem pripade je zrejme, ze zaporna cast je vetsi, takze i vysledek bude
  ; zapory. Takze se vypocte rozdil M2-M1 a prida se na konec zaporne znamenko
MUL_A_B_Eap_Ebn_M2_minus_M1:
	SUB M2,M1	; M2=M2-M1
	SET	; T-bit do 1
	BLD M2,6	; nastavi se zaporne znamenko
	MOV A_SE,M2	; A zkopiruje se do vysledku
	SBRS Mg,1	; Opet test na preteceni
MUL_A_B_Eap_Ebn_M2_minus_M1_end:
	RET	; Hotovo (kdyz nedoslo k preteceni)

	DEC A_SE	; Snizi ze zaporne cislo exp. -> zvetsi se cele cislo
  ; o jeden rad

	MOV Mg,A_SE	; prikaz CPI neumi pracovat s registry R0~R15
	CLT	; T-bit = 0
	BLD Mg,7	; Odstrani se znamenko
	CPI Mg,0b01000000	; Porovnani s "nulou"
	BRNE MUL_A_B_Eap_Ebn_M2_minus_M1_end	; Pokud neni vysledek exponentu
  ; "nula" pak uz neni co resit

  ; Pokud se dostaneme sem, tak vlastne pouze staci smazat exp. znamenko
	BLD A_SE,6	; Znamenko exponentu bude kladne -> vse OK (T-bit je
  ; uz nula -> viz. vyse)
	RET	; A hotovo



MUL_A_B_Eap_Ebn_M1_minus_M2:
  ; V opacnem pripade je kladna cast vesti jak zaporna -> vysledek bude kladny
  ; -> M1 - M2
	SUB M1,M2	; M1=M1-M2
	MOV A_SE,M1	; A zkopirovani exponentu do A_SE
	SBRS Mg,1	; Test na preteceni
MUL_A_B_Eap_Ebn_M1_minus_M2_end:
	RET	; Konec ; Pokud nedoslo j preteceni

	INC A_SE	; Zvyseni exp. o 1
	RET


MUL_A_B_Eap_Ebp:	; Ea+ Eb+
  ; Nejjednodussi pripad -> staci jen secist
	ADD M1,M2
	MOV A_SE,M1	; Vysledek se zkopiruje do A_SE
	SBRS Mg,1	; zase test na preteceni
	RET	; A konec

	INC A_SE	; Zvysi se hodnota exp.
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_A_minus_B:
	CLT	; T-bit do 0
  ; Staci pouze zmeni znamenko u B a pak provest soucet
	SBRS B_SE,7	; Pokud bude znamenko zaporne "1" -> nasledujici inst.
  ; se preskoci
	SET	; Nastavi se T-bit do "1"

  ; Takze: pokud bylo znamenko - ("1"), pak T-bit zustal v "0". Pokud bylo
  ; znamenko + ("0"), pak se T-bit nastavil na "1" -> uz jen "prokopirovat"
  ; T-bit na pozici znamenka
	BLD B_SE,7	; Zmena znamenka

  ; Pokud jsou mantisy i exponenty stejne, pak je vysledek nula. Nutno overit
  ; Nejprve zkontrolujeme nejnizsich 8 bitu. Tam je nejmensi pravdepodobnost,
  ; ze cisla budou stejna
	CP A_1,B_1
	BRNE float_A_minus_B_not_EQ	 ; pokud nejsou stejne, pak se
  ; "normalne" pokracuje dal
  ; Pokud ale jsou stejne, musi se "zkoumat" dal
	CP A_2,B_2
	BRNE float_A_minus_B_not_EQ	; Analogie s kodem vyse

	CP A_3,B_3
	BRNE float_A_minus_B_not_EQ

	CP A_SE,B_SE
	BRNE float_A_minus_B_not_EQ
  ; A pokud jsou opravdu vsechny bity rovny (vcetne znamenka), pak je vysledek
  ; nula
	CLR A_1
	CLR A_2
	CLR A_3
	LDI Mg,0b01000000	; Znaci nulu
	MOV A_SE,Mg	; Presun hodnoty Mg do A_SE
	RET	; navrat

float_A_minus_B_not_EQ:
	RCALL float_A_plus_B	; A provede se soucet

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

float_A_plus_B:
	CLT	; Smaze se T-bit (nasvi se na "0")

	SBRS A_SE,7	; Otestuje se MSB -> udava zda je cislo kladne, nebo ne
	RJMP fApB_A_is_positive	; Pokud nebude bit nastaven - nepreskoci se
  ; tato instrkukce
fApB_A_is_negative:	; (-A)
	SBRS B_SE,7	; Test znamena u B
	RJMP fApB_An_Bp	; pokud byl bit na "0", pak se dostaneme sem -> skok
fApB_An_Bn:	; (-A)+(-B)
	RCALL float_operation_prepare_ApB	; pripravi data, ale odstrani
  ; informaci o znamenkach -> do vysledku se pak s tim musi kalkulovat
	BRTS fApB_end	; pokud byl nastaven T-bit -> konec (jedno z cisel nula
  ; -> neni co poradne pocitat, operace jiz provedeny)
	RCALL ADD_A_B	; V podstate staci obe cisla secist, ale pote se musi
  ; pridat zaporne znamenko
	SET
	BLD A_SE,7	; Prida zaporne znamenko 
	RET

fApB_An_Bp:	; (-A)+(+B)
	RCALL float_operation_prepare_ApB	; pripravi data, ale odstrani
  ; informaci o znamenkach -> do vysledku se pak s tim musi kalkulovat
	BRTS fApB_end	; pokud byl nastaven T-bit -> konec (jedno z cisel nula
  ; -> neni co poradne pocitat, operace jiz provedeny)
	SET	; T-bit do 1
	BLD A_SE,7	; A nastavi se (opet) znamenko u A
	RCALL SUB_B_A
	RET

fApB_A_is_positive:	; (+A)
	SBRS B_SE,7	; Test znamenka u B
	RJMP fApB_Ap_Bp	; Skok na (+A) + (+B)

fApB_Ap_Bn:	; (+A)+(-B)
	RCALL float_operation_prepare_ApB	; pripravi data, ale odstrani
  ; informaci o znamenkach -> do vysledku se pak s tim musi kalkulovat
	BRTS fApB_end	; pokud byl nastaven T-bit -> konec (jedno z cisel nula
  ; -> neni co poradne pocitat, operace jiz provedeny)
	SET	; T-bit do 1
	BLD B_SE,7	; A nastavi se (opet) znamenko u B
	RCALL SUB_A_B
	RET

fApB_Ap_Bp:	; (+A) + (+B) - vysledne znamenko je kladne (0)
	RCALL float_operation_prepare_ApB	; pripravi data
	BRTS fApB_end	; pokud byl nastaven T-bit -> konec (jedno z cisel nula
  ; -> neni co poradne pocitat, operace jiz provedeny)
	RCALL ADD_A_B	; soucet - A = A + B
  ; Vyse volany podprogram znamenko smazal na "0" -> kladne cislo -> nemusi
  ; se nic resit (podprogram vzdy smaze toto znamenko, protoze ani nema smysl
  ; ho uchovavat, kdyz se pokazde scitaji cisla "jinak")
  ; Protoze kladne a kladne cislo da dohromady zase kladne

  ; Vysledek je tedy ulozen ve floatu "A"

fApB_end:
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_A_div2:	; Vezme cislo ulozene v A a vydeli ho dvema
  ; Kontrola, jestli se nejedna o nulu -> to by pak nemelo smysl
	MOV Mg,A_SE	; Stahneme si exponent do Mg
	CPI Mg,0b01000000
	BREQ float_A_div2_end	; Pokud se jedna o nulu -> konec


  ; Urceni znamenka exponentu. Pokud bude cislo kladne, pak se abs. hodnota
  ; exponentu bude snizovat. Pokud bude cislo zaporne (exponent), pak se abs.
  ; hodnota bude zvysovat
	SBRS A_SE,6	; "Proklepneme" si znamenko exponentu. 1 -> preskoci
  ; nasledujici instrukci
	RJMP f_A_d2_exp_positive
f_A_d2_exp_negative:
  ; Exponent je zaporny
	INC A_SE	; jen zvetsime "zapornost" exponentu. Tady neni zadna
  ; zrada (mimo preteceni, ale to by muselo byt cislo s exponentem 64 -> cislo
  ; by muselo byt velke 2^64. A to je opravdu dost)
	RET

f_A_d2_exp_positive:
  ; Exponent je kladny

  ; Do Mg si ulozime absolutni hodnotu exponentu
	LDI Mg,0b00111111	; Maska pro AND
	AND Mg,A_SE	; Zkopiruji se jen spodnich 6 bitu -> nemusime resit
  ; znamenka

  ; ted si overime, zda neni abs. hodnota exponentu nula. To by pak znamenalo,
  ; ze vlastne musime zapsat ne -1 (to by se zapsalo 255), ale musime opravdu
  ; zapsat -1 (cislo neni ve dvojkovem doplnku)
	CPI Mg,0
	BREQ f_A_d2_make_negative

  ; Pokud nebyl exponent nula, pak se proste zmensi jeho hodnota
	DEC A_SE

float_A_div2_end:
	RET	; A ted honem pryc

f_A_d2_make_negative:
  ; Takze pokud se dostaneme sem, tak misto exponentu nula, mame napsat
  ; exponent jedna a zmenit znamenko
	SET	; T-bit do 1
	BLD A_SE,6	; Nastavi znamenko exponentu na zaporne (pokud by
  ; totiz byl exponent "zaporna" nula, pak se jedna o nulu. A tu jsme osetrili
  ; uz vyse)
	INC A_SE	; Zvyseni o 1 na 1 ;-)
	RET	; A hotovo
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_B_div2:	; Vezme cislo ulozene v B a vydeli ho dvema
  ; Kontrola, jestli se nejedna o nulu -> to by pak nemelo smysl
	MOV Mg,B_SE	; Stahneme si exponent do Mg
	CPI Mg,0b01000000
	BREQ float_B_div2_end	; Pokud se jedna o nulu -> konec


  ; Urceni znamenka exponentu. Pokud bude cislo kladne, pak se abs. hodnota
  ; exponentu bude snizovat. Pokud bude cislo zaporne (exponent), pak se abs.
  ; hodnota bude zvysovat
	SBRS B_SE,6	; "Proklepneme" si znamenko exponentu. 1 -> preskoci
  ; nasledujici instrukci
	RJMP f_B_d2_exp_positive
f_B_d2_exp_negative:
  ; Exponent je zaporny
	INC B_SE	; jen zvetsime "zapornost" exponentu. Tady neni zadna
  ; zrada (mimo preteceni, ale to by muselo byt cislo s exponentem 64 -> cislo
  ; by muselo byt velke 2^64. A to je opravdu dost)
	RET

f_B_d2_exp_positive:
  ; Exponent je kladny

  ; Do Mg si ulozime absolutni hodnotu exponentu
	LDI Mg,0b00111111	; Maska pro AND
	AND Mg,B_SE	; Zkopiruji se jen spodnich 6 bitu -> nemusime resit
  ; znamenka

  ; ted si overime, zda neni abs. hodnota exponentu nula. To by pak znamenalo,
  ; ze vlastne musime zapsat ne -1 (to by se zapsalo 255), ale musime opravdu
  ; zapsat -1 (cislo neni ve dvojkovem doplnku)
	CPI Mg,0
	BREQ f_B_d2_make_negative

  ; Pokud nebyl exponent nula, pak se proste zmensi jeho hodnota
	DEC B_SE

float_B_div2_end:
	RET	; A ted honem pryc

f_B_d2_make_negative:
  ; Takze pokud se dostaneme sem, tak misto exponentu nula, mame napsat
  ; exponent jedna a zmenit znamenko
	SET	; T-bit do 1
	BLD B_SE,6	; Nastavi znamenko exponentu na zaporne (pokud by
  ; totiz byl exponent "zaporna" nula, pak se jedna o nulu. A tu jsme osetrili
  ; uz vyse)
	INC B_SE	; Zvyseni o 1 na 1 ;-)
	RET	; A hotovo
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_A_mul2:	; Vezme cislo ulozene v A a vynasobi ho dvema
  ; Kontrola, jestli se nejedna o nulu -> to pak nema smysl

  ; De-facto je cely algoritmus stejny jako pro float_A_div2, ale s tim
  ; rozdilem, ze zde se pocita "opacnym" smerem a tedy vyjimka je zde pokud
  ; se pohybujeme od zapornych cisel do nuly (musi se zmenit znamenko)
	MOV Mg,A_SE
	CPI Mg,0b01000000
	BREQ float_A_mul2_end

	SBRC A_SE,6	; kontrola znamenka
	RJMP f_A_m2_exp_negative
f_A_m2_exp_positive:
  ; Kladny exponent
	INC A_SE	; exp+1
	RET

f_A_m2_exp_negative:
  ; Zaporny exponent -> musi se resit vyjimka (z -1 do 0)
	LDI Mg,0b00111111
	AND Mg,A_SE
	CPI Mg,1	; test na -1 (bereme abs. hodnotu diky AND masce)
	BREQ f_A_m2_make_positive
  ; Pokud se nejednalo o -1, pak se v podstate nemusi nic resit
	DEC A_SE
float_A_mul2_end:
	RET

f_A_m2_make_positive:
	CLT
	BLD A_SE,6	; Cislo je nyni zaporne
	DEC A_SE	; Z -1 se nyni stala 0
	RET  
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_B_mul2:	; Vezme cislo ulozene v B a vynasobi ho dvema
  ; Kontrola, jestli se nejedna o nulu -> to pak nema smysl

  ; De-facto je cely algoritmus stejny jako pro float_B_div2, ale s tim
  ; rozdilem, ze zde se pocita "opacnym" smerem a tedy vyjimka je zde pokud
  ; se pohybujeme od zapornych cisel do nuly (musi se zmenit znamenko)
	MOV Mg,B_SE
	CPI Mg,0b01000000
	BREQ float_B_mul2_end

	SBRC B_SE,6	; kontrola znamenka
	RJMP f_B_m2_exp_negative
f_B_m2_exp_positive:
  ; Kladny exponent
	INC B_SE	; exp+1
	RET

f_B_m2_exp_negative:
  ; Zaporny exponent -> musi se resit vyjimka (z -1 do 0)
	LDI Mg,0b00111111
	AND Mg,B_SE
	CPI Mg,1	; test na -1 (bereme abs. hodnotu diky AND masce)
	BREQ f_B_m2_make_positive
  ; Pokud se nejednalo o -1, pak se v podstate nemusi nic resit
	DEC B_SE
float_B_mul2_end:
	RET

f_B_m2_make_positive:
	CLT
	BLD B_SE,6	; Cislo je nyni zaporne
	DEC B_SE	; Z -1 se nyni stala 0
	RET  
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_SQRT_A:	; Vypocte druhou odmocninu z A
  ; Nejprve se udela odhad, kolik iteraci bude asi potreba udelat. Je zbytecne
  ; resit vic desetinnych mist, nez 23, protoze jemnejsi rozliseni stejne float
  ; nenabizi. Na druhou stranu, maly pocet iteraci bude mit za nasledek
  ; nepresny vysledek.
  ; Toto optimum se da odhadnout podle velikosti exponentu

  ; Overeni, zda neni cislo zaporne. Pokud by tomu tak bylo, pak neni mozne
  ; vypocitat odmocninu. V takovem pripade se proste bude znamenko ignorovat
  ; a "smaze se"
	CLT
	BLD A_SE,7	; Pokud bylo cislo zaporne, tak uz neni :)


  ; zaloba B - jde o to, ze pocitame "pouze" s A, ale proste na vypocty je
  ; potreba i druha promenna. Takze aby uzivatel nebyl zmaten, ze dal vypocitat
  ; neco z A a ze v cislu B ma uplne jine hodnoty
	PUSH B_SE
	PUSH B_3
	PUSH B_2
	PUSH B_1

  ; zaloha A - bude jeste zapotrebi
	CALL Save_A_to_x4	; x4 = odmocnovane cislo


  ; Pocet iteraci se vypocita nasledovne: n = |exp|*2 +1
  ; Pokud by n<5 -> n=5
	LDI Mg,0b00111111	; Maska pro AND,
	AND Mg,A_SE	; ktera zpusobi, ze se zkopiruje jen hodnota, bez
  ; znamenek
	CPI Mg,2	; porovnani s 2
	BRSH f_SQRT_A_calc_num_of_iter	; Pokud je exponent vetsi, nebo roven
  ; 2, pak se pocet kroku bude pocitat.

  ; V opacnem pripade se pocet iteraci nastavi na 5
	LDI Mg,5
	MOV M1,Mg	; M1 - pocita iterace

	RJMP f_SQRT_A_make_guess

f_SQRT_A_calc_num_of_iter:
  ; M1=2*Mg+1 (M1 - pocita iterace ; Mg - velikost exponentu)
	MOV M1,Mg	; M1=Mg
	LSL M1		; M1=2*M1
	INC M1		; M1=M1+1

f_SQRT_A_make_guess:
  ; ted se provede prvni odhad. A to podle exponentu. Pokud bude kladny, pak
  ; bude cislo vetsi jak 1 a pokud vynasobime A*0.5 dostaneme celkem rozumny
  ; odhad. Naopak, pokud bude cislo mensi jak 1, pak se provede A*2
	SBRS A_SE,6	; Otuka se znamenko exponentu
	RJMP f_SQRT_A_guess_positive	; Pokud je exp. kladny
f_SQRT_A_guess_negative:	; Pokud je exp. zaporny
  ; mensi jak 1 -> A*2
	CALL float_A_mul2	; A=A*2		; ODHAD
	RJMP f_SQRT_A_calc_SQRT

f_SQRT_A_guess_positive:
	CALL float_A_div2	; A=A*0.5	; ODHAD

  ; Pote se aplikuje vzorec x1=0.5*(x0 + (x4/x0))
    ; kde x0 je predchozi iterace (odhad) a x1 je aktualni odhad
f_SQRT_A_calc_SQRT:
  ; Musi se zalohovat registry. Vypocty "pohlti" temer vsechny volne registry
	PUSH M1	; M1 - pocet zbyvajicich iteraci - zalohujeme

	CALL Save_A_to_x0	; A => x0 (x0 odpovida x0 ve vzorci)

	CALL float_A_to_B	; x0(A) => B

	CALL Save_x4_to_A	; x4 => A (x4 odpovida x4 ve vzorci)

	CALL float_A_div_B	; A=x4/x0

	CALL Save_x0_to_B	; B=x0

	CALL float_A_plus_B	; A=x0+(x4/x0)

	CALL float_A_div2	; A=0.5*(x0+(x4/x0))
  ; takze nyni je v A ulozen vysledek aktualni iterace

	POP M1
	DEC M1	; Pocet iteraci-1
	BRNE f_SQRT_A_calc_SQRT	; A dokud nebude rovno nule, opakuj



  ; Obnova registru B
	POP B_1
	POP B_2
	POP B_3
	POP B_SE

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
float_operation_prepare_ApB:
  ; Musi se zjistit, ktery exponent je vetsi, resp. jestli jsou vubec rozdilne
  ; a potom zjistovat, ktery je vetsi
	MOV M1,A_SE
  ; Obsah "A_SE" se zkopiroval do M1, ale potrebujeme se zbavit znamenka
  ; (celkoveho cisla)
	CLT	; Smaze se T-bit
	BLD M1,7	; A zkopiruje se na pozici 7 (MSB -> smaze se znamenko)
	MOV M2,B_SE	; To same, ale pro B
	BLD M2,7

  ; Kontrola nuly - v takovem pripade je vysledek roven tomu cislu, ve kterem
  ; neni nula, to da rozum :)

  ; Nyni se musi zjistit, zda neni zbytek
  ; exponentu same nuly -> jinymi slovy porovname exponent s cislem 0b01000000
  ; Pokud bude roven, pak se jedna o nulu a v klidu muzeme za vysledek dosadit
  ; B, at uz je jakekoli (i nula) - pozn. prvni bit je vzdy nula. Je to diky
  ; rotaci
	MOV Mg,M1
	CPI Mg,0b01000000	; CPI nelze provest s registry R0~R15 - proto
  ; se provadi operace s Mg
	BRNE fo_pAB_test_for_zero_B	; pokud se nerovna, pak neni nula
  ; a otestuje se B
  ; Pokud se tedy jednalo o nulu, pak se provede nasledujici procedura:
  ; (zkopirje se obsah B do A - vysledek je ulozen v A kvuli uspore pameti- ) 
	MOV A_SE,B_SE
	MOV A_3,B_3
	MOV A_2,B_2
	MOV A_1,B_1
	SET	; Nastavi se T-bit -> znaci, ze neni jiz potreba nic pocitat
	RET
fo_pAB_test_for_zero_B:	; Kontrola, zda B neni nula
	MOV Mg,M2
	CPI Mg,0b01000000
	BRNE fo_pAB_not_a_zero	; pokud ani B neni nula, pak se provede
  ; "klasicky" soucet

  ; Pokud je B nula, pak ulozime jako vysledek A do A -> jinymi slovy: vysledek
  ;  je uz ulozen v A -> pouze RET
	SET	; Nastavi se T-bit -> znaci, ze neni jiz potreba nic pocitat

	RET

fo_pAB_not_a_zero:	; takze ani jeden clen neni nula, takze se bude pocitat
	RCALL load_MSB_to_mantis	; 1. bit je vzdy "1" a neni ulozen
  ; v mantise. Pro vypocty je ale nutne s timto bitem pocitat -> provede
  ; rotaci VPRAVO a na MSB ulozi "1"

	CP M1,M2	; Porovname exponenty
	BRNE float_operation_prepare_ApB_E_Neq

	RET	; pokud jsi sou rovny exponenty, pak se jen sectou mantisy ->
  ; -> neni potreba provadet dalsi operace

float_operation_prepare_ApB_E_Neq:
  ; Musi se zjistit, ktery exponent je vetsi a podle toho provest rotaci.

  ; Nejdrive se vyresi problem se zapornymi cisly (tzn. ktera maji "1" na
  ; 6. bitu). Musime vzit v uvahu, ze pokud budeme brat znamenkovy bit ne jako
  ; znamenkovy, ale jako cislo, tak plati, ze cim je zaporne cislo "vetsi", tim
  ; je ve skutecnosti mensi ( -5>-10 )

  ; Zkontroluje se, zda A neni zaporne
	SBRS M1,6	; 6. bit - znamenkovy
	RJMP fo_pAB_Ea_positive	; pokud neni nastaven, pak je exponent A kladny

  ; Takze ted je jiste, ze A je zaporne (exponent) -> Ea -
	SBRS M2,6	; otukame si B
	RJMP fo_pAB_EaN_EbP	; pokud neni B zaporne (E), pak je A zaporne
  ; a B kladne -> skok na dane navesti
fo_pAB_EaN_EbN:	; Ea - ; Eb -
  ; tak ted zjistit, ktery exponent je vetsi
	CP M1,M2	; porovname je
	BRLO fo_pAB_EaN_EbN_M1	;  Pokud je M1 mensi -> pak je M1 vlasne
  ; vetsi (zaporna cisla) -> provest rotaci VPRAVO u mantisy B o rozdil
  ; abs(M1)-abs(M2) -> M2-M1 -> Vysledek bude v radu vetsiho cisla

  ; V opacnem pripade je logicky vetsi M2 -> pak je vlasne M2 mensi ->
  ; abs(M1)-abs(M2) -> M1-M2 -> rotace VPRAVO A o rozdil exponentu
	SUB M1,M2	; vypocita se delta, vysledek je v M1

	RJMP fo_pAB_rotate_A
fo_pAB_EaN_EbN_M1:
	SUB M2,M1	; M2 = M2-M1
  ; Takze ted je delta ulozena v M2, ale je potreba ji ulozit do M1 ->
  ; -> neni nic jednodussiho, nez MOV
	MOV M1,M2

	RJMP fo_pAB_rotate_B
; *-----------------------------------------*
fo_pAB_EaN_EbP:	; Ea - ; Eb +
  ; Uz ze znamenek je jasne, ze Ea se bude rotovat VPRAVO -> rotace A
  ; Ted jen spravne vypocitat rozdil. Problem je v tom ,ze jedno cislo je
  ; zaporne a druhe kladne. Rozdil muze byt teoreticky maximalne 2*63 = 126
  ; protoze exponent jako takovy je 7. bitovy, ale 7. bit udava znamenko, takze
  ; v hodnotach muze nabyvat cisel od -63 do +63 -> rozdil je max 126 -> to se
  ; do 8. botoveho registru vejde s prehledem

  ; pri volani funkce fo_pAB_rotate_A se pocita delta jako M2-M1 -> musime
  ; vyplnit hodnoty M1 a M2 tak, aby po jejich rozdilu vysla delta
	CLT
	BLD M1,6	; Ea nastavime jako kladny
	ADD M1,M2	; Secteme obe hodnoty - tim mame deltu uz ulozenou
  ; v M1
	RJMP fo_pAB_rotate_A	; A skok na algortitmus, ktery provede rotaci
; *-----------------------------------------*
fo_pAB_rotate_B:	; ROTACE B o DELTA (delta=M1)
	LSR B_3
	ROR B_2
	ROR B_1
	DEC M1
	BRNE fo_pAB_rotate_B	; A dokud nebude M1=0 opakuj

	MOV M1,A_SE	; B se rotuje -> exponent A je vysledek
	BLD M1,7	; smaze se info o znamenku
	RET
;--
fo_pAB_rotate_A:	; ROTACE A o DELTA (delta=M1)
	LSR A_3
	ROR A_2
	ROR A_1
	DEC M1
	BRNE fo_pAB_rotate_A	; A dokud nebude M1=0 opakuj

  ; Vetsi exponent je B (protoze se provadi rotace s A), takze do M1
  ; (vysledek) se ulozi exponent z B
	MOV M1,B_SE
	BLD M1,7	; A smaze se info o znamenku (ridi si programy, ktere
  ; volaji podprogram "float_operation_prepare_ApB")
	RET
; *-----------------------------------------*
fo_pAB_Ea_positive:	; Ea +
  ; Takze ted vime, ze exponent A je kladny, ale musi se jeste otukat B
	SBRS M2,6
	RJMP fo_pAB_EaP_EbP	; Pokud bude kladne -> RJMP
fo_pAB_EaP_EbN:	; V opacnem pripade je stav jasny: Ea + ; Eb -
  ; V tomto pripade je jasne, ze Ea je vetsi (posune se B). Takze se zase
  ; provede vypocet delty a smaze se M2 (tam se pocita M1-M2)
	CLT
	BLD M2,6	; M2 bude razem kladne :D
	ADD M1,M2	; M1 = M1+M2 = delta

	RJMP fo_pAB_rotate_B
; *-----------------------------------------*
fo_pAB_EaP_EbP:	; Ea + ; Eb +
	CP M1,M2
	BRLO fo_pAB_EaP_EbP_M1	; M1<M2 -> Ea<Eb -> Rotace A
  ; V opacnem pripade plati, ze M1>M2 -> Ea>Eb -> Rotace B
	SUB M1,M2	; M1 = M1-M2

	RJMP fo_pAB_rotate_B
fo_pAB_EaP_EbP_M1:
	SUB M2,M1
	MOV M1,M2

	RJMP fo_pAB_rotate_A
; *-----------------------------------------*
ADD_A_B:
  ; A = A + B 
	ADD A_1,B_1
	ADC A_2,B_2	; pokud byl pri predchozi operaci nastaven Carry
  ; (preteceni), pak se s tim pocita i tady
	ADC A_3,B_3

  ; Soucet je ulozen v A
  ; Takze ted je soucet kompletni. ALE: pokud bude nyni nastaven C, pak to
  ; znamena, ze soucet je v dalsim radu -> musi se vysledek posunout VPRAVO,
  ; zvysit exponent o 1 a na MSB vlozit "1" - tato 1 je ulozena vlasne v C
	BRCC ADD_A_B_ApB_end	; Pokud neni C nastaven, pak se
  ; provede "standardni" procedura - odstranime MSB a celou mantisu posuneme
  ; VLEVO

  ; Pokud je C nastaven, pak nastava tahle sranda:
	ROR A_3
	ROR A_2
	ROR A_1
  ; Ted se musime rozhodnout, jestli se ma exponent zvetsit, nebo zmensit.
  ; Aby to nebylo tak jednoduche, je tu hned nekolik moznosti.
  ; (1) Exponent je zaporny -> DEC M1 a nedojde k preteceni (napr. z -4 na -3)
  ; (2) Exponent je kladny -> INC (preteceni se neresi, exp. by musel byt 255)
  ; (3) Exponent je zaporny -> DEC M1 ale DOJDE k preteceni (jedina moznost:
  ;	Z -1 na 0 - musi se smazat znamenko)

	SBRS M1,6	; Test na znamenko exponentu
	RJMP ADD_A_B_ApB_exp_positive	; Pokud je kladne, skoci se sem

  ; Pokud se dostaneme sem, pak je znamenko zaporne. Nyni se budeme rozhodovat
  ; mezi moznosti (1) a (3), pricemz moznost (3) je nejvic slozita
	LDI Mg,0b00111111	; "Maska" pro AND
	AND Mg,M1	; Do Mg se ulozi jen spodnich 6 bitu

	CPI Mg,0b00000001	; Porovnani s jednickou (cislo je nyni v abs.
  ; hodnote -> exponent je stale zaporny)
	BRNE ADD_A_B_ApB_exp_negative
  ; Pokud se PC dostane sem, pak se jedna o danou vyjimku. Ta se da celkem
  ; rychle vyresit, vzhedem k tomu, ze prvni bit se stejne prepise, staci
  ; do M1 ulozit "natvrdo" jasne danou hodnotu
	LDI Mg,0b00000000	; Z -1 se stane +0
	MOV M1,Mg	; A presun do M1
	RJMP ADD_A_B_ApB_end	; A skok na reseni

ADD_A_B_ApB_exp_negative:
	DEC M1	; Zaporne cislo se "zvetsi" (bude mene zaporne -> zvetsi)
	RJMP ADD_A_B_ApB_end

ADD_A_B_ApB_exp_positive:
	INC M1	; V M1 je vlastne ulozena hodnota exponentu - s pretecenim se
  ; NEPOCITA!!! S tak vysokymi cisly proste pocitat nebude :D Navic by
  ; kontrolni algoritmy jenom zpomalovaly cely proces a spravneho vysledku by
  ; se stejne nedosahlo
ADD_A_B_ApB_end:
  ; takze ted se odebere MSB a posune se CELA matisa VLEVO. Navic se do A_SE
  ; ulozi M1 (exponent)
	LSL A_1	; posuneme nejnizsich 8 bitu vlevo
	ROL A_2	; A podle C se posune i dalsich 8 bitu
	ROL A_3	; Az na konec se posune i poslednich 8 bitu.
  ; Nyni by C melo byt vzdy 1, protoze nejvyssi bit se "schova" prave do C

  ; ted zbyva uz jenom doresit exponent
	MOV A_SE,M1	; Znamenko bude kladne ("0" - ulozeno pri rotaci, nebo
  ; jinde). Tento podprogram "umi" pracovat pouze se dvema kladnymi cisly,
  ; takze vysledek musi byt take kladny
	RET
; *-----------------------------------------*
SUB_A_B:
  ; A = A - B
  ; Jeste se musi provest kontrola, zda neni vysledek roven nule! To by pak
  ; znamenalo, ze A_SE musi byt: 0b01000000 (znaci ze cislo je nula)
  ; Vysledek bude roven nule jen za predpokladu, ze obe cisla jsou stejna
  ; (jejich posuvy jsou jiz vyreseny z minule)
	CP A_1,B_1	; Nejprve se porovnaji LSB -> nejmensi pravdepodobnost,
  ; ze si budou rovny
	BRNE SUB_A_B_Neq	; Pokud si nejsou rovny -> provede se
  ; standardni procedura
  ; V opacnem pripade se zkontroluji dalsi bity
	CP A_2,B_2
	BRNE SUB_A_B_Neq
	CP A_3,B_3
	BRNE SUB_A_B_Neq
  ; pokud se dostaneme sem, pak to znamena, ze obe cisla jsou stejna ->
  ; -> vysledek je nula
	LDI Mg,0b01000000	; Znaci nulu
	MOV A_SE,Mg	; zkopiruje se do A_SE
  ; Nasledujici 3 radky by se nemusely provadet, ale takhle je to uplne jasne
  ; (napriklad v simulatoru)
	CLR A_3
	CLR A_2
	CLR A_1
	RET

SUB_A_B_Neq:
	CLT
	CLR Mg	; Casem se mozna vyuzje - pri odcitani exponentu

	; Zaloha A_3:1 - pokud se ukaze, ze |B|>|A|, pak bude potreba obnovit A
	MOV M4,A_3
	MOV M3,A_2
	MOV M2,A_1

	SUB A_1,B_1
	SBC A_2,B_2
	SBC A_3,B_3
  ; odecitani skoro u konce. Pokud bude nastaven C (carry), pak to znamena, ze
  ; |B|>|A| -> vysledne cislo je zaporne
	BRCC SUB_A_B_MSB_check	; pokud nebylo C nastaveno, pak se porvede skok
	RCALL SUB_A_B_recalc_B_A	; Tak a je to v troube. Vysledek je proste blbe
  ; Problem je, ze zaporne B je vetsi jak kladne A. Takze se na to pujde od
  ; lesa a vypocte se B-A a znamenko se manualne nastavi na zaporne. A je to!
SUB_A_B_MSB_check:
  ; Ted se jeste musi zkontrolovat, jestli neni MSB v nule -> musela by se
  ; provest rotace VLEVO, dokud by se "nenarazilo" na "1"
  ; (Priklad: 110010b - 110001b = 000001b)
	SBRC A_3,7	; Pokud MSB=0 -> nasledujici instrukce se preskoci
	RJMP SUB_A_B_MSB_check_OK	; pokud je MSB=1 -> asi je to OK :)

  ; Kontrolni algortimus
    ; Provede se rotace VLEVO
	LSL A_1
	ROL A_2
	ROL A_3

	RCALL Dec_M1
	RJMP SUB_A_B_MSB_check

SUB_A_B_MSB_check_OK:
	BLD M1,7	; pokud byl C v "1" -> T bit se zkopiruje do M1 na MSB
	LSL A_1
	ROL A_2
	ROL A_3
	MOV A_SE,M1

	RET


Dec_M1:
  ; Pokud je aktualni hodnota nula, pak se nesmi pouzit DEC, protoze by
  ; vysledek byl 1111 1111b -> 255 a to je spatne -> musi se ulozit 1000 0001,
  ; coz symbolizuje -1
	CP M1,Mg	; Porovnej M1 a 0 (osah Mg byl smazan)
	BREQ Dec_M1_set_negative

	SBRC M1,6	; Test, zda se ma odecitat, nebo pricitat
	INC M1	; Pokud je exponent zaporny, pak se musi M1 zvysit (ciselne se
  ; zvysi, ale je to zaporne cislo ,takze cim je "vice zaporne", tim je vlastne
  ; mensi)
	SBRS M1,6	; Test na "kladny exponent"
	DEC M1

	RET
Dec_M1_set_negative:
	LDI Mg,0b01000001	; Nastavi se exponent na -1
	MOV M1,Mg	; A ulozise do Mg
	RET

SUB_A_B_recalc_B_A:	; A = -(B-A)
  ; Obnova A
	MOV A_3,M4
	MOV A_2,M3
	MOV A_1,M2

	SUB B_1,A_1
	SBC B_2,A_2
	SBC B_3,A_3

  ; Nezapomenout vysledek ulozit do A!
	MOV A_1,B_1
	MOV A_2,B_2
	MOV A_3,B_3

	SET	; T-bit se nastavi do "1" -> casem bude zapsan jako znamenko

	RET
; *-----------------------------------------*
SUB_B_A:	; Analogie s "SUB_A_B"
  ; A = B - A
	CLT
	CLR Mg

	; Zaloha B_3:1 (pro pripad, ze |A|>|B| )
	MOV M4,B_3
	MOV M3,B_2
	MOV M2,B_1

	SUB B_1,A_1	; B = B-A (pak se vysledek musi preulozit do A)
	SBC B_2,A_2
	SBC B_3,A_3

	BRCC SUB_B_A_MSB_check
	RCALL SUB_B_A_recalc_A_B
SUB_B_A_MSB_check:
	SBRC B_3,7
	RJMP SUB_B_A_MSB_check_OK

	LSL B_1
	ROL B_2
	ROL B_3

	RCALL Dec_M1
	RJMP SUB_B_A_MSB_check

SUB_B_A_MSB_check_OK:
	BLD M1,7
	LSL B_1
	ROL B_2
	ROL B_3
	MOV A_SE,M1
  ; A ted mantisu z B preulozit do A
	MOV A_3,B_3
	MOV A_2,B_2
	MOV A_1,B_1

	RET

SUB_B_A_recalc_A_B:	; B=-(A-B)
  ; Obnova B
	MOV B_3,M4
	MOV B_2,M3
	MOV B_1,M2

	SUB A_1,B_1
	SBC A_2,B_2
	SBC A_3,B_3

  ; Nezapomenout vysledek ulozit do B!
	MOV B_1,A_1
	MOV B_2,A_2
	MOV B_3,A_3

	SET

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
load_MSB_to_mantis:
  ; "prvni neviditelny bit" (ve float se nepouziva,
  ; protoze hodnota ve float vzdy zacina "1" -> zbytecne tuto informaci
  ; uchovavat) - pro vypocty je ale tato informace nutna

	SEC	; Nastavime C do 1
	ROR A_3	; A provede se rotace vpravo, ale C se vlozi na MSB a hodnota
  ; v LSB se ulozi do C -> takze v C je ted ulozena "MSB" hodnota pro dalsi
  ; rad
	ROR A_2	; A dokola...
	ROR A_1	; Ted je v C hodnota nejnizsiho bitu, ktery je nyni jiz
  ; "nezajimavy"
	SEC 	; Analogicky to same, ale pro B
	ROR B_3
	ROR B_2
	ROR B_1

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
  ; Musi se zacit od nejnizsiho radu kvuli preteceni. Pri vypoctech se prvne
  ; zacina nejnizsi hodnotou, prave kvuli preteceni. A protoze instrukce LPM
  ; nezna neco jako LPM tmp,Z- (Z- je problem), tak musi byt i poradi REVERZNI)

; Tyto hodnoty zabiraji 1300 bajtu (jen tak pro zajimavost)
Val_2em32_20d:
.DB 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em31_20d:
.DB 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em30_20d:
.DB 9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em29_20d:
.DB 8,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em28_20d:
.DB 7,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em27_20d:
.DB 4,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em26_20d:
.DB 9,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em25_20d:
.DB 8,9,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em24_20d:
.DB 6,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em23_20d:
.DB 2,9,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em22_20d:
.DB 4,8,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em21_20d:
.DB 8,6,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em20_20d:
.DB 6,3,5,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em19_20d:
.DB 3,7,0,9,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em18_20d:
.DB 6,4,1,8,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em17_20d:
.DB 3,9,2,6,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em16_20d:
.DB 7,8,5,2,5,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em15_20d:
.DB 5,7,1,5,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em14_20d:
.DB 1,5,3,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em13_20d:
.DB 3,0,7,0,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em12_20d:
.DB 6,0,4,1,4,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em11_20d:
.DB 2,1,8,2,8,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em10_20d:
.DB 5,2,6,5,6,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em09_20d:
.DB 0,5,2,1,3,5,9,1,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em08_20d:
.DB 0,0,5,2,6,0,9,3,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em07_20d:
.DB 0,0,0,5,2,1,8,7,0,0,0,0,0,0,0,0,0,0,0,0
Val_2em06_20d:
.DB 0,0,0,0,5,2,6,5,1,0,0,0,0,0,0,0,0,0,0,0
Val_2em05_20d:
.DB 0,0,0,0,0,5,2,1,3,0,0,0,0,0,0,0,0,0,0,0
Val_2em04_20d:
.DB 0,0,0,0,0,0,5,2,6,0,0,0,0,0,0,0,0,0,0,0
Val_2em03_20d:
.DB 0,0,0,0,0,0,0,5,2,1,0,0,0,0,0,0,0,0,0,0
Val_2em02_20d:
.DB 0,0,0,0,0,0,0,0,5,2,0,0,0,0,0,0,0,0,0,0
Val_2em01_20d:
.DB 0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0
Val_2e00_20d:
.DB 0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0
Val_2e01_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0
Val_2e02_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0
Val_2e03_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0
Val_2e04_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,1,0,0,0,0,0,0,0,0
Val_2e05_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,3,0,0,0,0,0,0,0,0
Val_2e06_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,6,0,0,0,0,0,0,0,0
Val_2e07_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,2,1,0,0,0,0,0,0,0
Val_2e08_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,5,2,0,0,0,0,0,0,0
Val_2e09_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,1,5,0,0,0,0,0,0,0
Val_2e10_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,2,0,1,0,0,0,0,0,0
Val_2e11_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,4,0,2,0,0,0,0,0,0
Val_2e12_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,9,0,4,0,0,0,0,0,0
Val_2e13_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,9,1,8,0,0,0,0,0,0
Val_2e14_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,8,3,6,1,0,0,0,0,0
Val_2e15_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,6,7,2,3,0,0,0,0,0
Val_2e16_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,3,5,5,6,0,0,0,0,0
Val_2e17_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,7,0,1,3,1,0,0,0,0
Val_2e18_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,4,1,2,6,2,0,0,0,0
Val_2e19_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,8,2,4,2,5,0,0,0,0
Val_2e20_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,7,5,8,4,0,1,0,0,0
Val_2e21_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,5,1,7,9,0,2,0,0,0
Val_2e22_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,0,3,4,9,1,4,0,0,0
Val_2e23_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,0,6,8,8,3,8,0,0,0
Val_2e24_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,1,2,7,7,7,6,1,0,0
Val_2e25_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,3,4,4,5,5,3,3,0,0
Val_2e26_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,6,8,8,0,1,7,6,0,0
Val_2e27_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,2,7,7,1,2,4,3,1,0
Val_2e28_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,5,4,5,3,4,8,6,2,0
Val_2e29_20d:
.DB 0,0,0,0,0,0,0,0,0,0,2,1,9,0,7,8,6,3,5,0
Val_2e30_20d:
.DB 0,0,0,0,0,0,0,0,0,0,4,2,8,1,4,7,3,7,0,1
Val_2e31_20d:
.DB 0,0,0,0,0,0,0,0,0,0,8,4,6,3,8,4,7,4,1,2
Val_2e32_20d:
.DB 0,0,0,0,0,0,0,0,0,0,6,9,2,7,6,9,4,9,2,4

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
calc_float2dec_20:	; prepocita cislo ve formatu float na cislo v desitkove
  ; soustave (Vysledek se ulozi do SRAM na pozice Dp9, ... Dp0, Dn1, ... Dn10
.EQU Dp9 = D_start_20_SRAM
.EQU Dp8 = Dp9+1
.EQU Dp7 = Dp8+1
.EQU Dp6 = Dp7+1
.EQU Dp5 = Dp6+1
.EQU Dp4 = Dp5+1
.EQU Dp3 = Dp4+1
.EQU Dp2 = Dp3+1
.EQU Dp1 = Dp2+1
.EQU Dp0 = Dp1+1
.EQU Dn1 = Dp0+1
.EQU Dn2 = Dn1+1
.EQU Dn3 = Dn2+1
.EQU Dn4 = Dn3+1
.EQU Dn5 = Dn4+1
.EQU Dn6 = Dn5+1
.EQU Dn7 = Dn6+1
.EQU Dn8 = Dn7+1
.EQU Dn9 = Dn8+1
.EQU Dn10 = Dn9+1

  ; Nejdriv se musi zjistit, jakou hodnotu ma MSB ve floatu
	CLR M1	; Pomocny registr. V kazdem pripade se jeho obsah bude mazat
  ; -> je ucelne tento kus kodu napsat 1x, kdyz se musi provest za kazde
  ; okolnosti

	LDI XH,HIGH(Dp9);	Nastavime se adresou na "prvni" pametovou bunku
	LDI XL,LOW(Dp9)
	LDI Mg,20	; Bude pouzito jako pocitadlo (ted)
calc_float2dec_20_CLR_SRAM:	; Smaze data ulozena v SRAM (Dp9 ~ Dn10)
	ST X+,M1
	DEC Mg
	BRNE calc_float2dec_20_CLR_SRAM



	MOV Mg,A_SE	; Informace ulozena v A_SE se zkopiruje do Mg
	CLT	; T-bit = 0
	BLD Mg,7	; Smaze se informace o znamenku (nyni potrebujeme
  ; zjistit hodnotu exponentu. Tato hodnota odpovida hodnote [2^exp] MSB)
	CPI Mg,0b01000000	; Kontrola na nulu. Pak je vysledek nula ->
  ; -> znacne zjednodussi praci
	BRNE calc_float2dec_20_not_zero	; Pokud neni cislo nula, pak se
  ; pokracuje v normalni procedure

  ; V opacnem pripade se jen smazou obsahy registru v SRAM (coz uz bylo
  ; provedeno drive)

  ; Takze ted by mela byt ve vsech registrech nula -> to presne vystuhuje cislo
  ; nula :)
	RET


calc_float2dec_20_not_zero:
  ; Takze cislo neni nula. To znamena, ze se musi prevest float na decimalni
  ; cislo

  ; V prvni rade se musi zjistit, jestli je exponent kladny, nebo zaporny
  ; Pokud bude kladny, pak se v podstate nemusi nic resit. Pokud je cislo
  ; zaporne, musi se prevest na dvojkovy doplnek. Zde se diky dvojkovemu
  ; doplnku algoritmus znacne zjednodussi
	SBRS Mg,6	; Kontrola znamenka exponentu
	RJMP c_f2d_20_exp_positive	; Pokud je exp. kladny, pak se skoci
  ; na dane navesti
c_f2d_20_exp_negative:	; Pokud je exponent zaporny, musi se prevest do
  ; dvojkoveho doplnku
	BLD Mg,6	; Zbavime se znamenka
	SUB M1,Mg	; M1=M1-Mg (M1=0-|exponent| )

	MOV Mg,M1	; A vysledek se jeste preulozi do Mg - bude potreba
  ; Takze nyni v Mg mame vysledek
	RJMP c_f2d_20_exp_OK

c_f2d_20_exp_positive:
  ; Exponent v Mg je jiz upravnen jak je potreba

c_f2d_20_exp_OK:
  ; Takze nyni je exponent pripraven (budto je kladny, nebo je zaporny, ve
  ; dvojkovem doplnku). M1 tedy reprezentuje exponent

  ; ALE: ma to zase hacek. Pro optimalizaci procesu, je vhodne zacit od
  ; nejnizsich jednotek a postupne se propracovat az k MSB (je to predevsim
  ; kvuli tomu, ze LPM neumi dekrementovat ukazatel Z, takze umi jen pocitat
  ; "nahoru").

  ; Takze si musime zjisit, jakou vahu ma LSB ve floatu. Vyjde se z toho, ze
  ; MSB ma hodnotu rovnou eponentu (ted myslim rad - napr. 2^5). Takze LSB musi
  ; byt o 24 radu niz (mantisa ma 0~23bitu -> 24 radu). Takze se musi vypocitat
  ; jake dekadicke hodnoty nalezi LSB (napr.: Val_2em07_20d ).
	SUBI Mg,24	; Mg=Mg-24 (v Mg byla ulozena exponentu - rad MSB -)
  ; Timto zjistime rad LSB

  ; Pokud by byl rad LSB mensi jak 2^-32 (Tzn. Mg< -32 ), pak se na toto LSB
  ; vynecha a zacne se az od hodnoty 2^-32. To ze hodnota je mensi jak nula,
  ; znaci prvni bit (znamena, ze cislo je zaporne). A pokud je cislo zaporne,
  ; tak potom tehdy ma smysl kontrolovat, jestli je vypoctena hodnota mensi jak
  ; -32
	CLR M1 	; bude pozdeji pouzit pro vypocty

	SBRS Mg,7	; Kontrola znamenka
	RJMP c_f2d_20_exp_verified	; Pokud bylo cislo kladne, nemusi se
  ; nic resit

  ; Pokud ne, musi se zkontrolovat, zda neni cislo mensi jak -32
  ; -32 dec = 0b11100000 ; -33 dec = 0b11011111 -> z toho plyne i podminka

	CPI Mg,0b11100000
	BRSH c_f2d_20_exp_verified	; Pokud bude Mg stejne, nebo vetsi, pak
  ; je vse v poradku a muze se provest vypocet

  ; V opacnem pripade se musi vypocitat, kolik LSB bitu se ma preskocit
	MOV M2,R17	; Zaloha R17 (musime si vypujcit dalsi registr)
	LDI R17,-32
	SUB R17,Mg	; -32-(-Mg) -> vypocet, kolik LSB se ma vynechat
	MOV M1,R17	; A vysledek se preulozi do M1

	MOV R17,M2	; Obnova R17

c_f2d_20_exp_verified:
  ; Nastaveni Z-pointeru na nulovy exponent
	LDI ZH,HIGH(2*Val_2e00_20d)
	LDI ZL,LOW(2*Val_2e00_20d)

  ; Nyni se musi vypocitat offset (posuv) vzhledem k 2^0. K tomu jsou ale
  ; zapotrebi registry R17~R31, takze krome Mg si musime jeste jeden "vypujcit"
	MOV M6,R17	; Zaloha R17 (vypujceny registr)
	LDI R17,20
	MULSU Mg,R17	; exponent LSB*20 (20 bajtu pro kazdy rad - kazdy rad
  ; zabira 20 bajtu, takze se posuv musi provest co krok, to 20 bajtu)

	ADD ZL,R0
	ADC ZH,R1	; Posuv Z-pointeru o patricnou hodnotu (vpred/vzad)

	MUL M1,R17	; Pokud byl exponent mensi jak -33, pak se musi preskocit "M1"
  ; *20 bajtu
  	ADD ZL,R0
	ADC ZH,R1

	MOV R17,M6	; Obnova R17

	MOV Mg,M1	; Bude pocitat kroky.

  ; A pote se zacnou provadet soucty...
c_f2d_20_sum:
	RCALL Add_byte_to_dec_num_20	; Pricte aktualni bit k jiz vypoctene
  ; hodnote
	INC Mg	; Snizi se hodnota pocitadla
	CPI Mg,24	; Porovnani s hodnotou 24

	BRNE c_f2d_20_sum	; A dokud nebude Mg=24, tak se cely proces bude
  ; cyklycky opakovat (posledni bit (MSB) se nepricte. Pricte se az
  ; v nasledujicim kroku)


  ; No, prvni MSB neni v mantise vyjadren, ale je tam :) A vzdy je jedna. To
  ; znamena, ze hodnotu tohoto MSB musime ulozit do patricnych pametovych bunek
  ; Exponent vlastne udava v jakem radu se nachazi MSB.

	RCALL Add_value_in_Z_to_dec_num_20



  ; A na konec se prida informace o znamenku. Rozhodl jsem se, ze ji vlozim do Dp9
  ; na "prvni" misto. "1" znaci zaporne cislo, "0", pak kladne
  ; Takze format je shodny jako u A_SE -> nacte se znamenkovy bit a vlozi se do Dp9
  	BST A_SE,7	; Do T-bitu se ulozi znamenkovy bit
	LDS Mg,Dp9	; Obsah nejvyssiho registru se zkopiruje do Mg
	BLD Mg,7	; A znamenkovy bit se vlozi do Mg
	STS Dp9,Mg	; A Mg se zkopiruje zpet do SRAM i se znamenkem


  ; V tomto momente je samotny prevod hotov. Zbyva uz jen cislo vhodne
  ; interpretovat na display, ale to maji na starost jine programy.
	RET
; *-----------------------------------------*
Add_byte_to_dec_num_20:	; Podle Mg si zjisti pozici bitu a podle jeho hodnoty
  ; si zjisti, jestli ma pricist dekadicke hodnoty, nebo ne. V pripade, ze ma
  ; provest soucet, jej udela. Pokud ne, pak jen posune Z-pointer o 20 bajtu
  ; Pracuje s argumentem Mg (poradi bitu)

  ; Podle Mg ("aktualniho bitu") se musi vybrat "spravny bit". Problem je
  ; v tom, ze mantisa je 3*8bitova -> 24 bitu -> musi se zjistit, ve ktere
  ; pametove bunce se nachazi
	MOV M4,Mg	; Zaloha Mg

	CPI Mg,16
	BRSH A_b2d_n_16_23_20	; Pokud bude Cislo vetsi, nebo rovno jak 16,
  ; pak se budeme pohybovat v pametove bunce A_3 (nejvyssich 8 bitu)

	CPI Mg,8	; Pripadne se kontroluje nizsi registr
	BRSH A_b2d_n_8_15_20
  ; A dalsi moznost uz proste ani neni. Zbytecne delat nejake podminky
	MOV M1,A_1
	RCALL Add_byte_to_dec_num_decide_20
	RJMP A_b2d_n_20_end

A_b2d_n_8_15_20:
	SUBI Mg,8
	MOV M1,A_2
	RCALL Add_byte_to_dec_num_decide_20
	RJMP A_b2d_n_20_end

A_b2d_n_16_23_20:	; Nejvyssich 8 bitu
	SUBI Mg,16	; Odecte se 16 -> takze v Mg je 0~7 -> cislo v Mg
  ; vlastne udava pozici aktualniho bitu v A_3
	MOV M1,A_3	; Zkopirovani A_3 do M1
	RCALL Add_byte_to_dec_num_decide_20

A_b2d_n_20_end:
	MOV Mg,M4	; Obnova Mg
	RET

; *-----------------------------------------*
Add_byte_to_dec_num_decide_20:
	CPI Mg,0
	BRNE Add_byte_to_dec_num_decide_1_20

  ; A pokud vyslo, ze pozice je 0 v M1 -> kontrola, zda je 1, nebo 0
  ; Pokud bude 1, pak se prictou dane dekadicke hodnoty k vysledkum. Pokud bude
  ; 0, tak staci akorat "posoupnout" Z-pointer o 20 mist
	SBRC M1,0
	RCALL Add_value_in_Z_to_dec_num_20	; Pokud byla 1, pak se provede
  ; tento podprogram
	SBRS M1,0
	ADIW ZH:ZL,20	; V opacnem pripade byla 0 -> posun Z-pointeru
	RET
Add_byte_to_dec_num_decide_1_20:
	CPI Mg,1
	BRNE Add_byte_to_dec_num_decide_2_20
	SBRC M1,1
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,1
	ADIW ZH:ZL,20
	RET
Add_byte_to_dec_num_decide_2_20:
	CPI Mg,2
	BRNE Add_byte_to_dec_num_decide_3_20
	SBRC M1,2
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,2
	ADIW ZH:ZL,20
	RET
Add_byte_to_dec_num_decide_3_20:
	CPI Mg,3
	BRNE Add_byte_to_dec_num_decide_4_20
	SBRC M1,3
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,3
	ADIW ZH:ZL,20
	RET
Add_byte_to_dec_num_decide_4_20:
	CPI Mg,4
	BRNE Add_byte_to_dec_num_decide_5_20
	SBRC M1,4
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,4
	ADIW ZH:ZL,20
	RET
Add_byte_to_dec_num_decide_5_20:
	CPI Mg,5
	BRNE Add_byte_to_dec_num_decide_6_20
	SBRC M1,5
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,5
	ADIW ZH:ZL,20
	RET
Add_byte_to_dec_num_decide_6_20:
	CPI Mg,6
	BRNE Add_byte_to_dec_num_decide_7_20
	SBRC M1,6
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,6
	ADIW ZH:ZL,20
	RET
Add_byte_to_dec_num_decide_7_20:
  ; uz ani jina moznost neni
	SBRC M1,7
	RCALL Add_value_in_Z_to_dec_num_20
	SBRS M1,7
	ADIW ZH:ZL,20
	RET
; *-----------------------------------------*
Add_value_in_Z_to_dec_num_20:	; Podle toho,co je ulozeno v Z-pointeru, prida
  ; dana data do SRAM (pricte je k vysledku)

	MOV M6,Mg	; Zaloha Mg -> bude zapotrebi obnovit!
  ; Nastavime X-pointer na "pocatek" (dekadicke MSB)
  ; Musi se zacit od nejnizsiho radu kvuli preteceni
	LDI XH,HIGH(Dn10+1)
	LDI XL,LOW(Dn10+1); Posuv X-pointeru o jeden vpred (nasledne je
  ; provedena dekrementace -> dostane se na "spravnou" pozici

	LDI Mg,20
	MOV M5,Mg	; M5 bude slouzit jako pocitadlo - cely cyklus je
  ; zapotrebi zopakovat 20x
	CLT	; T-bit=0 (bude pozdeji potreba)
A_v_i_Z2d_n_20_cycle:
	LD Mg,-X	; Do Mg se ulozi cislo v desitkove soustave (0~9)
	LPM M2,Z+	; Do M2 se ulozi aktualni hodnota, ktera ma byt
  ; prictena

	BRTC A_v_i_Z2d_n_20_cycle_T_CL
	SEC	; Pokud byl T-bit v 1 -> nastavi se i C do 1
A_v_i_Z2d_n_20_cycle_T_CL:
	ADC Mg,M2	; Soucet - Mg = Mg+M2+C (C - pokud pri "poslednim"
  ; cyklu doslo k preteceni, je potreba pricist 1)
	CPI Mg,10	; Porovnani s cislem 10
	BRSH A_v_i_Z2d_n_20_cycle_SEC	; Pokud je aktualni soucet vetsi jak
  ; 10, pak to samozrejme nemuzeme zapsat (v desitkove soustave je v jednom
  ; radu 0~9) -> proto skok na dane navesti, kde se to vyresi

  ; V opacnem pripade neni potreba resit preteceni
	CLT	; T-bit=0
	CLC
	ST X,Mg	; A vypocteny soucet se ulozi zpet do SRAM
	DEC M5	; Snizime cislo pocitadla o 1
	BRNE A_v_i_Z2d_n_20_cycle	; A dokud nebude 0 tak skok na navesti

	MOV Mg,M6	; Obnova Mg

	RET

A_v_i_Z2d_n_20_cycle_SEC:
	SET	; T-bit=1 - priznak preteceni na 1 -> priste se pricte jeste
  ; jednicka
	SUBI Mg,10	; Od aktualni hodnoty se odecte 10 -> zbydou jenom jednotky
	ST X,Mg
	DEC M5
	BRNE A_v_i_Z2d_n_20_cycle	;  A dokuk nebude M5=0, tak skok

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_8bit_signed_to_float:
Convert_8bit_signed_to_float_A:
  ; Prevede 8bitove, znamenkove, cislo ulozene v Mg na float a ulozi ho do A
	SBRC Mg,7	; test znamenka -> cislo v Mg je v dvojkovem doplnku ->
  ; -> pokud je na MSb pozici 1, je cislo zaporne
	RJMP Conv_8_sign2fl_negative_A	; Pokud je cislo zaporne, dostaneme se
  ; sem -> nasleduje skok
Conv_8_sign2fl_positive_A:	; V opacnem pripade se dostaneme sem
	RCALL Convert_8bit_unsigned_to_float_A	; V podstate neni co resit.
  ; Algoritmus je v podstate uplne stejny, tak proc toho nevyuzit.
	RET

Conv_8_sign2fl_negative_A:
	MOV M2,Mg	; Zaloha Mg do M2
	NEG Mg	; Dvojkovy doplnek (S tim pracuje nasledujici
  ; program)

	RCALL Convert_8bit_unsigned_to_float_A	; Prevede se

	SET	; T-bit = 1
	BLD A_SE,7	; A nastavi se znamenko na zaporne
	MOV Mg,M2
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_8bit_signed_to_float_B:
  ; Analogie s vyse uvedenym, ale pro B
	SBRC Mg,7
	RJMP Conv_8_sign2fl_negative_B
Conv_8_sign2fl_positive_B:
	RCALL Convert_8bit_unsigned_to_float_B
	RET

Conv_8_sign2fl_negative_B:
	MOV M2,Mg
	NEG Mg
	RCALL Convert_8bit_unsigned_to_float_B
	SET
	BLD B_SE,7
	MOV Mg,M2
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_8bit_unsigned_to_float:	; Defaultni je A
Convert_8bit_unsigned_to_float_A:
  ; Prevede 8bitove, neznamenkove cislo ulozene v Mg na float a ulozi ho do A
  ; Vyuziva A_SE, A_3, A_2, A_1, Mg (obnovi), M1

  ; tyto dva registry budou vzdy nulove, proto je vhodne je "vycistit"
  ; na zacatku. Usetri se tim cas a misto v pameti
	CLR A_2
	CLR A_1

	MOV M1,Mg	; Zaloha Mg - pokud cislo nebude nulove, pak se bude
  ; hodit

	SBRC Mg,7	; Test, zda je na nejvyssi pozici jednicka
	RJMP Conv_8_unsign2fl_7_A	; Pokud byla v nejvyssi pozici
  ; jednicka, pak je jasny exponent (2^7) a co se tyce hodnot zapsanych do A_3,
  ; tak staci jen nasedujici bity zkopirovat do A_3 a je vystarano

  ; V opacne pripade se hleda dal...
	SBRC Mg,6
	RJMP Conv_8_unsign2fl_6_A
  ; A dal... algoritmus je stale stejny
	SBRC Mg,5
	RJMP Conv_8_unsign2fl_5_A

	SBRC Mg,4
	RJMP Conv_8_unsign2fl_4_A

	SBRC Mg,3
	RJMP Conv_8_unsign2fl_3_A

	SBRC Mg,2
	RJMP Conv_8_unsign2fl_2_A

	SBRC Mg,1
	RJMP Conv_8_unsign2fl_1_A

	SBRC Mg,0
	RJMP Conv_8_unsign2fl_0_A
  ; A pokud se dostaneme sem, pak to znamena, ze cislo je nula -> tim se to
  ; hodne zjednodusuje
	LDI Mg,0b01000000	; Nula je tak trochu vyjimka. Proto ma tak
  ; zvlastni exponent (vlastne -0)
	MOV A_SE,Mg
	CLR A_3
	RET

Conv_8_unsign2fl_7_A:
  ; Exponent byl sedm -> ulozit do A_SE, nasedujici bity ulozit do A_3
	LDI Mg,7
	MOV A_SE,Mg	; Timto jsme vyresili exponent
  ; Ted se musi prokopirovat jednotlive bity do A_3
  ; V tomto pripade to jde udelat tak, ze hodnotu v M1 ulozime do A_3 a pak se
  ; provede posuv vlevo, cimz se vlastne zbavime MSB bitu a ostani budou na
  ; spravnych pozicich
	MOV A_3,M1
	LSL A_3
	MOV Mg,M1	; Obnova Mg (Pro pripad, ze by promenna byla dal
  ; potreba)
	RET

Conv_8_unsign2fl_6_A:
  ; Obdoba kodu vyse, ale posuv se musi provest 2x
	LDI Mg,6
	MOV A_SE,Mg

	MOV A_3,M1
	LSL A_3
	LSL A_3
	MOV Mg,M1
	RET

Conv_8_unsign2fl_5_A:
	LDI Mg,5
	MOV A_SE,Mg

	MOV A_3,M1
	LSL A_3
	LSL A_3
	LSL A_3
	MOV Mg,M1
	RET

Conv_8_unsign2fl_4_A:
	LDI Mg,4
	MOV A_SE,Mg

	MOV A_3,M1
	LSL A_3
	LSL A_3
	LSL A_3
	LSL A_3
	MOV Mg,M1
	RET

Conv_8_unsign2fl_3_A:
	LDI Mg,3
	MOV A_SE,Mg

	MOV A_3,M1
	LSL A_3
	LSL A_3
	LSL A_3
	LSL A_3
	LSL A_3
	MOV Mg,M1
	RET

Conv_8_unsign2fl_2_A:
	LDI Mg,2
	MOV A_SE,Mg
  ; Zde uz se vyplati namisto posuvu kopirovat a vkladat jednotlive bity

	CLR A_3
	BST M1,1	; Vezme se bit z pozice 1
	BLD A_3,7	; a vlozi se na pozici 7
	BST M1,0	; Vezme se bit z pozice 0
	BLD A_3,6	; a vlozi se na pozici 6
	MOV Mg,M1	; obnova
	RET

Conv_8_unsign2fl_1_A:
	LDI Mg,1
	MOV A_SE,Mg

	CLR A_3
	BST M1,0
	BLD A_3,7
	MOV Mg,M1
	RET

Conv_8_unsign2fl_0_A:
  ; Zde dojde k dost velkemu zjednoduseni. Exponent je nula, MSB se odstrani ->
  ; -> A_3 = 0
	CLR A_SE
	CLR A_3
  ; Nemusi se ani provadet obnova, data nebyla prepsana
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_8bit_unsigned_to_float_B:
  ; Prakticky to same jako Convert_8bit_unsigned_to_float_A, ale pro cislo B
	CLR B_2
	CLR B_1

	MOV M1,Mg
	SBRC Mg,7
	RJMP Conv_8_unsign2fl_7_B
	SBRC Mg,6
	RJMP Conv_8_unsign2fl_6_B
	SBRC Mg,5
	RJMP Conv_8_unsign2fl_5_B
	SBRC Mg,4
	RJMP Conv_8_unsign2fl_4_B
	SBRC Mg,3
	RJMP Conv_8_unsign2fl_3_B
	SBRC Mg,2
	RJMP Conv_8_unsign2fl_2_B
	SBRC Mg,1
	RJMP Conv_8_unsign2fl_1_B
	SBRC Mg,0
	RJMP Conv_8_unsign2fl_0_B

	LDI Mg,0b01000000
	MOV B_SE,Mg
	CLR B_3
	RET

Conv_8_unsign2fl_7_B:
	LDI Mg,7
	MOV B_SE,Mg
	MOV B_3,M1
	LSL B_3
	MOV Mg,M1
	RET
Conv_8_unsign2fl_6_B:
	LDI Mg,6
	MOV B_SE,Mg
	MOV B_3,M1
	LSL B_3
	LSL B_3
	MOV Mg,M1
	RET
Conv_8_unsign2fl_5_B:
	LDI Mg,5
	MOV B_SE,Mg
	MOV B_3,M1
	LSL B_3
	LSL B_3
	LSL B_3
	MOV Mg,M1
	RET
Conv_8_unsign2fl_4_B:
	LDI Mg,4
	MOV B_SE,Mg
	MOV B_3,M1
	LSL B_3
	LSL B_3
	LSL B_3
	LSL B_3
	MOV Mg,M1
	RET
Conv_8_unsign2fl_3_B:
	LDI Mg,3
	MOV B_SE,Mg
	MOV B_3,M1
	LSL B_3
	LSL B_3
	LSL B_3
	LSL B_3
	LSL B_3
	MOV Mg,M1
	RET
Conv_8_unsign2fl_2_B:
	LDI Mg,2
	MOV B_SE,Mg
	CLR B_3
	BST M1,1
	BLD B_3,7
	BST M1,0
	BLD B_3,6
	MOV Mg,M1
	RET
Conv_8_unsign2fl_1_B:
	LDI Mg,1
	MOV B_SE,Mg
	CLR B_3
	BST M1,0
	BLD B_3,7
	MOV Mg,M1
	RET
Conv_8_unsign2fl_0_B:
	CLR B_SE
	CLR B_3
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_16bit_signed_to_float:
Convert_16bit_signed_to_float_A:
  ; Prevede 16bitove, znamenkove cislo ulozene v M1, M2 na float do promenne A.
  ; M2 - vyssi bajt, M1 nizsi bajt

  ; Nejprve se otestuje znamenko
	SBRC M2,7	; pokud je cislo ve dvojkovem doplnku, pak zde bude
  ; logicka jednicka
	RJMP Conv_16_sign2fl_negative_A	; A pokud tam byla jednicka skok na
  ; toto navesti

Conv_16_sign2fl_positive_A:
	RCALL Convert_16bit_unsigned_to_float_A	; Pokud je cislo kladne, neni
  ; zde vlastne co resit. Algoritmus je uplne stejny, jako kdyby bylo
  ; neznamenkove
	RET

Conv_16_sign2fl_negative_A:
  ; Tady je to trochu slozitejsi. Musime si cislo prevest z dvojkoveho doplnku
  ; na absolutni hodnotu.

  ; Prevod na ABS. hodnotu: invertovat vsechny bity a pak pricist 1
  ; Ale nejprve registry zalohovat
	MOV M3,M1	; M3 = M1
	MOV M4,M2	; M4 = M2

	COM M2	; Jednicky se prohodi za nuly a naopak
	NEG M1	; Vypocte se rovnou dvojkovy doplnek
  ; Nyni se musi vyhodnotit pripadne preteceni pri vykonavani NEG
	BRNE Conv_16_sign2fl_negative_not_overflow_A	; Pokud nedoslo
  ; k preteceni -> preskoci se instrukce INC
	INC M2	; Pripadne se pricte 1

Conv_16_sign2fl_negative_not_overflow_A:
	RCALL Convert_16bit_unsigned_to_float_A
  ; Ted uz jen pridat znamenko
	SET	; T-bit do 1
	BLD A_SE,7	; nahraje se znamenko
  ; A obnova registru
	MOV M1,M3
	MOV M2,M4

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_16bit_signed_to_float_B:
  ; analogie s Convert_16bit_signed_to_float_A, ale pro float promennou B
	SBRC M2,7
	RJMP Conv_16_sign2fl_negative_B

Conv_16_sign2fl_positive_B:
	RCALL Convert_16bit_unsigned_to_float_B
	RET

Conv_16_sign2fl_negative_B:
	MOV M3,M1
	MOV M4,M2

	COM M2
	NEG M1
	BRNE Conv_16_sign2fl_negative_not_overflow_B

	INC M2
Conv_16_sign2fl_negative_not_overflow_B:
	RCALL Convert_16bit_unsigned_to_float_B

	SET
	BLD B_SE,7
	MOV M1,M3
	MOV M2,M4

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_16bit_unsigned_to_float:	; Defaultni je opet registr A
Convert_16bit_unsigned_to_float_A:
  ; Prevede 16. bitove cislo ulozene v M1 (LSB) a M2 (MSB) a prevede ho na
  ; float, ktery ulozi do A_SE, A_3, A_2 a A_1

  ; Cislo je sestnactibitove -> float ma 24bitovou mantisu -> "spodni registr"
  ; A_1 bude vzdy nulovy -> muzeme ho ihned smazat (vycistit/nahradit nulama)
	CLR A_1

  ; Ted se musi zjistit, "kde lezi" MSB. Teoreticky mame 16 moznosti. Pro
  ; urychleni vypoctu si nejprve "otukame" registr M2, jestli neni roven nule.
  ; Pokud bude totiz roven nule, pak je evidentni, ze se MSB bit nenachazi zde,
  ; ale musi byt v dalsim registru (pokud neni cele cislo rovno nule)
	MOV Mg,M2	; Mg=M2 (MSB bajt)
	CPI Mg,0	; porovnani s nulou
	BRNE Conv_16_unsign2fl_In_MSB_A	; Pokud neni roven nule, pak je MSB
  ; ulozen prave v registru M2

;	RJMP Conv_16_unsign2fl_In_LSB_A	; V opacnem pripade je ulozen v M1 ->
  ; -> v podstate staci zavolat 8bitovy prepocet
	MOV Mg,M1
	RCALL Convert_8bit_unsigned_to_float_A
	RET

Conv_16_unsign2fl_In_MSB_A:
  ; Trochu slozitejsi situace. Nejprve si zjistime, kolik kroku jsme udelali,
  ; nez jsme narazli na MSB bit (proste nez narazime na prvni jednicku)
	CLR M3	; M3 bude pocitat kroky
Conv_16_unsign2fl_In_MSB_find_MSB_A:
	SBRC M2,7	; Test na nejvyssi bit v M2
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A	; Pokud byla na dane
  ; pozici "1", pak se dostane PC sem -> MSB nalezeno

  ; V opacnem pripade se musi prezkoumat dalsi bit a pricist krok do M3
	INC M3	; Pribyl jeden krok
	SBRC M2,6
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A	; Opet jako vyse. Pokud
  ; nalezena log. "1" -> skok

  ; A pokracuje se analogicky dal....
	INC M3
	SBRC M2,5
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A

	INC M3
	SBRC M2,4
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A

	INC M3
	SBRC M2,3
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A

	INC M3
	SBRC M2,2
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A

	INC M3
	SBRC M2,1
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_A

	INC M3
  ; Tady uz jina moznost ani neni. Zde musi byt jednicka, protoze jsme vyse
  ; testovali, zda neni registr nulovy
;	SBRC M2,0
;	RJMP Conv_16_unsign2fl_In_MSB_MSB_found
Conv_16_unsign2fl_In_MSB_MSB_found_A:
  ; Takze nyni je v M3 ulozena informace, kolikrat se bude muset vysledek
  ; rotovat vlevo.
  ; Dale se da vypocitat velikost exponentu
	LDI Mg,15
	MOV A_SE,Mg	; exponent = 15
	SUB A_SE,M3	; exponent = exponent - pocet kroku (15-pocet kroku)
  ; Tim se vyresil problem s exponentem

  ; Nyni nasleduje presun z M1 a M2 do A_2 a A_3
	MOV A_3,M2
	MOV A_2,M1

  ; Dulezite je, ze se musi udelat jeste jeden krok navic -> MSB neni ve floatu
  ; zapsano!
	INC M3	; plus krok navic
Conv_16_unsign2fl_In_MSB_rotate_A:
	LSL A_2	; Posun vlevo od LSB (A_1 bude stale nula, nema smysl)
	ROL A_3	; Posun i MSB a pripadne se prenese C
	DEC M3
	BRNE Conv_16_unsign2fl_In_MSB_rotate_A	; A dokud nebude roven nule ->
  ; -> rozuj dal
	RET

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_16bit_unsigned_to_float_B:
  ; Analogie s Convert_16bit_unsigned_to_float_A, ale na zaver se pracuje
  ; s registrem B.
	CLR B_1
	MOV Mg,M2
	CPI Mg,0
	BRNE Conv_16_unsign2fl_In_MSB_B

	MOV Mg,M1
	RCALL Convert_8bit_unsigned_to_float_B
	RET

Conv_16_unsign2fl_In_MSB_B:
	CLR M3
Conv_16_unsign2fl_In_MSB_find_MSB_B:
	SBRC M2,7
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
	SBRC M2,6
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
	SBRC M2,5
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
	SBRC M2,4
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
	SBRC M2,3
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
	SBRC M2,2
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
	SBRC M2,1
	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B

	INC M3
;	SBRC M2,0
;	RJMP Conv_16_unsign2fl_In_MSB_MSB_found_B
Conv_16_unsign2fl_In_MSB_MSB_found_B:
	LDI Mg,15
	MOV B_SE,Mg
	SUB B_SE,M3

	MOV B_3,M2
	MOV B_2,M1

	INC M3
Conv_16_unsign2fl_In_MSB_rotate_B:
	LSL B_2
	ROL B_3
	DEC M3
	BRNE Conv_16_unsign2fl_In_MSB_rotate_B

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_24bit_unsigned_to_float:	; Prevede cislo ulozene v M1,M2,M3
  ; (od LSB do MSB) na cislo s plovouci desetinnou carkou
Convert_24bit_unsigned_to_float_A:
  ; Kontrola, zda se nejedna o nulu
	MOV Mg,M1	; Zkopirujeme M1 (LSB) do Mg
	CPI Mg,0	; porovnani s nulou
	BRNE Conv_24_unsign2fl_not_a_zero_A	; pokud neni nula, skoci
  ; Pokud byl nula, testuje se dalsi

	MOV Mg,M2	; opet, zkoumame M2
	CPI Mg,0
	BRNE Conv_24_unsign2fl_not_a_zero_A	; A opet. Pokud je nula, skok

	MOV Mg,M3	; MSB
	CPI Mg,0
	BRNE Conv_24_unsign2fl_not_a_zero_A

  ; Takze, pokud se dostaneme sem, pak slo skutecne o nulu
	LDI Mg,0b01000000	; exponent pro nulu
	MOV A_SE,Mg
	CLR A_3
	CLR A_2
	CLR A_1

	RET	; A hotovo


Conv_24_unsign2fl_not_a_zero_A:
  ; Vzhledem k tomu, ze mantisa je 24 bitova a my potrebujeme prevest 24 bitove
    ; cislo, tak se toho dost zjednodusuje
	MOV A_1,M1	; LSB
	MOV A_2,M2
	MOV A_3,M3	; MSB

	CLR R0	; Pomocny registr pro prenosy do vyssich radu
	LDI Mg,24
	MOV A_SE,Mg	; Pocita exponent

Conv_24_unsign2fl_find_MSB_A:
	DEC A_SE	; Snizi se hodnota exponentu o 1

  ; Provede se rotace vpravo
	LSL A_1
	ROL A_2
	ROL A_3
  ; Pokud se MSB bit "dostal za" A_3 -> C bude nastaveno
	BRCC Conv_24_unsign2fl_find_MSB_A	; test na MSB
  ; Pokud nebylo C nastaveno -> nejednalo se o MSB -> hledat dal

Conv_24_unsign2fl_MSB_found_A:
  ; V opacnem pripade se dostaneme sem

  ; Vlastne je uz vsechno hotovo
	RET

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
Convert_24bit_unsigned_to_float_B:
  ; Kontrola, zda se nejedna o nulu
	MOV Mg,M1	; Zkopirujeme M1 (LSB) do Mg
	CPI Mg,0	; porovnani s nulou
	BRNE Conv_24_unsign2fl_not_a_zero_B	; pokud neni nula, skoci
  ; Pokud byl nula, testuje se dalsi

	MOV Mg,M2	; opet, zkoumame M2
	CPI Mg,0
	BRNE Conv_24_unsign2fl_not_a_zero_B	; A opet. Pokud je nula, skok

	MOV Mg,M3	; MSB
	CPI Mg,0
	BRNE Conv_24_unsign2fl_not_a_zero_B

  ; Takze, pokud se dostaneme sem, pak slo skutecne o nulu
	LDI Mg,0b01000000	; exponent pro nulu
	MOV B_SE,Mg
	CLR B_3
	CLR B_2
	CLR B_1

	RET	; A hotovo


Conv_24_unsign2fl_not_a_zero_B:
  ; Vzhledem k tomu, ze mantisa je 24 bitova a my potrebujeme prevest 24 bitove
    ; cislo, tak se toho dost zjednodusuje
	MOV B_1,M1	; LSB
	MOV B_2,M2
	MOV B_3,M3	; MSB

	CLR R0	; Pomocny registr pro prenosy do vyssich radu
	LDI Mg,24
	MOV B_SE,Mg	; Pocita exponent

Conv_24_unsign2fl_find_MSB_B:
	DEC B_SE	; Snizi se hodnota exponentu o 1

  ; Provede se rotace vpravo
	LSL B_1
	ROL B_2
	ROL B_3
  ; Pokud se MSB bit "dostal za" A_3 -> C bude nastaveno
	BRCC Conv_24_unsign2fl_find_MSB_B	; test na MSB
  ; Pokud nebylo C nastaveno -> nejednalo se o MSB -> hledat dal

Conv_24_unsign2fl_MSB_found_B:
  ; V opacnem pripade se dostaneme sem

  ; Vlastne je uz vsechno hotovo
	RET

