Skip to content

Commit 419a994

Browse files
author
Federico Berti
committed
68k: fix flags for shift/rotate instructions when shift value = 0
1 parent feb8938 commit 419a994

2 files changed

Lines changed: 199 additions & 40 deletions

File tree

src/m68k/cpu/CpuCore.java

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -379,16 +379,16 @@ public void calcFlagsParam(InstructionType type, int src, int dst, int result, i
379379
{
380380
//params are different here!
381381
if(src != 0) // shift count
382-
{
383-
if(dst != 0) // last bit out
384-
{
385-
reg_sr |= (C_FLAG | X_FLAG);
386-
}
387-
else
388-
{
389-
reg_sr &= ~(C_FLAG | X_FLAG);
390-
}
391-
}
382+
{
383+
if(dst != 0) // last bit out
384+
{
385+
reg_sr |= (C_FLAG | X_FLAG);
386+
} else {
387+
reg_sr &= ~(C_FLAG | X_FLAG);
388+
}
389+
} else {
390+
reg_sr &= ~(C_FLAG);
391+
}
392392

393393
if(result == 0)
394394
{
@@ -424,16 +424,16 @@ public void calcFlagsParam(InstructionType type, int src, int dst, int result, i
424424
{
425425
//params are different here!
426426
if(src != 0) // shift count
427-
{
428-
if(dst != 0) // last bit out
429-
{
430-
reg_sr |= (C_FLAG | X_FLAG);
431-
}
432-
else
433-
{
434-
reg_sr &= ~(C_FLAG | X_FLAG);
435-
}
436-
}
427+
{
428+
if(dst != 0) // last bit out
429+
{
430+
reg_sr |= (C_FLAG | X_FLAG);
431+
} else {
432+
reg_sr &= ~(C_FLAG | X_FLAG);
433+
}
434+
} else {
435+
reg_sr &= ~(C_FLAG);
436+
}
437437

438438
if(result == 0)
439439
{
@@ -504,16 +504,16 @@ public void calcFlagsParam(InstructionType type, int src, int dst, int result, i
504504
case ROXR:
505505
{
506506
if(src > 0) //shift count
507-
{
508-
if(dst != 0) //last bit out
509-
{
510-
reg_sr |= (C_FLAG | X_FLAG);
511-
}
512-
else
513-
{
514-
reg_sr &= ~(C_FLAG | X_FLAG);
515-
}
516-
}
507+
{
508+
if(dst != 0) //last bit out
509+
{
510+
reg_sr |= (C_FLAG | X_FLAG);
511+
} else {
512+
reg_sr &= ~(C_FLAG | X_FLAG);
513+
}
514+
} else {
515+
reg_sr &= ~(C_FLAG);
516+
}
517517

518518
if(result == 0)
519519
{
@@ -635,16 +635,16 @@ public void calcFlagsParam(InstructionType type, int src, int dst, int result, i
635635
case ROR:
636636
{
637637
if(src > 0) //shift count
638-
{
639-
if(dst != 0) //last bit out
640-
{
641-
reg_sr |= C_FLAG;
642-
}
643-
else
644-
{
645-
reg_sr &= ~(C_FLAG);
646-
}
647-
}
638+
{
639+
if(dst != 0) //last bit out
640+
{
641+
reg_sr |= C_FLAG;
642+
} else {
643+
reg_sr &= ~(C_FLAG);
644+
}
645+
} else {
646+
reg_sr &= ~(C_FLAG);
647+
}
648648

649649
if(result == 0)
650650
{
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package m68k.cpu.instructions;
2+
3+
import junit.framework.Assert;
4+
import miggy.BasicSetup;
5+
6+
import static miggy.SystemModel.CPU;
7+
import static miggy.SystemModel.CpuFlag;
8+
9+
/**
10+
* ${FILE}
11+
* <p>
12+
* Check Flags for shift/rotate instructions when shift value = 0
13+
* <p>
14+
* Federico Berti
15+
* <p>
16+
* Copyright 2019
17+
*/
18+
public class BitShiftTest extends BasicSetup {
19+
20+
private int destReg = 0;
21+
private int srcReg = 1;
22+
private int shiftOrRotateValue = 0;
23+
24+
public BitShiftTest(String test) {
25+
super(test);
26+
}
27+
28+
/**
29+
* Shift count of zero:
30+
* <p>
31+
* X - unaffected
32+
* V - cleared
33+
* C - cleared
34+
*/
35+
public void testLsl() {
36+
int opcode = 0xE328; //lsl.b d1,d0
37+
int d0 = 0x07654321;
38+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0);
39+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0);
40+
}
41+
42+
public void testLsr() {
43+
int opcode = 0xE228; //lsr.b d1,d0
44+
int d0 = 0x07654321;
45+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0);
46+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0);
47+
}
48+
49+
/**
50+
* Shift count of zero:
51+
* <p>
52+
* X - unaffected
53+
* V - cleared
54+
* C - cleared
55+
*/
56+
public void testAsl() {
57+
int opcode = 0xE320; //asl.b d1,d0
58+
int d0 = 0x4321;
59+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0);
60+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0);
61+
}
62+
63+
public void testAsr() {
64+
int opcode = 0xE220; //asr.b d1,d0
65+
int d0 = 0x4321;
66+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0);
67+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0);
68+
}
69+
70+
/**
71+
* Shift count of zero:
72+
* <p>
73+
* X - unaffected
74+
* V - cleared
75+
* C - cleared
76+
*/
77+
public void testRol() {
78+
int opcode = 0xE338; //rol.b d1,d0
79+
int d0 = 0x4321;
80+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0);
81+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0);
82+
}
83+
84+
public void testRor() {
85+
int opcode = 0xE238; //ror.b d1,d0
86+
int d0 = 0x4321;
87+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0);
88+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0);
89+
}
90+
91+
/**
92+
* Shift count of zero:
93+
* <p>
94+
* X - unaffected
95+
* V - cleared
96+
* C - set to the value of the extend bit
97+
*/
98+
public void testRoxl() {
99+
int opcode = 0xE330; //roxl.b d1,d0
100+
int d0 = 0x4321;
101+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0, true);
102+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0, true);
103+
}
104+
105+
public void testRoxr() {
106+
int opcode = 0xE230; //roxr.b d1,d0
107+
int d0 = 0x4321;
108+
testInstInternal(opcode, CpuFlag.C | CpuFlag.X | CpuFlag.V, d0, true);
109+
testInstInternal(opcode, CpuFlag.C | CpuFlag.V, d0, true);
110+
}
111+
112+
private void testInstInternal(int opcode, int flagState, int d0) {
113+
testInstInternal(opcode, flagState, d0, false);
114+
}
115+
116+
private void testInstInternal(int opcode, int flagState, int d0, boolean isRox) {
117+
testOpcodeInternal(opcode, flagState, d0, isRox); //byte
118+
testOpcodeInternal(opcode + 0x40, flagState, d0, isRox); //word
119+
testOpcodeInternal(opcode + 0x80, flagState, d0, isRox); //long
120+
}
121+
122+
private void testOpcodeInternal(int opcode, int flagState, int d0, boolean isRox) {
123+
setUp();
124+
setInstruction(opcode);
125+
CPU.setDataRegister(destReg, d0);
126+
CPU.setDataRegister(srcReg, shiftOrRotateValue);
127+
CPU.setCCR(0);
128+
CPU.setFlags(flagState);
129+
130+
CPU.execute();
131+
assertEquals("Check result", d0, CPU.getDataRegister(destReg));
132+
assertFlagStates(flagState, isRox);
133+
}
134+
135+
private static void assertFlagStates(int beforeState, boolean isRox) {
136+
switch (beforeState) {
137+
case CpuFlag.C | CpuFlag.X | CpuFlag.V:
138+
assertTrue("Check X", CPU.isSet(CpuFlag.X));
139+
break;
140+
case CpuFlag.C | CpuFlag.V:
141+
assertFalse("Check X", CPU.isSet(CpuFlag.X));
142+
break;
143+
default:
144+
Assert.fail("Unknown flag combination: " + beforeState);
145+
break;
146+
}
147+
assertFalse("Check V", CPU.isSet(CpuFlag.V));
148+
if (isRox) {
149+
assertEquals("Check C", CPU.isSet(CpuFlag.X),
150+
CPU.isSet(CpuFlag.C));
151+
} else {
152+
assertFalse("Check C", CPU.isSet(CpuFlag.C));
153+
}
154+
assertFalse("Check Z", CPU.isSet(CpuFlag.Z));
155+
assertFalse("Check N", CPU.isSet(CpuFlag.N));
156+
}
157+
158+
159+
}

0 commit comments

Comments
 (0)