1
0
mirror of https://github.com/DoctorWkt/unix-jun72.git synced 2026-02-10 10:20:36 +00:00
Files
DoctorWkt.unix-jun72/tools/apout/branch.c
2008-05-06 23:25:22 +00:00

388 lines
6.9 KiB
C

/* branch.c - Branch instructions, and instructions which are complex to do
*
* $Revision: 2.22 $
* $Date: 1999/12/27 04:38:29 $
*/
#include "defines.h"
/* We use the following macro for the branch instructions below */
#define do_branch() \
{ offset = LOW8(ir); \
if (offset & SIGN_B) \
offset += 0177400; \
regs[PC] += (offset * 2); \
} \
static u_int16_t offset;
void bne() {
if (CC_Z==0) do_branch();
}
void beq() {
if (CC_Z==1) do_branch();
}
void bpl() {
if (CC_N==0) do_branch();
}
void bmi() {
if (CC_N==1) do_branch();
}
void bhi() {
if ((CC_Z==0) && (CC_C==0)) do_branch();
}
void bvc() {
if (CC_V==0) do_branch();
}
void bvs() {
if (CC_V==1) do_branch();
}
void bcc() {
if (CC_C==0) do_branch();
}
void bcs() {
if (CC_C==1) do_branch();
}
/* br() - Branch Always. */
void br() {
do_branch();
}
/* blos() - Branch Lower or Same Instruction. */
void blos() {
if ((CC_C!=0) || (CC_Z!=0)) do_branch();
}
/* bge() - Branch Greater Than or Equal Instruction. */
void bge() {
if ((CC_N ^ CC_V) == 0) do_branch();
}
/* blt() - Branch Less Than Instruction. */
void blt() {
if ((CC_N ^ CC_V) == 1) do_branch();
}
/* ble() - Branch Less Than Or Equal Instruction. */
void ble() {
if (((CC_N ^ CC_V) == 1) || ((CC_Z)!=0)) do_branch();
}
/* bgt() - Branch Greater Than Instruction. */
void bgt() {
if (((CC_N ^ CC_V) == 0) && ((CC_Z) == 0)) do_branch();
}
/* jmp() - Jump Instruction. */
void jmp() {
load_ea(); regs[PC]=dstword;
}
/* jsr() - Jump To Subroutine Instruction. */
void jsr() {
load_ea();
srcword=regs[SRC_REG]; push();
regs[SRC_REG] = regs[PC];
regs[PC] = dstword;
JsrDebug((dbg_file, "jsr to 0%o\n", dstword));
}
/* rts() - Return From Subroutine Instruction. */
void rts() {
regs[PC] = regs[DST_REG];
pop(); regs[DST_REG] = dstword;
JsrDebug((dbg_file, "rts to 0%o\n", regs[PC]));
}
void scc() {
if (ir & CC_NBIT) CC_N=1;
if (ir & CC_ZBIT) CC_Z=1;
if (ir & CC_VBIT) CC_V=1;
if (ir & CC_CBIT) CC_C=1;
}
void ccc() {
if (ir & CC_NBIT) CC_N=0;
if (ir & CC_ZBIT) CC_Z=0;
if (ir & CC_VBIT) CC_V=0;
if (ir & CC_CBIT) CC_C=0;
}
/* sob() - Subtract One and Branch Instruction. */
void sob() {
regs[SRC_REG] -= 1;
if (regs[SRC_REG]) {
regs[PC] -= (ir & 077) * 2;
}
}
/* mfps() - Move from Processor Status Instruction. */
void mfps() {
srcbyte=(u_int8_t)0;
if (CC_N) srcbyte|= CC_NBIT;
if (CC_Z) srcbyte|= CC_ZBIT;
if (CC_V) srcbyte|= CC_VBIT;
if (CC_C) srcbyte|= CC_CBIT;
CHGB_CC_N(srcbyte);
CHGB_CC_Z(srcbyte);
CLR_CC_V();
if (DST_MODE) {
storeb_dst();
} else {
if (srcbyte & SIGN_B) {
dstword = 0177400;
} else {
dstword = 0;
}
dstword += (u_int16_t)srcbyte;
store_dst();
}
}
/* mtps() - Move to Processor Status Instruction. */
void mtps() {
loadb_dst();
if (dstbyte & CC_NBIT) CC_N=1;
if (dstbyte & CC_ZBIT) CC_Z=1;
if (dstbyte & CC_VBIT) CC_V=1;
if (dstbyte & CC_CBIT) CC_C=1;
}
/* mfpi() - Move From Previous Instruction Space Instruction. */
void mfpi() {
loadp_dst(); push();
}
/* mtpi() - To From Previous Instruction Space Instruction. */
void mtpi() {
pop(); storep_dst();
}
/* ash() - Arithmetic Shift Instruction. */
void ash() {
u_int16_t temp;
u_int16_t old;
u_int16_t sign;
u_int16_t count;
temp = regs[SRC_REG];
load_dst();
old = temp;
if ((dstword & 077) == 0) { /* no shift */
CHG_CC_N(temp);
CHG_CC_Z(temp);
CLR_CC_V();
return;
}
if (dstword & 040) { /* right shift */
count = 0100 - (dstword & 077);
sign = temp & SIGN;
while (count--) {
if (temp & LSBIT) {
SET_CC_C();
} else {
CLR_CC_C();
}
temp >>= 1;
temp += sign;
}
} else { /* left shift */
count = dstword & 037;
while (count--) {
if (temp & SIGN) {
SET_CC_C();
} else {
CLR_CC_C();
}
temp <<= 1;
}
}
CHG_CC_N(temp);
CHG_CC_Z(temp);
if ((old & SIGN) == (temp & SIGN)) {
CLR_CC_V();
} else {
SET_CC_V();
}
regs[SRC_REG] = temp;
}
/* mul() and divide() - Multiply and Divide Instructions. These work on
* signed values, and we'll do the same. This may not be portable. */
union s_u_word {
u_int16_t u_word;
short s_word;
};
union s_u_long {
u_int32_t u_long;
long s_long;
};
void mul() {
union s_u_word data1;
union s_u_word data2;
union s_u_long tmp;
data1.u_word = regs[SRC_REG];
load_dst();
data2.u_word=dstword;
tmp.s_long = ((long) data1.s_word) * ((long) data2.s_word);
regs[SRC_REG] = (u_int16_t)(tmp.u_long >> 16);
regs[(SRC_REG) | 1] = (u_int16_t)(tmp.u_long & 0177777);
CLR_CC_ALL();
if (tmp.u_long == 0)
SET_CC_Z();
else
CLR_CC_Z();
if (tmp.u_long & 0x80000000)
SET_CC_N();
else
CLR_CC_N();
}
void divide() {
union s_u_long tmp;
union s_u_long eql;
union s_u_word data2;
tmp.u_long = regs[SRC_REG];
tmp.u_long = tmp.u_long << 16;
tmp.u_long += regs[(SRC_REG) | 1];
load_dst();
data2.u_word=dstword;
if (data2.u_word == 0) {
SET_CC_C();
SET_CC_V();
return;
} else {
CLR_CC_C();
}
eql.s_long = tmp.s_long / data2.s_word;
regs[SRC_REG] = (u_int16_t)eql.u_long & 0177777;
if (eql.u_long == 0)
SET_CC_Z();
else
CLR_CC_Z();
if ((eql.s_long > 077777) || (eql.s_long < -0100000))
SET_CC_V();
else
CLR_CC_V();
if (eql.s_long < 0)
SET_CC_N();
else
CLR_CC_N();
eql.s_long = tmp.s_long % data2.s_word;
regs[(SRC_REG) | 1] = (u_int16_t)eql.u_long & 0177777;
}
/* ashc() - Arithmetic Shift Combined Instruction. */
void ashc() {
u_int32_t temp;
u_int32_t old;
u_int32_t sign;
u_int16_t count;
temp = regs[SRC_REG];
temp <<= 16;
temp += regs[(SRC_REG) | 1];
old = temp;
load_dst();
if ((dstword & 077) == 0) { /* no shift */
CLR_CC_V();
if (temp & 0x80000000) {
SET_CC_N();
} else {
CLR_CC_N();
}
if (temp) {
CLR_CC_Z();
} else {
SET_CC_Z();
}
return;
}
if (dstword & 040) { /* right shift */
count = 0100 - (dstword & 077);
sign = temp & 0x80000000;
while (count--) {
if (temp & LSBIT) {
SET_CC_C();
} else {
CLR_CC_C();
}
temp >>= 1;
temp += sign;
}
} else { /* left shift */
count = dstword & 037;
while (count--) {
if (temp & 0x80000000) {
SET_CC_C();
} else {
CLR_CC_C();
}
temp <<= 1;
}
}
if (temp & 0x80000000)
SET_CC_N();
else
CLR_CC_N();
if (temp)
CLR_CC_Z();
else
SET_CC_Z();
if ((old & 0x80000000) == (temp & 0x80000000)) {
CLR_CC_V();
} else {
SET_CC_V();
}
regs[SRC_REG] = (u_int16_t)(temp >> 16);
regs[(SRC_REG) | 1] = LOW16(temp);
}
/* xor() - Exclusive Or Instruction */
void xor() {
tmpword = regs[SRC_REG];
load_dst();
tmpword = tmpword ^ dstword;
CHG_CC_N(tmpword);
CHG_CC_Z(tmpword);
CLR_CC_V();
dstword=tmpword; store_dst_2();
}