xref: /inferno-os/os/mpc/powerbreak.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"../port/error.h"
7 #include	"ureg.h"
8 
9 extern int (*breakhandler)(Ureg *ur, Proc*);	/* trap.c */
10 extern Instr BREAK;	/* trap.c */
11 extern void portbreakinit(void);
12 
13 #define getop(i) ((i>>26)&0x3F)
14 #define getxo(i) ((i>>1)&0x3FF)
15 #define getbobi(i)	bo = (i>>21)&0x1f; bi = (i>>16)&0x1f; xx = (i>>11)&0x1f;
16 
17 void
machbreakinit(void)18 machbreakinit(void)
19 {
20 	portbreakinit();
21 	breakhandler = breakhit;
22 }
23 
24 Instr
machinstr(ulong addr)25 machinstr(ulong addr)
26 {
27 	if (addr < KTZERO)
28 		error(Ebadarg);
29 	return *(Instr*)addr;
30 }
31 
32 void
machbreakset(ulong addr)33 machbreakset(ulong addr)
34 {
35 	if (addr < KTZERO)
36 		error(Ebadarg);
37 	*(Instr*)addr = BREAK;
38 	segflush((void*)addr, sizeof(Instr));
39 }
40 
41 void
machbreakclear(ulong addr,Instr i)42 machbreakclear(ulong addr, Instr i)
43 {
44 	if (addr < KTZERO)
45 		error(Ebadarg);
46 	*(Instr*)addr = i;
47 	segflush((void*)addr, sizeof(Instr));
48 }
49 
50 static int
condok(Ureg * ur,ulong ir,int ctrok)51 condok(Ureg *ur, ulong ir, int ctrok)
52 {
53 	int bo, bi, xx;
54 	ulong ctrval;
55 
56 	ctrval = ur->ctr;
57 	getbobi(ir);
58 	if(xx)
59 		return 0;	/* illegal */
60 	if((bo & 0x4) == 0) {
61 		if(!ctrok)
62 			return 0;	/* illegal */
63 		ctrval--;
64 	}
65 	if(bo & 0x4 || (ctrval!=0)^((bo>>1)&1)) {
66 		if(bo & 0x10 || (((ur->cr & (1L<<(31-bi))!=0)==((bo>>3)&1))))
67 			return 1;
68 	}
69 	return 0;
70 }
71 
72 /*
73  * Return the address of the instruction that will be executed after the
74  * instruction at ur->pc, accounting for current branch conditions.
75  */
76 ulong
machnextaddr(Ureg * ur)77 machnextaddr(Ureg *ur)
78 {
79 	long imm;
80 	ulong ir;
81 
82 	ir = *(ulong*)ur->pc;
83 	switch(getop(ir)) {
84 	case 18:	/* branch */
85 		imm = ir & 0x03FFFFFC;
86 		if(ir & 0x02000000)
87 			imm |= 0xFC000000;	/* sign extended */
88 		if((ir & 2) == 0)	/* relative address */
89 			return ur->pc + imm;
90 		return imm;
91 
92 	case 16:	/* conditional branch */
93 		if(condok(ur, ir&0xFFFF0000, 1)){
94 			imm = ir & 0xFFFC;
95 			if(ir & 0x08000)
96 				imm |= 0xFFFF0000;	/* sign extended */
97 			if((ir & 2) == 0)	/* relative address */
98 				return ur->pc + imm;
99 			return imm;
100 		}
101 		break;
102 
103 	case 19:	/* conditional branch to register */
104 		switch(getxo(ir)){
105 		case 528:	/* bcctr */
106 			if(condok(ur, ir, 0))
107 				return ur->ctr & ~3;
108 			break;
109 		case 16:	/* bclr */
110 			if(condok(ur, ir, 1))
111 				return ur->lr & ~3;
112 			break;
113 		}
114 		break;
115 	}
116 	return ur->pc+4;	/* next instruction */
117 }
118 
119 int
isvalid_va(void * v)120 isvalid_va(void *v)
121 {
122 	return (ulong)v >= KTZERO;
123 }
124