]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blob - cbios/utils.180
8157abab67fa83073137b0b48d8d7e3514c54394
[z180-stamp-cpm3.git] / cbios / utils.180
1 title 'general utility routines'
2
3 ; i/o port init routines
4
5 public ioiniml,ioini1l ;
6
7 ; math
8
9 public add_hla ; add a to hl
10 public div32_16,div32_r ; divide 32 bit by 16 bit number (rounded)
11
12 ; print utils
13
14 public ?pmsg ; print message
15 public pr.inln,pr.crlf ; print message inline, print newline
16 public phex2,phex4 ; print 2 digit hex (A) or 4 digit hex (HL)
17 public pr.dec,pr.decl ; print 16 or 32 bit decimal number
18 public ?pderr ; print BIOS disk error message header
19
20
21
22 extrn ?cono
23 extrn @adrv,@trk,@sect ; used by disk error message
24
25 ;-------------------------------------------------------------------------------
26
27 cr equ 13
28 lf equ 10
29 bell equ 7
30
31
32 dseg
33
34 ;----------------------------------------------------------------------
35 ; output bytes to consecutive portaddresses
36 ;
37 ; hl: table with following structure:
38 ; db n, port1, val1, val2,... valn
39 ; db m, port1, val1, val2,... valm
40 ; ...
41 ; db 0 ; Terminate table
42
43 ioiniml:
44 push bc
45 xor a
46 ioml_lp:
47 ld b,(hl)
48 inc hl
49 cp b
50 jr z,ioml_e
51
52 ld c,(hl)
53 inc hl
54 otimr
55 jr ioml_lp
56 ioml_e:
57 pop bc
58 ret
59
60 ;----------------------------------------------------------------------
61 ; output bytes to ports
62 ;
63 ; hl: tables of port,value pairs:
64 ; db n, port1,val1, port2,val2,... portn,valn
65 ; ...
66 ; db 0 ; Terminate table
67
68 ioini1l:
69 push bc
70 jr io1_nxt
71 io1_lp:
72 ld c,(hl) ;port address
73 inc hl
74 otim
75 jr nz,io1_lp
76 io1_nxt:
77 ld b,(hl) ;count
78 inc hl
79 inc b
80 djnz io1_lp
81
82 pop bc
83 ret
84
85 ;--------------------------------------------------------------------
86 ; add a to hl
87 ;
88 ; return:
89 ; hl = hl + a
90 ; Flags undefined
91
92 add_hla:
93 add a,l
94 ld l,a
95 ret nc
96 inc h
97 ret
98
99 ;--------------------------------------------------------------------
100 ; rounded div 32 by 16 bit
101 ;
102 ; HLDE: Dividend (x)
103 ; BC: Divisor (y)
104 ; return:
105 ; HLDE: Rounded Quotient (q)
106 ; BC: Remainder (r)
107
108 div32_r:
109 push bc
110 srl b ;y/2
111 rr c
112 add hl,bc ;low x + y/2
113 pop bc
114 jr nc,div_r1
115 inc de
116 div_r1:
117 ;fall thru
118
119 ;--------------------------------------------------------------------
120 ; Divide 32 bit by 16
121 ;
122 ; DEHL: Dividend (x)
123 ; BC: Divisor (y)
124 ;
125 ; return:
126 ; DEHL: Quotient
127 ; BC: Reminder
128
129 div32_16:
130 exx ;low
131 push de ;save alternate registers (de,bc)
132 push bc
133 exx ;high
134 push hl ;lx
135 push bc ;ly
136 ld bc,0 ;bc = hy = 0
137 ld h,b ;hl = hr = 0
138 ld l,c
139 ;de = x, hl = r
140 exx ;low
141 pop bc ;bc' = ly
142 ex (sp),hl ;hl' = lx, save alternate hl
143 ld de,0 ;de' = lr = 0
144 ex de,hl ;de = x, hl = r
145 exx ;high
146 ld a,32 ;count
147 ;
148 ; start:
149 ; de: x (de: hx, de': lx)
150 ; bc: y (bc: hy, bc': ly)
151 ; hl: 0
152 ;
153 div_lp: ;do
154 exx ; low
155 ex de,hl ; x
156 add hl,hl ; x <<= 1
157 exx ; high
158 ex de,hl ; x
159 adc hl,hl ; x <<= 1
160 exx ; low
161 ex de,hl ; r
162 adc hl,hl ; r <<= 1
163 exx ; high
164 ex de,hl ; r
165 adc hl,hl ; r <<= 1
166 exx ; low
167 inc de ; x/q += 1
168 or a ;
169 sbc hl,bc ;
170 exx ; high
171 sbc hl,bc ;
172 jr nc,div_no_restore
173 exx ; low
174 dec de ;
175 add hl,bc ; r += y
176 exx ; high
177 adc hl,bc ;
178
179 div_no_restore: ;
180 dec a ;
181 jr nz,div_lp ;while (--count)
182
183 ; result:
184 ; de: q (de: hq, de': lq)
185 ; hl: r (hl: hr, hl': lr)
186
187 exx ;low
188 ex de,hl ;hl = lq, de = lr
189
190 ex (sp),hl ;lq
191 push de ;lr
192 exx ;high
193 pop bc ;bc = lr
194 pop hl ;de = lq
195
196 exx ;low
197 pop bc ;restore alternate registers
198 pop de
199 exx ;high
200 ret
201
202 ;-------------------------------------------------------------------------------
203 ; print message @<HL> up to a null
204 ; saves <BC> & <DE>
205
206 ?pmsg:
207 push bc
208 push de
209 pmsg$loop:
210 ld a,(hl)
211 or a
212 jr z,pmsg$exit
213 ld c,a
214 push hl
215 call ?cono
216 pop hl
217 inc hl
218 jr pmsg$loop
219 pmsg$exit:
220 pop de
221 pop bc
222 ret
223
224 ;-------------------------------------------------------------------------------
225 ; print message inline up to a null
226 ; saves all registers
227
228 pr.inln:
229 ex (sp),hl
230 push af
231 call ?pmsg
232 pop af
233 ex (sp),hl
234 ret
235
236 ;-------------------------------------------------------------------------------
237 ; print <CR><LF>
238 ; saves all registers
239
240 pr.crlf:
241 call pr.inln
242 db cr,lf,0
243 ret
244
245 ;-------------------------------------------------------------------------------
246 ; print hl as a 4 digit hexadecimal number
247 ; saves all registers
248
249 phex4:
250 ld a,h
251 call phex2
252 ld a,l
253 ; fall thru
254
255 ;-------------------------------------------------------------------------------
256 ; print a as a 2 digit hexadecimal number
257 ; saves all registers
258
259 phex2:
260 push af
261 rra
262 rra
263 rra
264 rra
265 call print.digit
266 pop af
267
268 print.digit:
269 push hl
270 push de
271 push bc
272 push af
273 and 00fh
274 cp 10
275 jr c,prd_1
276 add a,007h
277 prd_1:
278 add a,'0'
279
280 ld c,a
281 call ?cono
282 pop af
283 pop bc
284 pop de
285 pop hl
286 ret
287
288
289 ;-------------------------------------------------------------------------------
290 ; print decimal 16 bit number from HL
291 ;
292 ; HL: unsigned binary number to print
293 ; C: minimum print field width
294 ; number is prined right-aligned
295 ; B: pad character, typically ' ' or '0'
296
297 pr.dec:
298 push de
299 ld de,0
300 call pr.decl
301 pop de
302 ret
303
304 ;-------------------------------------------------------------------------------
305 ; print decimal 32 bit number from DEHL
306 ;
307 ; DEHL: unsigned binary number to print
308 ; C: minimum print field width
309 ; number is prined right-aligned
310 ; B: pad character, typically ' ' or '0'
311
312 pr.decl:
313 push bc ;save width and fillchar
314 push bc
315 exx ;(alt)
316 ex (sp),hl ;save hl', get width and fill
317 push de ;save de'
318
319 xor a
320 ld d,a ;clear counter
321 ld e,a
322 push af ; string terminator
323 inc sp
324
325 prd_divloop: ;do
326 exx ; (main)
327 ld bc,10 ;
328 call div32_16 ; get a digit
329 ld a,c ;
330 add a,'0' ; make it printable
331 push af ;
332
333 ld a,h ;
334 or l ;
335 or d ;
336 or e ;
337 exx ; (alt)
338 inc sp ;
339 inc de ;
340 jr nz,prd_divloop ;
341
342 prd_filloop: ;h=filler, l=field width
343 ld a,e
344 cp l
345 jr nc,prd_out
346 push hl
347 inc sp
348 inc de
349 jr prd_filloop
350 prd_out:
351 ld hl,0
352 add hl,sp ;ptr to beginning of number string (hl==0 here)
353 call ?pmsg
354 ex de,hl
355 add hl,sp
356 ld sp,hl
357 inc sp ;remove string terminator
358 pop de
359 pop hl
360 exx ;(main)
361 pop bc
362 ret
363
364
365 ;-------------------------------------------------------------------------------
366
367 ?pderr:
368 ld hl,drive$msg
369 call ?pmsg ; error header
370 ld a,(@adrv)
371 add a,'A'
372 ld c,a
373 call ?cono ; drive code
374 ld hl,track$msg
375 call ?pmsg ; track header
376 ld c,0
377 ld hl,(@trk)
378 call pr.dec ; track number
379 ld hl,sector$msg
380 call ?pmsg ; sector header
381 ld hl,(@sect)
382 call pr.dec ; sector number
383 ret
384
385 ; error message components
386 drive$msg: db cr,lf,bell,'BIOS Error on ',0
387 track$msg: db ': T-',0
388 sector$msg: db ', S-',0