Line 56... |
Line 56... |
* clr_flags: Flags to clear in the SR
|
* clr_flags: Flags to clear in the SR
|
* opc: The opcode
|
* opc: The opcode
|
* op1: First operand value
|
* op1: First operand value
|
* op2: Second operand value
|
* op2: Second operand value
|
* res: Expected result
|
* res: Expected result
|
* str: Output string
|
|
* cy: Expected carry flag
|
* cy: Expected carry flag
|
* ov: Expected overflow flag
|
* ov: Expected overflow flag
|
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
#define TEST_ADD(set_flags, clr_flags, opc, op1, op2, res, str, cy, ov) \
|
#define TEST_ADD(set_flags, clr_flags, opc, op1, op2, res, cy, ov) \
|
l.mfspr r3,r0,SPR_SR ;\
|
l.mfspr r3,r0,SPR_SR ;\
|
LOAD_CONST (r2, set_flags) /* Set flags */ ;\
|
LOAD_CONST (r2, set_flags) /* Set flags */ ;\
|
l.or r3,r3,r2 ;\
|
l.or r3,r3,r2 ;\
|
LOAD_CONST (r2, ~clr_flags) /* Clear flags */ ;\
|
LOAD_CONST (r2, ~clr_flags) /* Clear flags */ ;\
|
l.and r3,r3,r2 ;\
|
l.and r3,r3,r2 ;\
|
l.mtspr r0,r3,SPR_SR ;\
|
l.mtspr r0,r3,SPR_SR ;\
|
;\
|
;\
|
LOAD_CONST (r5,op1) /* Load numbers to add */ ;\
|
LOAD_CONST (r5,op1) /* Load numbers to add */ ;\
|
LOAD_CONST (r6,op2) ;\
|
LOAD_CONST (r6,op2) ;\
|
opc r4,r5,r6 ;\
|
l.mtspr r0,r0,SPR_EPCR_BASE /* Clear record */ ;\
|
|
50: opc r4,r5,r6 ;\
|
l.mfspr r2,r0,SPR_SR /* So we can examine flags */ ;\
|
l.mfspr r2,r0,SPR_SR /* So we can examine flags */ ;\
|
|
l.mfspr r5,r0,SPR_EPCR_BASE /* What triggered exception */ ;\
|
|
PUSH (r5) /* Save EPCR for later */ ;\
|
PUSH (r2) ;\
|
PUSH (r2) ;\
|
CHECK_RES (str, r4, res) ;\
|
PUSH (r4) /* Save result for later */ ;\
|
|
;\
|
|
PUTS (" 0x") ;\
|
|
PUTH (op1) ;\
|
|
PUTS (" + 0x") ;\
|
|
PUTH (op2) ;\
|
|
;\
|
|
LOAD_CONST (r2, set_flags) /* Are we adding in carry */ ;\
|
|
LOAD_CONST (r4, SPR_SR_CY) ;\
|
|
l.and r2,r2,r4 ;\
|
|
l.sfeq r2,r4 ;\
|
|
l.bnf 51f ;\
|
|
l.nop ;\
|
|
;\
|
|
PUTS (" + c") /* CY set to add in? */ ;\
|
|
l.j 52f ;\
|
|
l.nop ;\
|
|
;\
|
|
51: PUTS (" ") /* CY clear to add in? */ ;\
|
|
;\
|
|
52: PUTS (" = 0x") ;\
|
|
PUTH (res) ;\
|
|
PUTS (": ") ;\
|
|
POP (r4) ;\
|
|
CHECK_RES1 (r4, res) ;\
|
|
;\
|
POP(r2) /* Retrieve SR */ ;\
|
POP(r2) /* Retrieve SR */ ;\
|
PUSH(r2) ;\
|
PUSH(r2) ;\
|
LOAD_CONST (r4, SPR_SR_CY) /* The carry bit */ ;\
|
LOAD_CONST (r4, SPR_SR_CY) /* The carry bit */ ;\
|
l.and r2,r2,r4 ;\
|
l.and r2,r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
CHECK_FLAG ("- carry flag set: ", cy) ;\
|
CHECK_FLAG ("- carry flag set: ", cy) ;\
|
;\
|
;\
|
POP(r2) /* Retrieve SR */ ;\
|
POP(r2) /* Retrieve SR */ ;\
|
PUSH(r2) ;\
|
|
LOAD_CONST (r4, SPR_SR_OV) /* The overflow bit */ ;\
|
LOAD_CONST (r4, SPR_SR_OV) /* The overflow bit */ ;\
|
l.and r2,r2,r4 ;\
|
l.and r2,r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
CHECK_FLAG ("- overflow flag set: ", ov)
|
CHECK_FLAG ("- overflow flag set: ", ov) ;\
|
|
;\
|
|
POP (r2) /* Retrieve EPCR */ ;\
|
|
LOAD_CONST (r4, 50b) /* The opcode of interest */ ;\
|
|
l.and r2,r2,r4 ;\
|
|
l.sfeq r2,r4 ;\
|
|
l.bnf 53f ;\
|
|
;\
|
|
PUTS (" - exception triggered: TRUE\n") ;\
|
|
l.j 54f ;\
|
|
l.nop ;\
|
|
;\
|
|
53: PUTS (" - exception triggered: FALSE\n") ;\
|
|
54:
|
|
|
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
* A macro to carry out a test of addition with an immediate value
|
* A macro to carry out a test of addition with an immediate value
|
*
|
*
|
*
|
*
|
Line 99... |
Line 138... |
* clr_flags: Flags to clear in the SR
|
* clr_flags: Flags to clear in the SR
|
* opc: The opcode
|
* opc: The opcode
|
* op1: First operand value
|
* op1: First operand value
|
* op2: Second operand value (immediate)
|
* op2: Second operand value (immediate)
|
* res: Expected result
|
* res: Expected result
|
* str: Output string
|
|
* cy: Expected carry flag
|
* cy: Expected carry flag
|
* ov: Expected overflow flag
|
* ov: Expected overflow flag
|
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
#define TEST_ADDI(set_flags, clr_flags, opc, op1, op2, res, str, cy, ov) \
|
#define TEST_ADDI(set_flags, clr_flags, opc, op1, op2, res, cy, ov) \
|
l.mfspr r3,r0,SPR_SR ;\
|
l.mfspr r3,r0,SPR_SR ;\
|
LOAD_CONST (r2, set_flags) /* Set flags */ ;\
|
LOAD_CONST (r2, set_flags) /* Set flags */ ;\
|
l.or r3,r3,r2 ;\
|
l.or r3,r3,r2 ;\
|
LOAD_CONST (r2, ~clr_flags) /* Clear flags */ ;\
|
LOAD_CONST (r2, ~clr_flags) /* Clear flags */ ;\
|
l.and r3,r3,r2 ;\
|
l.and r3,r3,r2 ;\
|
l.mtspr r0,r3,SPR_SR ;\
|
l.mtspr r0,r3,SPR_SR ;\
|
;\
|
;\
|
LOAD_CONST (r5,op1) /* Load first number to add */ ;\
|
LOAD_CONST (r5,op1) /* Load numbers to add */ ;\
|
opc r4,r5,op2 ;\
|
l.mtspr r0,r0,SPR_EPCR_BASE /* Clear record */ ;\
|
|
55: opc r4,r5,op2 ;\
|
l.mfspr r2,r0,SPR_SR /* So we can examine flags */ ;\
|
l.mfspr r2,r0,SPR_SR /* So we can examine flags */ ;\
|
|
l.mfspr r5,r0,SPR_EPCR_BASE /* What triggered exception */ ;\
|
|
PUSH (r5) /* Save EPCR for later */ ;\
|
PUSH (r2) ;\
|
PUSH (r2) ;\
|
CHECK_RES (str, r4, res) ;\
|
PUSH (r4) /* Save result for later */ ;\
|
|
;\
|
|
PUTS (" 0x") ;\
|
|
PUTH (op1) ;\
|
|
PUTS (" + 0x") ;\
|
|
PUTH (op2) ;\
|
|
;\
|
|
LOAD_CONST (r2, set_flags) /* Are we adding in carry */ ;\
|
|
LOAD_CONST (r4, SPR_SR_CY) ;\
|
|
l.and r2,r2,r4 ;\
|
|
l.sfeq r2,r4 ;\
|
|
l.bnf 56f ;\
|
|
l.nop ;\
|
|
;\
|
|
PUTS (" + c") /* CY set to add in? */ ;\
|
|
l.j 57f ;\
|
|
l.nop ;\
|
|
;\
|
|
56: PUTS (" ") /* CY clear to add in? */ ;\
|
|
;\
|
|
57: PUTS (" = 0x") ;\
|
|
PUTH (res) ;\
|
|
PUTS (": ") ;\
|
|
POP (r4) ;\
|
|
CHECK_RES1 (r4, res) ;\
|
|
;\
|
POP(r2) /* Retrieve SR */ ;\
|
POP(r2) /* Retrieve SR */ ;\
|
PUSH(r2) ;\
|
PUSH(r2) ;\
|
LOAD_CONST (r4, SPR_SR_CY) /* The carry bit */ ;\
|
LOAD_CONST (r4, SPR_SR_CY) /* The carry bit */ ;\
|
l.and r2,r2,r4 ;\
|
l.and r2,r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
CHECK_FLAG ("- carry flag set: ", cy) ;\
|
CHECK_FLAG ("- carry flag set: ", cy) ;\
|
;\
|
;\
|
POP(r2) /* Retrieve SR */ ;\
|
POP(r2) /* Retrieve SR */ ;\
|
PUSH(r2) ;\
|
|
LOAD_CONST (r4, SPR_SR_OV) /* The overflow bit */ ;\
|
LOAD_CONST (r4, SPR_SR_OV) /* The overflow bit */ ;\
|
l.and r2,r2,r4 ;\
|
l.and r2,r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
l.sfeq r2,r4 ;\
|
CHECK_FLAG ("- overflow flag set: ", ov)
|
CHECK_FLAG ("- overflow flag set: ", ov) ;\
|
|
;\
|
|
POP (r2) /* Retrieve EPCR */ ;\
|
|
LOAD_CONST (r4, 55b) /* The opcode of interest */ ;\
|
|
l.and r2,r2,r4 ;\
|
|
l.sfeq r2,r4 ;\
|
|
l.bnf 58f ;\
|
|
;\
|
|
PUTS (" - exception triggered: TRUE\n") ;\
|
|
l.j 59f ;\
|
|
l.nop ;\
|
|
;\
|
|
58: PUTS (" - exception triggered: FALSE\n") ;\
|
|
59:
|
|
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* Start of code
|
|
* ------------------------------------------------------------------------- */
|
.section .text
|
.section .text
|
.global _start
|
.global _start
|
_start:
|
_start:
|
|
l.mfspr r3,r0,SPR_SR
|
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
|
l.and r3,r3,r2
|
|
l.mtspr r0,r3,SPR_SR
|
|
|
|
LOAD_STR (r3, " ** OVE flag cleared **\n")
|
|
l.jal _puts
|
|
l.nop
|
|
|
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
* Test of add signed, l.add
|
* Test of add signed, l.add
|
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
_add:
|
_add:
|
Line 146... |
Line 235... |
l.nop
|
l.nop
|
|
|
/* Add two small positive numbers */
|
/* Add two small positive numbers */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 1, 2, 3,
|
l.add, 1, 2, 3,
|
"0x00000001 + 0x00000002 = 0x00000003: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Check carry in is ignored. */
|
/* Check carry in is ignored. */
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.add, 1, 2, 3,
|
l.add, 1, 2, 3,
|
"0x00000001 + 0x00000002 = 0x00000003: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two small negative numbers. Sets the carry flag but not the
|
/* Add two small negative numbers. Sets the carry flag but not the
|
overflow flag. */
|
overflow flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
l.add, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large positive numbers. Should set neither the
|
/* Add two quite large positive numbers. Should set neither the
|
overflow nor the carry flag. */
|
overflow nor the carry flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0x40000000, 0x3fffffff, 0x7fffffff,
|
l.add, 0x40000000, 0x3fffffff, 0x7fffffff,
|
"0x40000000 + 0x3fffffff = 0x7fffffff: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two large positive numbers. Should set the overflow, but not
|
/* Add two large positive numbers. Should set the overflow, but not
|
the carry flag. */
|
the carry flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0x40000000, 0x40000000, 0x80000000,
|
l.add, 0x40000000, 0x40000000, 0x80000000,
|
"0x40000000 + 0x40000000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Add two quite large negative numbers. Should set the carry, but not
|
/* Add two quite large negative numbers. Should set the carry, but not
|
the overflow flag. */
|
the overflow flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0xc0000000, 0xc0000000, 0x80000000,
|
l.add, 0xc0000000, 0xc0000000, 0x80000000,
|
"0xc0000000 + 0xc0000000 = 0x80000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two large negative numbers. Should set both the overflow and
|
/* Add two large negative numbers. Should set both the overflow and
|
carry flags. */
|
carry flags. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
l.add, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
"0xbfffffff + 0xbfffffff = 0x7ffffffe: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Check that range exceptions are triggered */
|
/* Check that range exceptions are triggered */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
Line 203... |
Line 285... |
l.nop
|
l.nop
|
|
|
/* Check that an overflow alone causes a RANGE Exception. */
|
/* Check that an overflow alone causes a RANGE Exception. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0x40000000, 0x40000000, 0x80000000,
|
l.add, 0x40000000, 0x40000000, 0x80000000,
|
"0x40000000 + 0x40000000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Check that a carry alone does not cause a RANGE Exception. */
|
/* Check that a carry alone does not cause a RANGE Exception. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
l.add, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Check that carry and overflow together cause an exception. */
|
/* Check that carry and overflow together cause an exception. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.add, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
l.add, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
"0xbfffffff + 0xbfffffff = 0x7ffffffe: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Finished checking range exceptions */
|
/* Finished checking range exceptions */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
Line 239... |
Line 318... |
l.nop
|
l.nop
|
|
|
/* Add two small positive numbers */
|
/* Add two small positive numbers */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 1, 2, 3,
|
l.addc, 1, 2, 3,
|
"0x00000001 + 0x00000002 = 0x00000003: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two small negative numbers. Sets the carry flag but not the
|
/* Add two small negative numbers. Sets the carry flag but not the
|
overflow flag. */
|
overflow flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
l.addc, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large positive numbers. Should set neither the
|
/* Add two quite large positive numbers. Should set neither the
|
overflow nor the carry flag. */
|
overflow nor the carry flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0x40000000, 0x3fffffff, 0x7fffffff,
|
l.addc, 0x40000000, 0x3fffffff, 0x7fffffff,
|
"0x40000000 + 0x3fffffff = 0x7fffffff: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two quite large positive numbers with a carry in. Should set
|
/* Add two quite large positive numbers with a carry in. Should set
|
the overflow but not the carry flag. */
|
the overflow but not the carry flag. */
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.addc, 0x40000000, 0x3fffffff, 0x80000000,
|
l.addc, 0x40000000, 0x3fffffff, 0x80000000,
|
"0x40000000 + 0x3fffffff + c = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Add two large positive numbers. Should set the overflow, but not
|
/* Add two large positive numbers. Should set the overflow, but not
|
the carry flag. */
|
the carry flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0x40000000, 0x40000000, 0x80000000,
|
l.addc, 0x40000000, 0x40000000, 0x80000000,
|
"0x40000000 + 0x40000000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Add the largest unsigned value to zero with a carry. This
|
/* Add the largest unsigned value to zero with a carry. This
|
potentially can break a simplistic test for carry that does not
|
potentially can break a simplistic test for carry that does not
|
consider the carry flag properly. Do it both ways around. */
|
consider the carry flag properly. Do it both ways around. */
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.addc, 0xffffffff, 0x00000000, 0x00000000,
|
l.addc, 0xffffffff, 0x00000000, 0x00000000,
|
"0xffffffff + 0x00000000 + c = 0x00000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.addc, 0x00000000, 0xffffffff, 0x00000000,
|
l.addc, 0x00000000, 0xffffffff, 0x00000000,
|
"0x00000000 + 0xffffffff + c = 0x00000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large negative numbers. Should set the carry, but not
|
/* Add two quite large negative numbers. Should set the carry, but not
|
the overflow flag. flag. */
|
the overflow flag. flag. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0xc0000000, 0xc0000000, 0x80000000,
|
l.addc, 0xc0000000, 0xc0000000, 0x80000000,
|
"0xc0000000 + 0xc0000000 = 0x80000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large negative numbers that would overflow, with a
|
/* Add two quite large negative numbers that would overflow, with a
|
carry that just avoids the overflow. Should set the carry, but not
|
carry that just avoids the overflow. Should set the carry, but not
|
the overflow flag. flag. */
|
the overflow flag. flag. */
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.addc, 0xc0000000, 0xbfffffff, 0x80000000,
|
l.addc, 0xc0000000, 0xbfffffff, 0x80000000,
|
"0xc0000000 + 0xbfffffff + c = 0x80000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two large negative numbers. Should set both the overflow and
|
/* Add two large negative numbers. Should set both the overflow and
|
carry flags. */
|
carry flags. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
l.addc, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
"0xbfffffff + 0xbfffffff = 0x7ffffffe: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Check that range exceptions are triggered */
|
/* Check that range exceptions are triggered */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
Line 319... |
Line 388... |
|
|
/* Check that an overflow alone causes a RANGE Exception, even when it
|
/* Check that an overflow alone causes a RANGE Exception, even when it
|
is the carry that causes the overflow. */
|
is the carry that causes the overflow. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0x40000000, 0x40000000, 0x80000000,
|
l.addc, 0x40000000, 0x40000000, 0x80000000,
|
"0x40000000 + 0x40000000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.addc, 0x40000000, 0x3fffffff, 0x80000000,
|
l.addc, 0x40000000, 0x3fffffff, 0x80000000,
|
"0x40000000 + 0x3fffffff + c = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Check that a carry alone does not cause a RANGE Exception, even
|
/* Check that a carry alone does not cause a RANGE Exception, even
|
when it is the carry that causes the overflow. */
|
when it is the carry that causes the overflow. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
l.addc, 0xffffffff, 0xfffffffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADD (SPR_SR_CY, SPR_SR_OV,
|
l.addc, 0x00000000, 0xffffffff, 0x00000000,
|
l.addc, 0x00000000, 0xffffffff, 0x00000000,
|
"0x00000000 + 0xffffffff + c = 0x00000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Check that carry and overflow together cause an exception. */
|
/* Check that carry and overflow together cause an exception. */
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADD (0, SPR_SR_CY | SPR_SR_OV,
|
l.addc, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
l.addc, 0xbfffffff, 0xbfffffff, 0x7ffffffe,
|
"0xbfffffff + 0xbfffffff = 0x7ffffffe: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Finished checking range exceptions */
|
/* Finished checking range exceptions */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
Line 366... |
Line 430... |
l.nop
|
l.nop
|
|
|
/* Add two small positive numbers */
|
/* Add two small positive numbers */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 1, 2, 3,
|
l.addi, 1, 2, 3,
|
"0x00000001 + 0x00000002 = 0x00000003: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Check carry in is ignored. */
|
/* Check carry in is ignored. */
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addi, 1, 2, 3,
|
l.addi, 1, 2, 3,
|
"0x00000001 + 0x00000002 = 0x00000003: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two small negative numbers. Sets the carry flag but not the
|
/* Add two small negative numbers. Sets the carry flag but not the
|
overflow flag. */
|
overflow flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0xffffffff, 0xfffe, 0xfffffffd,
|
l.addi, 0xffffffff, 0xfffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large positive numbers. Should set neither the
|
/* Add two quite large positive numbers. Should set neither the
|
overflow nor the carry flag. */
|
overflow nor the carry flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0x7fff8000, 0x7fff, 0x7fffffff,
|
l.addi, 0x7fff8000, 0x7fff, 0x7fffffff,
|
"0x7fff8000 + 0x00007fff = 0x7fffffff: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two large positive numbers. Should set the overflow, but not
|
/* Add two large positive numbers. Should set the overflow, but not
|
the carry flag. */
|
the carry flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0x7fffc000, 0x4000, 0x80000000,
|
l.addi, 0x7fffc000, 0x4000, 0x80000000,
|
"0x7fffc000 + 0x00004000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Add two quite large negative numbers. Should set the carry, but not
|
/* Add two quite large negative numbers. Should set the carry, but not
|
the overflow flag. */
|
the overflow flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0x80008000, 0x8000, 0x80000000,
|
l.addi, 0x80008000, 0x8000, 0x80000000,
|
"0x80008000 + 0xffff8000 = 0x80000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two large negative numbers. Should set both the overflow and
|
/* Add two large negative numbers. Should set both the overflow and
|
carry flags. */
|
carry flags. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0x80007fff, 0x8000, 0x7fffffff,
|
l.addi, 0x80007fff, 0x8000, 0x7fffffff,
|
"0x80007fff + 0xffff8000 = 0x7fffffff: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Check that range exceptions are triggered */
|
/* Check that range exceptions are triggered */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
Line 423... |
Line 480... |
l.nop
|
l.nop
|
|
|
/* Check that an overflow alone causes a RANGE Exception. */
|
/* Check that an overflow alone causes a RANGE Exception. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0x7fffc000, 0x4000, 0x80000000,
|
l.addi, 0x7fffc000, 0x4000, 0x80000000,
|
"0x7fffc000 + 0x00004000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Check that a carry alone does not cause a RANGE Exception. */
|
/* Check that a carry alone does not cause a RANGE Exception. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0xffffffff, 0xfffe, 0xfffffffd,
|
l.addi, 0xffffffff, 0xfffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Check that carry and overflow together cause an exception. */
|
/* Check that carry and overflow together cause an exception. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addi, 0x80007fff, 0x8000, 0x7fffffff,
|
l.addi, 0x80007fff, 0x8000, 0x7fffffff,
|
"0x80007fff + 0xffff8000 = 0x7ffffffe: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Finished checking range exceptions */
|
/* Finished checking range exceptions */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
Line 459... |
Line 513... |
l.nop
|
l.nop
|
|
|
/* Add two small positive numbers */
|
/* Add two small positive numbers */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 1, 2, 3,
|
l.addic, 1, 2, 3,
|
"0x00000001 + 0x00000002 = 0x00000003: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two small negative numbers. Sets the carry flag but not the
|
/* Add two small negative numbers. Sets the carry flag but not the
|
overflow flag. */
|
overflow flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0xffffffff, 0xfffe, 0xfffffffd,
|
l.addic, 0xffffffff, 0xfffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large positive numbers. Should set neither the
|
/* Add two quite large positive numbers. Should set neither the
|
overflow nor the carry flag. */
|
overflow nor the carry flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0x7fff8000, 0x7fff, 0x7fffffff,
|
l.addic, 0x7fff8000, 0x7fff, 0x7fffffff,
|
"0x7fff8000 + 0x00007fff = 0x7fffffff: ",
|
|
FALSE, FALSE)
|
FALSE, FALSE)
|
|
|
/* Add two quite large positive numbers with a carry in. Should set
|
/* Add two quite large positive numbers with a carry in. Should set
|
the overflow but not the carry flag. */
|
the overflow but not the carry flag. */
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addic, 0x7fff8000, 0x7fff, 0x80000000,
|
l.addic, 0x7fff8000, 0x7fff, 0x80000000,
|
"0x7fff8000 + 0x00007fff + c = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Add two large positive numbers. Should set the overflow, but not
|
/* Add two large positive numbers. Should set the overflow, but not
|
the carry flag. */
|
the carry flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0x7fffc000, 0x4000, 0x80000000,
|
l.addic, 0x7fffc000, 0x4000, 0x80000000,
|
"0x7fffc000 + 0x00004000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Add the largest unsigned value to zero with a carry. This
|
/* Add the largest unsigned value to zero with a carry. This
|
potentially can break a simplistic test for carry that does not
|
potentially can break a simplistic test for carry that does not
|
consider the carry flag properly. Do it both ways around. */
|
consider the carry flag properly. Do it both ways around. */
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addic, 0xffffffff, 0x0000, 0x00000000,
|
l.addic, 0xffffffff, 0x0000, 0x00000000,
|
"0xffffffff + 0x00000000 + c = 0x00000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addic, 0x00000000, 0xffff, 0x00000000,
|
l.addic, 0x00000000, 0xffff, 0x00000000,
|
"0x00000000 + 0xffffffff + c = 0x00000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large negative numbers. Should set the carry, but not
|
/* Add two quite large negative numbers. Should set the carry, but not
|
the overflow flag. flag. */
|
the overflow flag. flag. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0x80008000, 0x8000, 0x80000000,
|
l.addic, 0x80008000, 0x8000, 0x80000000,
|
"0x80008000 + 0xffff8000 = 0x80000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two quite large negative numbers that would overflow, with a
|
/* Add two quite large negative numbers that would overflow, with a
|
carry that just avoids the overflow. Should set the carry, but not
|
carry that just avoids the overflow. Should set the carry, but not
|
the overflow flag. flag. */
|
the overflow flag. flag. */
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addic, 0x80007fff, 0x8000, 0x80000000,
|
l.addic, 0x80007fff, 0x8000, 0x80000000,
|
"0x80007fff + 0xffff8000 + c = 0x80000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Add two large negative numbers. Should set both the overflow and
|
/* Add two large negative numbers. Should set both the overflow and
|
carry flags. */
|
carry flags. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0x80007fff, 0x8000, 0x7fffffff,
|
l.addic, 0x80007fff, 0x8000, 0x7fffffff,
|
"0x80007fff + 0xffff8000 = 0x7fffffff: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Check that range exceptions are triggered */
|
/* Check that range exceptions are triggered */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
LOAD_CONST (r2, SPR_SR_OVE) /* Set OVE */
|
Line 539... |
Line 583... |
|
|
/* Check that an overflow alone causes a RANGE Exception, even when it
|
/* Check that an overflow alone causes a RANGE Exception, even when it
|
is the carry that causes the overflow. */
|
is the carry that causes the overflow. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0x7fffc000, 0x4000, 0x80000000,
|
l.addic, 0x7fffc000, 0x4000, 0x80000000,
|
"0x7fffc000 + 0x00004000 = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addic, 0x7fffc000, 0x3fff, 0x80000000,
|
l.addic, 0x7fffc000, 0x3fff, 0x80000000,
|
"0x7fffc000 + 0x00003fff + c = 0x80000000: ",
|
|
FALSE, TRUE)
|
FALSE, TRUE)
|
|
|
/* Check that a carry alone does not cause a RANGE Exception, even
|
/* Check that a carry alone does not cause a RANGE Exception, even
|
when it is the carry that causes the overflow. */
|
when it is the carry that causes the overflow. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0xffffffff, 0xfffe, 0xfffffffd,
|
l.addic, 0xffffffff, 0xfffe, 0xfffffffd,
|
"0xffffffff + 0xfffffffe = 0xfffffffd: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
TEST_ADDI (SPR_SR_CY, SPR_SR_OV,
|
l.addic, 0x00000000, 0xffff, 0x00000000,
|
l.addic, 0x00000000, 0xffff, 0x00000000,
|
"0x00000000 + 0xffffffff + c = 0x00000000: ",
|
|
TRUE, FALSE)
|
TRUE, FALSE)
|
|
|
/* Check that carry and overflow together cause an exception. */
|
/* Check that carry and overflow together cause an exception. */
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
TEST_ADDI (0, SPR_SR_CY | SPR_SR_OV,
|
l.addic, 0x80007fff, 0x8000, 0x7fffffff,
|
l.addic, 0x80007fff, 0x8000, 0x7fffffff,
|
"0x80007fff + 0xffff8000 = 0x7ffffffe: ",
|
|
TRUE, TRUE)
|
TRUE, TRUE)
|
|
|
/* Finished checking range exceptions */
|
/* Finished checking range exceptions */
|
l.mfspr r3,r0,SPR_SR
|
l.mfspr r3,r0,SPR_SR
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|
LOAD_CONST (r2, ~SPR_SR_OVE) /* Clear OVE */
|