/*
|
/*
|
OR1200 carry bit checking
|
OR1200 carry bit checking
|
|
|
Carry generated on all adds which we interpret to be
|
Carry generated on all adds which we interpret to be
|
unsigned. The CPU will generate both CY and OV.
|
unsigned. The CPU will generate both CY and OV.
|
CY is generated when unsigned values generate an extra bit.
|
CY is generated when unsigned values generate an extra bit.
|
OV is when the values, interpreted as signed, cannot have
|
OV is when the values, interpreted as signed, cannot have
|
the result displayed as it is too large.
|
the result displayed as it is too large.
|
|
|
OV is not checked here. Just CY generation and inclusion by
|
OV is not checked here. Just CY generation and inclusion by
|
the l.addc and l.addic instructions.
|
the l.addc and l.addic instructions.
|
|
|
Very basic, testing.
|
Very basic, testing.
|
|
|
TODO: Substraction carry out testing.
|
TODO: Substraction carry out testing.
|
|
|
Julius Baxter, ORSoC AB, julius.baxter@orsoc.se
|
Julius Baxter, ORSoC AB, julius.baxter@orsoc.se
|
|
|
*/
|
*/
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
|
//// Copyright (C) 2011 Authors and OPENCORES.ORG ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
#include "spr-defs.h"
|
#include "spr-defs.h"
|
#include "board.h"
|
#include "board.h"
|
#include "or1200-defines.h"
|
#include "or1200-defines.h"
|
|
|
|
|
/* =================================================== [ exceptions ] === */
|
/* =================================================== [ exceptions ] === */
|
.section .vectors, "ax"
|
.section .vectors, "ax"
|
|
|
|
|
/* ---[ 0x100: RESET exception ]----------------------------------------- */
|
/* ---[ 0x100: RESET exception ]----------------------------------------- */
|
.org 0x100
|
.org 0x100
|
l.movhi r0, 0
|
l.movhi r0, 0
|
/* Clear status register */
|
/* Clear status register */
|
l.ori r1, r0, SPR_SR_SM
|
l.ori r1, r0, SPR_SR_SM
|
l.mtspr r0, r1, SPR_SR
|
l.mtspr r0, r1, SPR_SR
|
/* Clear timer */
|
/* Clear timer */
|
l.mtspr r0, r0, SPR_TTMR
|
l.mtspr r0, r0, SPR_TTMR
|
|
|
/* Jump to program initialisation code */
|
/* Jump to program initialisation code */
|
.global _start
|
.global _start
|
l.movhi r4, hi(_start)
|
l.movhi r4, hi(_start)
|
l.ori r4, r4, lo(_start)
|
l.ori r4, r4, lo(_start)
|
l.jr r4
|
l.jr r4
|
l.nop
|
l.nop
|
|
|
.org 0x600
|
.org 0x600
|
l.nop 0x1
|
l.nop 0x1
|
|
|
|
|
/* ---[ 0x700: Illegal instruction exception ]-------------------------- */
|
/* ---[ 0x700: Illegal instruction exception ]-------------------------- */
|
.org 0x700
|
.org 0x700
|
#ifndef OR1200_IMPL_ADDC
|
#ifndef OR1200_IMPL_ADDC
|
// No problem - instruction not supported
|
// No problem - instruction not supported
|
l.movhi r3, hi(0x8000000d)
|
l.movhi r3, hi(0x8000000d)
|
l.ori r3, r3, lo(0x8000000d)
|
l.ori r3, r3, lo(0x8000000d)
|
l.nop 0x2
|
l.nop 0x2
|
l.ori r3, r0, 0
|
l.ori r3, r0, 0
|
#else
|
#else
|
l.ori r3, r0, 1
|
l.ori r3, r0, 1
|
#endif
|
#endif
|
l.nop 0x1
|
l.nop 0x1
|
|
|
/* ---[ 0xb00: Range exception ]---------------------------------------- */
|
/* ---[ 0xb00: Range exception ]---------------------------------------- */
|
.org 0xb00
|
.org 0xb00
|
l.sw 0(r0), r3
|
l.sw 0(r0), r3
|
l.ori r3, r0, 0xaaee
|
l.ori r3, r0, 0xaaee
|
l.nop 0x2
|
l.nop 0x2
|
l.lwz r3, 0(r0)
|
l.lwz r3, 0(r0)
|
l.rfe
|
l.rfe
|
|
|
/* =================================================== [ text ] === */
|
/* =================================================== [ text ] === */
|
.section .text
|
.section .text
|
|
|
/* =================================================== [ start ] === */
|
/* =================================================== [ start ] === */
|
|
|
.global _start
|
.global _start
|
_start:
|
_start:
|
// Clear all regs
|
// Clear regs
|
l.movhi r1, 0
|
l.movhi r1, 0
|
l.movhi r2, 0
|
l.movhi r2, 0
|
l.movhi r3, 0
|
l.movhi r3, 0
|
l.movhi r4, 0
|
l.movhi r4, 0
|
l.movhi r5, 0
|
l.movhi r5, 0
|
l.movhi r6, 0
|
l.movhi r6, 0
|
l.movhi r7, 0
|
|
l.movhi r8, 0
|
|
l.movhi r9, 0
|
|
l.movhi r10, 0
|
|
l.movhi r11, 0
|
|
l.movhi r12, 0
|
|
l.movhi r13, 0
|
|
l.movhi r14, 0
|
|
l.movhi r15, 0
|
|
l.movhi r16, 0
|
|
l.movhi r17, 0
|
|
l.movhi r18, 0
|
|
l.movhi r19, 0
|
|
l.movhi r20, 0
|
|
l.movhi r21, 0
|
|
l.movhi r22, 0
|
|
l.movhi r23, 0
|
|
l.movhi r24, 0
|
|
l.movhi r25, 0
|
|
l.movhi r26, 0
|
|
l.movhi r27, 0
|
|
l.movhi r28, 0
|
|
l.movhi r29, 0
|
|
l.movhi r30, 0
|
|
l.movhi r31, 0
|
|
|
|
#ifdef OR1200_IMPL_CY
|
#ifdef OR1200_IMPL_CY
|
// Kick off test
|
// Kick off test
|
l.jal _main
|
l.jal _main
|
#else
|
#else
|
// Not supported, exit test
|
// Not supported, exit test
|
l.j _finish
|
l.j _finish
|
#endif
|
#endif
|
l.nop
|
l.nop
|
|
|
|
|
/* =================================================== [ main ] === */
|
/* =================================================== [ main ] === */
|
|
|
|
|
#define CHECK_CY_CLEAR \
|
#define CHECK_CY_CLEAR \
|
l.mfspr r20, r0, SPR_SR ; \
|
l.mfspr r6, r0, SPR_SR ; \
|
l.andi r21, r20, SPR_SR_CY ; \
|
l.andi r6, r6, SPR_SR_CY ; \
|
l.sfne r21, r0 ; \
|
l.sfne r6, r0 ; \
|
l.bf _fail ; \
|
l.bf _fail ; \
|
l.nop
|
l.nop
|
|
|
#define CHECK_CY_SET \
|
#define CHECK_CY_SET \
|
l.mfspr r20, r0, SPR_SR ; \
|
l.mfspr r6, r0, SPR_SR ; \
|
l.andi r21, r20, SPR_SR_CY ; \
|
l.andi r6, r6, SPR_SR_CY ; \
|
l.sfnei r21, SPR_SR_CY ; \
|
l.sfnei r6, SPR_SR_CY ; \
|
l.bf _fail ; \
|
l.bf _fail ; \
|
l.nop
|
l.nop
|
|
|
.global _main
|
.global _main
|
_main:
|
_main:
|
|
|
// Set up some values, check the CY bit is cleared from reset
|
// Set up some values, check the CY bit is cleared from reset
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
// A large unsigned value
|
// A large unsigned value
|
l.movhi r4, 0xffff
|
l.movhi r4, 0xffff
|
l.ori r4, r4, 0xefff
|
l.ori r4, r4, 0xefff
|
|
|
// A value large enough to cause carry
|
// A value large enough to cause carry
|
l.ori r5, r0, 0x1001
|
l.ori r5, r0, 0x1001
|
|
|
l.add r3, r5, r4 ;// Should set CY
|
l.add r3, r5, r4 ;// Should set CY
|
l.nop 0x2
|
l.nop 0x2
|
CHECK_CY_SET
|
CHECK_CY_SET
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
l.addi r3, r4, 0x1001 ;// Should set CY
|
l.addi r3, r4, 0x1001 ;// Should set CY
|
l.nop 0x2
|
l.nop 0x2
|
CHECK_CY_SET
|
CHECK_CY_SET
|
|
|
l.addi r3, r4, 0x1000 ;// Shouldn't set CY
|
l.addi r3, r4, 0x1000 ;// Shouldn't set CY
|
l.nop 0x2
|
l.nop 0x2
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
// Check use of carry - l.addc
|
// Check use of carry - l.addc
|
l.addi r3, r4, 0x1001 ;// Should set CY
|
l.addi r3, r4, 0x1001 ;// Should set CY
|
;; // Consequtive instructions
|
;; // Consequtive instructions
|
l.addc r3, r3, r5 ;// r3 should be 0x1002
|
l.addc r3, r3, r5 ;// r3 should be 0x1002
|
l.nop 0x2 ;// Report
|
l.nop 0x2 ;// Report
|
|
|
l.sfnei r3, 0x1002
|
l.sfnei r3, 0x1002
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
l.add r3, r4, r5 ;// Should set CY
|
l.add r3, r4, r5 ;// Should set CY
|
l.nop ;// 1 delay instruction
|
l.nop ;// 1 delay instruction
|
l.addc r3, r3, r5 ;// r3 should be 0x1002
|
l.addc r3, r3, r5 ;// r3 should be 0x1002
|
l.nop 0x2 ;// Report
|
l.nop 0x2 ;// Report
|
|
|
l.sfnei r3, 0x1002
|
l.sfnei r3, 0x1002
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
l.add r3, r4, r5 ;// Should set
|
l.add r3, r4, r5 ;// Should set
|
l.nop 0x2 ;// 1 delay instruction
|
l.nop 0x2 ;// 1 delay instruction
|
l.nop ;// 2nd delay instruction
|
l.nop ;// 2nd delay instruction
|
l.addc r3, r3, r5 ;// r3 should be 0x1002
|
l.addc r3, r3, r5 ;// r3 should be 0x1002
|
l.nop 0x2 ;// Report
|
l.nop 0x2 ;// Report
|
|
|
l.sfnei r3, 0x1002
|
l.sfnei r3, 0x1002
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
// Check use of carry - l.addic
|
// Check use of carry - l.addic
|
l.addi r3, r4, 0x1001 ;// Should set CY
|
l.addi r3, r4, 0x1001 ;// Should set CY
|
;; // Consequtive instructions
|
;; // Consequtive instructions
|
l.addic r3, r3, 0x1 ;// r3 should be 2
|
l.addic r3, r3, 0x1 ;// r3 should be 2
|
l.nop 0x2 ;// Report
|
l.nop 0x2 ;// Report
|
|
|
l.sfnei r3, 0x2
|
l.sfnei r3, 0x2
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
l.add r3, r4, r5 ;// Should set CY
|
l.add r3, r4, r5 ;// Should set CY
|
l.nop ;// 1 delay instruction
|
l.nop ;// 1 delay instruction
|
l.addic r3, r3, 0x1 ;// r3 should be 2
|
l.addic r3, r3, 0x1 ;// r3 should be 2
|
l.nop 0x2 ;// Report
|
l.nop 0x2 ;// Report
|
|
|
l.sfnei r3, 0x2
|
l.sfnei r3, 0x2
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
l.add r3, r4, r5 ;// Should set
|
l.add r3, r4, r5 ;// Should set
|
l.nop 0x2 ;// 1 delay instruction
|
l.nop 0x2 ;// 1 delay instruction
|
l.nop ;// 2nd delay instruction
|
l.nop ;// 2nd delay instruction
|
l.addic r3, r3, 0x1 ;// r3 should be 2
|
l.addic r3, r3, 0x1 ;// r3 should be 2
|
l.nop 0x2 ;// Report
|
l.nop 0x2 ;// Report
|
|
|
l.sfnei r3, 0x2
|
l.sfnei r3, 0x2
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
// Add with carry and generate carry with l.addc
|
// Add with carry and generate carry with l.addc
|
|
|
l.add r3, r4, r5
|
l.add r3, r4, r5
|
l.addc r3, r4, r5
|
l.addc r3, r4, r5
|
l.nop 0x2
|
l.nop 0x2
|
|
|
l.sfnei r3, 0x1
|
l.sfnei r3, 0x1
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
CHECK_CY_SET
|
CHECK_CY_SET
|
|
|
l.add r3, r0, r0 ;// Should clear CY
|
l.add r3, r0, r0 ;// Should clear CY
|
CHECK_CY_CLEAR
|
CHECK_CY_CLEAR
|
|
|
// Add with carry and generate carry with l.addic
|
// Add with carry and generate carry with l.addic
|
|
|
l.addi r3, r4, 0x1001
|
l.addi r3, r4, 0x1001
|
l.addic r3, r4, 0x1001
|
l.addic r3, r4, 0x1001
|
l.nop 0x2
|
l.nop 0x2
|
|
|
l.sfnei r3, 0x1
|
l.sfnei r3, 0x1
|
l.bf _fail
|
l.bf _fail
|
l.nop
|
l.nop
|
|
|
CHECK_CY_SET
|
CHECK_CY_SET
|
|
|
_finish:
|
_finish:
|
l.movhi r3, hi(0x8000000d)
|
l.movhi r3, hi(0x8000000d)
|
l.ori r3, r3, lo(0x8000000d)
|
l.ori r3, r3, lo(0x8000000d)
|
l.nop 0x2
|
l.nop 0x2
|
l.ori r3, r0, 0
|
l.ori r3, r0, 0
|
l.nop 0x1
|
l.nop 0x1
|
|
|
_fail:
|
_fail:
|
l.ori r3, r0, 1
|
l.ori r3, r0, 1
|
l.nop 0x1
|
l.nop 0x1
|
|
|