]> cloudbase.mooo.com Git - z180-stamp-cpm3.git/blame - cbios/utils.180
Add ldrbios.180 and generate cpmldr.com Load cpm3.sys from CF-IF device.
[z180-stamp-cpm3.git] / cbios / utils.180
CommitLineData
50f3b8f0
L
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
27cr equ 13
28lf equ 10
29bell 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
43ioiniml:
44 push bc
45 xor a
46ioml_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
56ioml_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
68ioini1l:
69 push bc
70 jr io1_nxt
71io1_lp:
72 ld c,(hl) ;port address
73 inc hl
74 otim
75 jr nz,io1_lp
76io1_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
92add_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;
5c4f36fa 102; DEHL: Dividend (x)
50f3b8f0
L
103; BC: Divisor (y)
104; return:
105; HLDE: Rounded Quotient (q)
106; BC: Remainder (r)
107
108div32_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
40df51ae 115 inc de
50f3b8f0
L
116div_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
129div32_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;
153div_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
179div_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
209pmsg$loop:
210 ld a,(hl)
d628fed8 211 inc hl
50f3b8f0
L
212 or a
213 jr z,pmsg$exit
214 ld c,a
215 push hl
216 call ?cono
217 pop hl
50f3b8f0
L
218 jr pmsg$loop
219pmsg$exit:
220 pop de
221 pop bc
222 ret
223
224;-------------------------------------------------------------------------------
225; print message inline up to a null
226; saves all registers
227
228pr.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
240pr.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
249phex4:
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
259phex2:
260 push af
261 rra
262 rra
263 rra
264 rra
265 call print.digit
266 pop af
267
268print.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
277prd_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
297pr.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
312pr.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
325prd_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
342prd_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
350prd_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
386drive$msg: db cr,lf,bell,'BIOS Error on ',0
387track$msg: db ': T-',0
388sector$msg: db ', S-',0