Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
Accumulator |
|
| 3.25;3.25 |
1 | /* |
|
2 | * Accumulator.java |
|
3 | * |
|
4 | * This file is part of JavaGear. |
|
5 | * |
|
6 | * JavaGear is free software; you can redistribute it and/or modify |
|
7 | * it under the terms of the GNU General Public License as published by |
|
8 | * the Free Software Foundation; either version 2 of the License, or |
|
9 | * (at your option) any later version. |
|
10 | * |
|
11 | * JavaGear is distributed in the hope that it will be useful, |
|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 | * GNU General Public License for more details. |
|
15 | * |
|
16 | * You should have received a copy of the GNU General Public License |
|
17 | * along with JavaGear; if not, write to the Free Software |
|
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
19 | */ |
|
20 | ||
21 | package uk.co.javagear; |
|
22 | ||
23 | /** |
|
24 | * Zilog Z80 CPU accumulator register emulation. |
|
25 | * |
|
26 | * @author Copyright (C) 2002-2003 Chris White |
|
27 | * @version 18th January 2003 |
|
28 | * @see "JavaGear Final Project Report" |
|
29 | */ |
|
30 | public final class Accumulator { |
|
31 | ||
32 | /** |
|
33 | * First register of the accumulator's bank. |
|
34 | */ |
|
35 | private static int reg; |
|
36 | ||
37 | /** |
|
38 | * Second register of the accumulator's bank. |
|
39 | */ |
|
40 | private static int reg2; |
|
41 | ||
42 | /** |
|
43 | * Flag register. |
|
44 | */ |
|
45 | private static Flag f; |
|
46 | ||
47 | /** |
|
48 | * <code>Accumulator</code> constructor. |
|
49 | * |
|
50 | * @param fl pointer to flag register. |
|
51 | */ |
|
52 | 0 | public Accumulator(Flag fl) { |
53 | 0 | reg = 0; |
54 | 0 | reg2 = 0; |
55 | 0 | this.f = fl; |
56 | 0 | } |
57 | ||
58 | /** |
|
59 | * Clear register. |
|
60 | */ |
|
61 | public void clear() { |
|
62 | 0 | reg = 0; |
63 | 0 | reg2 = 0; |
64 | 0 | } |
65 | ||
66 | /** |
|
67 | * Get value of accumulator. |
|
68 | * |
|
69 | * @return value stored in register. |
|
70 | */ |
|
71 | public int get() { |
|
72 | 0 | return reg; |
73 | } |
|
74 | ||
75 | /** |
|
76 | * Set register. |
|
77 | * |
|
78 | * @param value value to set register (<code>0</code> - <code>0xFF</code>). |
|
79 | */ |
|
80 | public void set(int value) { |
|
81 | 0 | reg = value & 0xff; |
82 | 0 | } |
83 | ||
84 | /** |
|
85 | * Increment register. |
|
86 | */ |
|
87 | public void inc() { |
|
88 | 0 | reg = (reg + 1) & 0xff; |
89 | ||
90 | 0 | if ((reg & 0x0F) == 0x00) { |
91 | 0 | f.halfCarryOn(); |
92 | } else { |
|
93 | 0 | f.halfCarryOff(); |
94 | } |
|
95 | ||
96 | 0 | f.negativeOff(); |
97 | ||
98 | // Overflow has occurred (to last bit) |
|
99 | 0 | if (reg == 0x80) { |
100 | 0 | f.parityOn(); |
101 | } else { |
|
102 | 0 | f.parityOff(); |
103 | } |
|
104 | ||
105 | 0 | if (reg == 0) { |
106 | 0 | f.zeroOn(); |
107 | } else { |
|
108 | 0 | f.zeroOff(); |
109 | } |
|
110 | ||
111 | 0 | if ((reg & 0x80) == 0) { |
112 | 0 | f.signOff(); |
113 | } else { |
|
114 | 0 | f.signOn(); |
115 | } |
|
116 | 0 | } |
117 | ||
118 | /** |
|
119 | * Decrement register. |
|
120 | */ |
|
121 | public void dec() { |
|
122 | 0 | reg = (reg - 1) & 0xff; |
123 | ||
124 | 0 | if ((reg & 0x0F) == 0x0F) { |
125 | 0 | f.halfCarryOn(); |
126 | } else { |
|
127 | 0 | f.halfCarryOff(); |
128 | } |
|
129 | ||
130 | 0 | f.negativeOn(); |
131 | ||
132 | // Overflow has occurred (from last bit) |
|
133 | 0 | if (reg == 0x7F) { |
134 | 0 | f.parityOn(); |
135 | } else { |
|
136 | 0 | f.parityOff(); |
137 | } |
|
138 | ||
139 | 0 | if (reg == 0) { |
140 | 0 | f.zeroOn(); |
141 | } else { |
|
142 | 0 | f.zeroOff(); |
143 | } |
|
144 | ||
145 | 0 | if ((reg & 0x80) == 0) { |
146 | 0 | f.signOff(); |
147 | } else { |
|
148 | 0 | f.signOn(); |
149 | } |
|
150 | 0 | } |
151 | ||
152 | /** |
|
153 | * Exchange register banks. |
|
154 | */ |
|
155 | public void ex() { |
|
156 | int temp; |
|
157 | 0 | temp = reg; |
158 | 0 | reg = reg2; |
159 | 0 | reg2 = temp; |
160 | 0 | } |
161 | ||
162 | /** |
|
163 | * ADD 8 BIT. |
|
164 | * |
|
165 | * @param value value to add. |
|
166 | */ |
|
167 | public void add(int value) { |
|
168 | 0 | int result = reg + value; |
169 | ||
170 | 0 | int carrybits = reg ^ value ^ result; |
171 | ||
172 | // half carry |
|
173 | 0 | if ((carrybits & 0x10) != 0) { |
174 | 0 | f.halfCarryOn(); |
175 | } else { |
|
176 | 0 | f.halfCarryOff(); |
177 | } |
|
178 | ||
179 | // carry |
|
180 | 0 | if ((carrybits & 0x100) != 0) { |
181 | 0 | f.carryOn(); |
182 | } else { |
|
183 | 0 | f.carryOff(); |
184 | } |
|
185 | ||
186 | // overflow |
|
187 | 0 | if ((((carrybits << 1) ^ carrybits) & 0x100) != 0) { |
188 | 0 | f.parityOn(); |
189 | } else { |
|
190 | 0 | f.parityOff(); |
191 | } |
|
192 | ||
193 | 0 | reg = result & 0xFF; |
194 | ||
195 | 0 | if (reg == 0) { |
196 | 0 | f.zeroOn(); |
197 | } else { |
|
198 | 0 | f.zeroOff(); |
199 | } |
|
200 | ||
201 | 0 | if ((reg & 0x80) == 0) { |
202 | 0 | f.signOff(); |
203 | } else { |
|
204 | 0 | f.signOn(); |
205 | } |
|
206 | ||
207 | 0 | f.negativeOff(); |
208 | ||
209 | 0 | f.setBit3(reg); |
210 | 0 | f.setBit5(reg); |
211 | 0 | } |
212 | ||
213 | /** |
|
214 | * ADC 8 BIT - Add with carry. |
|
215 | * |
|
216 | * @param value value to add. |
|
217 | */ |
|
218 | public void adc(int value) { |
|
219 | 0 | int result = reg + value + (f.carry() ? 1 : 0); |
220 | 0 | int carrybits = reg ^ value ^ result; |
221 | ||
222 | // half carry |
|
223 | 0 | if ((carrybits & 0x10) != 0) { |
224 | 0 | f.halfCarryOn(); |
225 | } else { |
|
226 | 0 | f.halfCarryOff(); |
227 | } |
|
228 | ||
229 | // carry |
|
230 | 0 | if ((carrybits & 0x100) != 0) { |
231 | 0 | f.carryOn(); |
232 | } else { |
|
233 | 0 | f.carryOff(); |
234 | } |
|
235 | ||
236 | // overflow |
|
237 | 0 | if ((((carrybits << 1) ^ carrybits) & 0x100) != 0) { |
238 | 0 | f.parityOn(); |
239 | } else { |
|
240 | 0 | f.parityOff(); |
241 | } |
|
242 | ||
243 | 0 | reg = result & 0xFF; |
244 | ||
245 | 0 | if (reg == 0) { |
246 | 0 | f.zeroOn(); |
247 | } else { |
|
248 | 0 | f.zeroOff(); |
249 | } |
|
250 | ||
251 | 0 | if ((reg & 0x80) == 0) { |
252 | 0 | f.signOff(); |
253 | } else { |
|
254 | 0 | f.signOn(); |
255 | } |
|
256 | ||
257 | 0 | f.negativeOff(); |
258 | 0 | f.setBit3(reg); |
259 | 0 | f.setBit5(reg); |
260 | 0 | } |
261 | ||
262 | /** |
|
263 | * SUB 8 BIT. |
|
264 | * |
|
265 | * @param value value to subtract. |
|
266 | */ |
|
267 | public void sub(int value) { |
|
268 | 0 | int result = reg - value; |
269 | 0 | int carrybits = reg ^ value ^ result; |
270 | ||
271 | // half carry |
|
272 | 0 | if ((carrybits & 0x10) != 0) { |
273 | 0 | f.halfCarryOn(); |
274 | } else { |
|
275 | 0 | f.halfCarryOff(); |
276 | } |
|
277 | ||
278 | // carry |
|
279 | 0 | if ((carrybits & 0x100) != 0) { |
280 | 0 | f.carryOn(); |
281 | } else { |
|
282 | 0 | f.carryOff(); |
283 | } |
|
284 | ||
285 | // overflow |
|
286 | 0 | if ((((carrybits << 1) ^ carrybits) & 0x100) != 0) { |
287 | 0 | f.parityOn(); |
288 | } else { |
|
289 | 0 | f.parityOff(); |
290 | } |
|
291 | ||
292 | 0 | reg = result & 0xFF; |
293 | ||
294 | 0 | if (reg == 0) { |
295 | 0 | f.zeroOn(); |
296 | } else { |
|
297 | 0 | f.zeroOff(); |
298 | } |
|
299 | ||
300 | 0 | if ((reg & 0x80) == 0) { |
301 | 0 | f.signOff(); |
302 | } else { |
|
303 | 0 | f.signOn(); |
304 | } |
|
305 | ||
306 | 0 | f.negativeOn(); |
307 | ||
308 | 0 | f.setBit3(reg); |
309 | 0 | f.setBit5(reg); |
310 | 0 | } |
311 | ||
312 | /** |
|
313 | * SBC 8 BIT. |
|
314 | * |
|
315 | * @param value subtract with carry. |
|
316 | */ |
|
317 | public void sbc(int value) { |
|
318 | 0 | int result = reg - value - (f.carry() ? 1 : 0); |
319 | 0 | int carrybits = reg ^ value ^ result; |
320 | ||
321 | // half carry |
|
322 | 0 | if ((carrybits & 0x10) != 0) { |
323 | 0 | f.halfCarryOn(); |
324 | } else { |
|
325 | 0 | f.halfCarryOff(); |
326 | } |
|
327 | ||
328 | // carry |
|
329 | 0 | if ((carrybits & 0x100) != 0) { |
330 | 0 | f.carryOn(); |
331 | } else { |
|
332 | 0 | f.carryOff(); |
333 | } |
|
334 | ||
335 | // overflow |
|
336 | 0 | if ((((carrybits << 1) ^ carrybits) & 0x100) != 0) { |
337 | 0 | f.parityOn(); |
338 | } else { |
|
339 | 0 | f.parityOff(); |
340 | } |
|
341 | ||
342 | 0 | reg = result & 0xFF; |
343 | ||
344 | 0 | if (reg == 0) { |
345 | 0 | f.zeroOn(); |
346 | } else { |
|
347 | 0 | f.zeroOff(); |
348 | } |
|
349 | ||
350 | 0 | if ((reg & 0x80) == 0) { |
351 | 0 | f.signOff(); |
352 | } else { |
|
353 | 0 | f.signOn(); |
354 | } |
|
355 | ||
356 | 0 | f.negativeOn(); |
357 | 0 | f.setBit3(reg); |
358 | 0 | f.setBit5(reg); |
359 | 0 | } |
360 | ||
361 | /** |
|
362 | * AND Operation. |
|
363 | * |
|
364 | * @param value value to &. |
|
365 | */ |
|
366 | public void and(int value) { |
|
367 | // AND the value from memory |
|
368 | 0 | reg &= value; |
369 | ||
370 | 0 | if ((reg & 0x80) == 0) { |
371 | 0 | f.signOff(); |
372 | } else { |
|
373 | 0 | f.signOn(); |
374 | } |
|
375 | ||
376 | 0 | if (reg == 0) { |
377 | 0 | f.zeroOn(); |
378 | } else { |
|
379 | 0 | f.zeroOff(); |
380 | } |
|
381 | ||
382 | 0 | f.halfCarryOn(); |
383 | 0 | f.setParity(reg); |
384 | 0 | f.negativeOff(); |
385 | 0 | f.carryOff(); |
386 | 0 | f.setBit3(reg); |
387 | 0 | f.setBit5(reg); |
388 | 0 | } |
389 | ||
390 | /** |
|
391 | * OR Operation. |
|
392 | * |
|
393 | * @param value Value to | |
|
394 | */ |
|
395 | public void or(int value) { |
|
396 | 0 | reg |= value; // bitwise inclusive OR to turn relevant bits on |
397 | ||
398 | 0 | if ((reg & 0x80) == 0) { |
399 | 0 | f.signOff(); |
400 | } else { |
|
401 | 0 | f.signOn(); |
402 | } |
|
403 | ||
404 | 0 | if (reg == 0) { |
405 | 0 | f.zeroOn(); |
406 | } else { |
|
407 | 0 | f.zeroOff(); |
408 | } |
|
409 | ||
410 | 0 | f.halfCarryOff(); |
411 | 0 | f.setParity(reg); |
412 | 0 | f.negativeOff(); |
413 | 0 | f.carryOff(); |
414 | 0 | f.setBit3(reg); |
415 | 0 | f.setBit5(reg); |
416 | 0 | } |
417 | ||
418 | /** |
|
419 | * XOR Operation (Bitwise Exclusive OR). |
|
420 | * |
|
421 | * @param value Value to ^ |
|
422 | */ |
|
423 | public void xor(int value) { |
|
424 | 0 | reg ^= value; // bitwise exclusive OR |
425 | ||
426 | 0 | if (reg == 0) { |
427 | 0 | f.zeroOn(); |
428 | } else { |
|
429 | 0 | f.zeroOff(); |
430 | } |
|
431 | ||
432 | 0 | if ((reg & 0x80) == 0) { |
433 | 0 | f.signOff(); |
434 | } else { |
|
435 | 0 | f.signOn(); |
436 | } |
|
437 | ||
438 | 0 | f.halfCarryOff(); |
439 | 0 | f.negativeOff(); |
440 | 0 | f.carryOff(); |
441 | 0 | f.setParity(reg); |
442 | 0 | f.setBit3(reg); |
443 | 0 | f.setBit5(reg); |
444 | 0 | } |
445 | ||
446 | ||
447 | /** |
|
448 | * CP Operation - Compare with Accumulator. |
|
449 | * |
|
450 | * @param value Value to compare |
|
451 | */ |
|
452 | public void cp(int value) { |
|
453 | 0 | int result = reg - value; |
454 | ||
455 | 0 | int carrybits = reg ^ value ^ result; |
456 | ||
457 | // half carry |
|
458 | 0 | if ((carrybits & 0x10) != 0) { |
459 | 0 | f.halfCarryOn(); |
460 | } else { |
|
461 | 0 | f.halfCarryOff(); |
462 | } |
|
463 | ||
464 | // carry |
|
465 | 0 | if ((carrybits & 0x100) != 0) { |
466 | 0 | f.carryOn(); |
467 | } else { |
|
468 | 0 | f.carryOff(); |
469 | } |
|
470 | ||
471 | // overflow |
|
472 | 0 | if ((((carrybits << 1) ^ carrybits) & 0x100) != 0) { |
473 | 0 | f.parityOn(); |
474 | } else { |
|
475 | 0 | f.parityOff(); |
476 | } |
|
477 | ||
478 | 0 | result &= 0xFF; |
479 | ||
480 | // sign |
|
481 | 0 | if ((result & 0x80) == 0) { |
482 | 0 | f.signOff(); |
483 | } else { |
|
484 | 0 | f.signOn(); |
485 | } |
|
486 | ||
487 | // zero |
|
488 | 0 | if (result == 0) { |
489 | 0 | f.zeroOn(); |
490 | } else { |
|
491 | 0 | f.zeroOff(); |
492 | } |
|
493 | ||
494 | // negative |
|
495 | 0 | f.negativeOn(); |
496 | ||
497 | // YF and XF flags copied from operand, not result |
|
498 | 0 | f.setBit3(value); |
499 | 0 | f.setBit5(value); |
500 | 0 | } |
501 | ||
502 | /** |
|
503 | * CPL Operation - Complement Accumulator. |
|
504 | */ |
|
505 | public void cpl() { |
|
506 | 0 | reg = (~reg) & 0xff; |
507 | 0 | f.negativeOn(); |
508 | 0 | f.halfCarryOn(); |
509 | 0 | f.setBit3(reg); |
510 | 0 | f.setBit5(reg); |
511 | 0 | } |
512 | ||
513 | /** |
|
514 | * RRA Operation - Rotate Right Accumulator. |
|
515 | */ |
|
516 | public void rra() { |
|
517 | 0 | int temp = reg; |
518 | ||
519 | // Shift Right One Bit Position |
|
520 | 0 | reg >>= 1; |
521 | ||
522 | // Move contents of carry flag to bit 7 |
|
523 | 0 | if (f.carry()) { |
524 | 0 | reg |= 0x80; |
525 | } |
|
526 | ||
527 | // Move original contents to carry flag |
|
528 | 0 | if ((temp & 0x01) != 0) { |
529 | 0 | f.carryOn(); |
530 | } else { |
|
531 | 0 | f.carryOff(); |
532 | } |
|
533 | ||
534 | 0 | f.negativeOff(); f.halfCarryOff(); |
535 | 0 | } |
536 | ||
537 | /** |
|
538 | * RLA Operation - Rotate Left Accumulator. |
|
539 | */ |
|
540 | public void rla() { |
|
541 | 0 | int temp = reg; |
542 | // Shift Left One Bit Position |
|
543 | 0 | reg = (reg << 1) & 0xff; |
544 | ||
545 | // Move contents of carry flag to bit 0 |
|
546 | 0 | if (f.carry()) { |
547 | 0 | reg |= 0x01; |
548 | } |
|
549 | ||
550 | // Move original contents to carry flag |
|
551 | 0 | if ((temp & 0x80) == 0x80) { |
552 | 0 | f.carryOn(); |
553 | } else { |
|
554 | 0 | f.carryOff(); |
555 | } |
|
556 | ||
557 | 0 | f.negativeOff(); f.halfCarryOff(); |
558 | 0 | } |
559 | ||
560 | /** |
|
561 | * RLCA Operation - Rotate Left With Carry Accumulator. |
|
562 | */ |
|
563 | public void rlca() { |
|
564 | // Backup copy of register |
|
565 | 0 | int temp = reg; |
566 | ||
567 | // Shift register left |
|
568 | 0 | reg = (reg << 1) & 0xff; |
569 | ||
570 | // Transfer Original Bit 7 to Bit 0 and Carry Flag |
|
571 | 0 | if ((temp & 0x80) == 0x80) { |
572 | 0 | f.carryOn(); |
573 | 0 | reg |= 0x01; |
574 | } else { |
|
575 | 0 | f.carryOff(); |
576 | } |
|
577 | ||
578 | 0 | f.negativeOff(); f.halfCarryOff(); |
579 | 0 | } |
580 | ||
581 | ||
582 | /** |
|
583 | * RRCA Operation - Rotate Right With Carry Accumulator. |
|
584 | */ |
|
585 | public void rrca() { |
|
586 | 0 | int temp = reg; |
587 | 0 | reg >>= 1; |
588 | 0 | if ((temp & 0x01) != 0) { |
589 | 0 | f.carryOn(); |
590 | 0 | reg |= 0x80; |
591 | } else { |
|
592 | 0 | f.carryOff(); |
593 | } |
|
594 | 0 | f.negativeOff(); f.halfCarryOff(); |
595 | 0 | } |
596 | ||
597 | } |