Coverage Report - uk.co.javagear.Accumulator
 
Classes in this File Line Coverage Branch Coverage Complexity
Accumulator
0% 
0% 
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  
 }