ref: eff99e9be0f63c0cc54146e21af5bd423238c226
parent: 8d93ccdbb2a2dee8d2eb1387da1b316fdf84b208
author: halfwit <michaelmisch1985@gmail.com>
date: Sat Jul 19 12:54:05 EDT 2025
updates to embedded 5e
--- a/include/proc.h
+++ b/include/proc.h
@@ -1,2 +1,4 @@
extern void step(void);
int loadtext(char *, int, char **);
+void inittos(void);
+void resetvfp(void);
\ No newline at end of file
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -23,6 +23,7 @@
devtab.$O\
dirread.$O\
error.$O\
+ fpa.$O\
getwd.$O\
memchr.$O\
parse.$O\
@@ -44,6 +45,7 @@
qlock.$O\
wait.$O\
waserror.$O\
+ vfp.$O\
$(OS).$O
default: $(LIB)
--- a/kern/arm.c
+++ b/kern/arm.c
@@ -20,72 +20,73 @@
void
invalid(u32int instr)
{- fprint(2, "undefined instruction %8ux @ %8ux", instr, up->R[15] - 4);
+ panic("undefined instruction %.8ux @ %.8ux\n", instr, up->R[15] - 4);}
u32int
evenaddr(u32int addr, u32int mask)
{- if((addr & mask) == 0)
- return addr;
- return addr & ~mask;
+ if((addr & mask) == 0)
+ return addr;
+ panic("unaligned access %8ux @ %8ux", addr, up->R[15] - 4);+ return addr & ~mask;
}
static u32int
-doshift(u32int instr, uint *carry)
+doshift(u32int instr, uchar *carry)
{- ulong amount, val;
-
- val = up->R[instr & 15];
- if(instr & (1<<4)) {- if(instr & (1<<7))
- invalid(instr);
- amount = up->R[(instr >> 8) & 15] & 0xFF;
- if(amount == 0)
- return val;
- } else {- amount = (instr >> 7) & 31;
- if(amount == 0 && (instr & (3<<5)) != 0)
- amount = 32;
- }
- switch((instr >> 5) & 3) {- default:
- if(amount == 0)
- return val;
- if(amount < 32) {- *carry = (val >> (32 - amount)) & 1;
- return val << amount;
- }
- *carry = val & 1;
- return 0;
- case 1:
- if(amount < 32){- *carry = (val >> (amount - 1)) & 1;
- return val >> amount;
- }
- *carry = val >> 31;
- return 0;
- case 2:
- if(amount < 32){- *carry = (val >> (amount - 1)) & 1;
- return ((long) val) >> amount;
- }
- if((long)val < 0){- *carry = 1;
- return -1;
- }
- *carry = 0;
- return 0;
- case 3:
- amount &= 31;
- if(amount){- *carry = (val >> (amount - 1)) & 1;
- return (val >> amount) | (val << (32 - amount));
- }
- amount = *carry & 1;
- *carry = val & 1;
- return (val>>1) | (amount<<31);
- }
+ ulong amount, val;
+print("doshift\n");+ val = up->R[instr & 15];
+ if(instr & (1<<4)) {+ if(instr & (1<<7))
+ invalid(instr);
+ amount = up->R[(instr >> 8) & 15] & 0xFF;
+ if(amount == 0)
+ return val;
+ } else {+ amount = (instr >> 7) & 31;
+ if(amount == 0 && (instr & (3<<5)) != 0)
+ amount = 32;
+ }
+ switch((instr >> 5) & 3) {+ default:
+ if(amount == 0)
+ return val;
+ if(amount < 32) {+ *carry = (val >> (32 - amount)) & 1;
+ return val << amount;
+ }
+ *carry = val & 1;
+ return 0;
+ case 1:
+ if(amount < 32){+ *carry = (val >> (amount - 1)) & 1;
+ return val >> amount;
+ }
+ *carry = val >> 31;
+ return 0;
+ case 2:
+ if(amount < 32){+ *carry = (val >> (amount - 1)) & 1;
+ return ((long) val) >> amount;
+ }
+ if((long)val < 0){+ *carry = 1;
+ return -1;
+ }
+ *carry = 0;
+ return 0;
+ case 3:
+ amount &= 31;
+ if(amount){+ *carry = (val >> (amount - 1)) & 1;
+ return (val >> amount) | (val << (32 - amount));
+ }
+ amount = *carry & 1;
+ *carry = val & 1;
+ return (val>>1) | (amount<<31);
+ }
}
static void
@@ -96,9 +97,10 @@
u32int *Rn, *Rd;
void *targ;
Segment *seg;
-
+print("single\n");+
if(instr & fI) {- uint carry = 0;
+ uchar carry = 0;
if(instr & (1<<4))
invalid(instr);
offset = doshift(instr, &carry);
@@ -108,6 +110,7 @@
offset = - offset;
Rn = up->R + ((instr >> 16) & 15);
Rd = up->R + ((instr >> 12) & 15);
+
if((instr & (fW | fP)) == fW)
invalid(instr);
if(Rn == up->R + 15) {@@ -114,8 +117,7 @@
if(instr & fW)
invalid(instr);
addr = up->R[15] + 4;
- }
- else
+ } else
addr = *Rn;
if(instr & fP)
addr += offset;
@@ -127,18 +129,18 @@
*(u32int*) targ = *Rd;
break;
case fB:
- *(uint*) targ = *Rd;
+ *(uchar*) targ = *Rd;
break;
case fL:
*Rd = *(u32int*) targ;
break;
case fB | fL:
- *Rd = *(uint*) targ;
+ *Rd = *(uchar*) targ;
break;
}
if(Rd == up->R + 15 && !(instr & fL)) {if(instr & fB)
- *(uint*) targ += 8;
+ *(uchar*) targ += 8;
else
*(u32int*) targ += 8;
}
@@ -152,67 +154,67 @@
static void
swap(u32int instr)
{- u32int *Rm, *Rn, *Rd, *targ, addr, old, new;
- Segment *seg;
-
- Rm = up->R + (instr & 15);
- Rd = up->R + ((instr >> 12) & 15);
- Rn = up->R + ((instr >> 16) & 15);
- if(Rm == up->R + 15 || Rd == up->R + 15 || Rn == up->R + 15)
- invalid(instr);
- addr = *Rn;
- if((instr & fB) == 0)
- addr = evenaddr(addr, 3);
- targ = (u32int *) vaddr(addr & ~3, 4, &seg);
- do {- old = *targ;
- new = *Rm;
- if(instr & fB){- new &= 0xFF;
- new <<= 8*(addr&3);
- new |= old & ~(0xFF << 8*(addr&3));
- }
- } while(!cas((int*)targ, old, new));
- if(instr & fB) {- old >>= 8*(addr&3);
- old &= 0xFF;
- }
- *Rd = old;
- segunlock(seg);
+ u32int *Rm, *Rn, *Rd, *targ, addr, old, new;
+ Segment *seg;
+print("swap\n");+ Rm = up->R + (instr & 15);
+ Rd = up->R + ((instr >> 12) & 15);
+ Rn = up->R + ((instr >> 16) & 15);
+ if(Rm == up->R + 15 || Rd == up->R + 15 || Rn == up->R + 15)
+ invalid(instr);
+ addr = *Rn;
+ if((instr & fB) == 0)
+ addr = evenaddr(addr, 3);
+ targ = (u32int *) vaddr(addr & ~3, 4, &seg);
+ do {+ old = *targ;
+ new = *Rm;
+ if(instr & fB){+ new &= 0xFF;
+ new <<= 8*(addr&3);
+ new |= old & ~(0xFF << 8*(addr&3));
+ }
+ } while(!cas((int*)targ, old, new));
+ if(instr & fB) {+ old >>= 8*(addr&3);
+ old &= 0xFF;
+ }
+ *Rd = old;
+ segunlock(seg);
}
static u32int
-add(u32int a, u32int b, uint type, uint *carry, uint *overflow)
+add(u32int a, u32int b, uchar type, uchar *carry, uchar *overflow)
{- u32int res1;
- u64int res2;
-
- if(type) {- res2 = (u64int)a - b + *carry - 1;
- res1 = res2;
- if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
- else *overflow = 0;
- if(res2 & 0x100000000LL) *carry = 0;
- else *carry = 1;
- } else {- res2 = (u64int)a + b + *carry;
- res1 = res2;
- if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
- else *overflow = 0;
- if(res2 & 0x100000000LL) *carry = 1;
- else *carry = 0;
- }
- return res1;
+ u32int res1;
+ u64int res2;
+print("add\n");+ if(type) {+ res2 = (u64int)a - b + *carry - 1;
+ res1 = res2;
+ if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
+ else *overflow = 0;
+ if(res2 & 0x100000000LL) *carry = 0;
+ else *carry = 1;
+ } else {+ res2 = (u64int)a + b + *carry;
+ res1 = res2;
+ if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
+ else *overflow = 0;
+ if(res2 & 0x100000000LL) *carry = 1;
+ else *carry = 0;
+ }
+ return res1;
}
static void
alu(u32int instr)
{- u32int Rn, *Rd, operand, shift, result, op;
- uint carry, overflow;
-
- Rn = up->R[(instr >> 16) & 15];
- Rd = up->R + ((instr >> 12) & 15);
+ u32int Rn, *Rd, operand, shift, result, op;
+ uchar carry, overflow;
+ Rn = up->R[(instr >> 16) & 15];
+ Rd = up->R + ((instr >> 12) & 15);
+print("alu\n"); if(((instr >> 16) & 15) == 15) {Rn += 4;
if(!(instr & fI) && (instr & (1<<4)))
@@ -235,10 +237,8 @@
operand = doshift(instr, &carry);
op = (instr >> 21) & 15;
- if(op >= 8 && op <= 11 && !(instr & fS)){- fprint(2, "no PSR transfers plz");
- return;
- }
+ if(op >= 8 && op <= 11 && !(instr & fS))
+ sysfatal("no PSR transfers plz");if(op >= 5 && op < 8)
carry = (up->CPSR & flC) != 0;
switch(op) {@@ -271,310 +271,287 @@
static void
branch(u32int instr)
{- long offset;
-
- offset = instr & ((1<<24) - 1);
- if(offset & (1<<23))
- offset |= ~((1 << 24) - 1);
- offset *= 4;
- if(instr & fLi)
- up->R[14] = up->R[15];
- up->R[15] += offset + 4;
+ long offset;
+print("branch\n"); + offset = instr & ((1<<24) - 1);
+ if(offset & (1<<23))
+ offset |= ~((1 << 24) - 1);
+ offset *= 4;
+ if(instr & fLi)
+ up->R[14] = up->R[15];
+ up->R[15] += offset + 4;
}
static void
halfword(u32int instr)
{- u32int offset, target, *Rn, *Rd;
- Segment *seg;
-
- if(instr & (1<<22)) {- offset = (instr & 15) | ((instr >> 4) & 0xF0);
- } else {- if((instr & 15) == 15)
- invalid(instr);
- offset = up->R[instr & 15];
- }
- if(!(instr & fU))
- offset = - offset;
- if(!(instr & fP) && (instr & fW))
- invalid(instr);
- Rn = up->R + ((instr >> 16) & 15);
- Rd = up->R + ((instr >> 12) & 15);
- if(Rn == up->R + 15 || Rd == up->R + 15)
- fprint(2, "R15 in halfword");
- target = *Rn;
- if(instr & fP)
- target += offset;
- if(instr & fH)
- target = evenaddr(target, 1);
- switch(instr & (fSg | fH | fL)) {- case fSg: *(uint*) vaddr(target, 1, &seg) = *Rd; break;
- case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
- case fH: case fSg | fH: *(uint16_t*) vaddr(target, 2, &seg) = *Rd; break;
- case fH | fL: *Rd = *(uint16_t*) vaddr(target, 2, &seg); break;
- case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
- }
- segunlock(seg);
- if(!(instr & fP))
- target += offset;
- if(!(instr & fP) || (instr & fW))
- *Rn = target;
+ u32int offset, target, *Rn, *Rd;
+ Segment *seg;
+print("halfword\n"); + if(instr & (1<<22)) {+ offset = (instr & 15) | ((instr >> 4) & 0xF0);
+ } else {+ if((instr & 15) == 15)
+ invalid(instr);
+ offset = up->R[instr & 15];
+ }
+ if(!(instr & fU))
+ offset = - offset;
+ if(!(instr & fP) && (instr & fW))
+ invalid(instr);
+ Rn = up->R + ((instr >> 16) & 15);
+ Rd = up->R + ((instr >> 12) & 15);
+ target = *Rn;
+ if(instr & fP)
+ target += offset;
+ if(instr & fH)
+ target = evenaddr(target, 1);
+ switch(instr & (fSg | fH | fL)) {+ case fSg: *(uchar*) vaddr(target, 1, &seg) = *Rd; break;
+ case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
+ case fH: case fSg | fH: *(uint16_t*) vaddr(target, 2, &seg) = *Rd; break;
+ case fH | fL: *Rd = *(uint16_t*) vaddr(target, 2, &seg); break;
+ case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
+ }
+ segunlock(seg);
+ if(!(instr & fP))
+ target += offset;
+ if(!(instr & fP) || (instr & fW))
+ *Rn = target;
}
static void
block(u32int instr)
{- int i;
- u32int targ, *Rn;
- Segment *seg;
+ int i;
+ u32int targ, *Rn;
+ Segment *seg;
- print("Checking invalid\n");- if(instr & (1<<22))
- invalid(instr);
-
- Rn = up->R +((instr >> 16) & 15);
- if(Rn == up->R + 15 || instr & (1<<15))
- print("R15 in block");- targ = evenaddr(*Rn, 3);
- if(instr & fU) {- for(i = 0; i < 16; i++) {- if(!(instr & (1<<i)))
- continue;
- if(instr & fP)
- targ += 4;
- if(instr & fL)
- up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
- else
- *(u32int*) vaddr(targ, 4, &seg) = up->R[i];
- segunlock(seg);
- if(!(instr & fP))
- targ += 4;
- }
- } else {- for(i = 15; i >= 0; i--) {- if(!(instr & (1<<i)))
- continue;
- if(instr & fP)
- targ -= 4;
- if(instr & fL)
- up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
- else
- *(u32int*) vaddr(targ, 4, &seg) = up->R[i];
- segunlock(seg);
- if(!(instr & fP))
- targ -= 4;
- }
- }
- if(instr & fW)
- *Rn = targ;
- print("Farnished\n");+ if(instr & (1<<22))
+ invalid(instr);
+print("block\n"); + Rn = up->R +((instr >> 16) & 15);
+ targ = evenaddr(*Rn, 3);
+ if(instr & fU) {+ for(i = 0; i < 16; i++) {+ if(!(instr & (1<<i)))
+ continue;
+print("%d\n", i);+ if(instr & fP)
+ targ += 4;
+ if(instr & fL)
+ up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+ else
+ *(u32int*) vaddr(targ, 4, &seg) = up->R[i];
+ segunlock(seg);
+ if(!(instr & fP))
+ targ += 4;
+ }
+ } else {+ for(i = 15; i >= 0; i--) {+ if(!(instr & (1<<i)))
+ continue;
+ if(instr & fP)
+ targ -= 4;
+ if(instr & fL)
+ up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+ else
+ *(u32int*) vaddr(targ, 4, &seg) = up->R[i];
+ segunlock(seg);
+ if(!(instr & fP))
+ targ -= 4;
+ }
+ }
+ if(instr & fW)
+ *Rn = targ;
}
static void
multiply(u32int instr)
{- u32int *Rd, *Rn, *Rs, *Rm, res;
-
- Rm = up->R + (instr & 15);
- Rs = up->R + ((instr >> 8) & 15);
- Rn = up->R + ((instr >> 12) & 15);
- Rd = up->R + ((instr >> 16) & 15);
- if(Rd == Rm || Rm == up->R + 15 || Rs == up->R + 15 || Rn == up->R + 15 || Rd == up->R + 15)
- invalid(instr);
- res = *Rm * *Rs;
- if(instr & (1<<21))
- res += *Rn;
- *Rd = res;
- if(instr & (1<<20)) {- up->CPSR &= ~(flN | flZ);
- if(res & (1<<31))
- up->CPSR |= flN;
- if(res == 0)
- up->CPSR |= flZ;
- }
+ u32int *Rd, *Rn, *Rs, *Rm, res;
+print("multiply\n");+ Rm = up->R + (instr & 15);
+ Rs = up->R + ((instr >> 8) & 15);
+ Rn = up->R + ((instr >> 12) & 15);
+ Rd = up->R + ((instr >> 16) & 15);
+ if(Rd == Rm || Rm == up->R + 15 || Rs == up->R + 15 || Rn == up->R + 15 || Rd == up->R + 15)
+ invalid(instr);
+ res = *Rm * *Rs;
+ if(instr & (1<<21))
+ res += *Rn;
+ *Rd = res;
+ if(instr & (1<<20)) {+ up->CPSR &= ~(flN | flZ);
+ if(res & (1<<31))
+ up->CPSR |= flN;
+ if(res == 0)
+ up->CPSR |= flZ;
+ }
}
static void
multiplylong(u32int instr)
{- u32int *RdH, *RdL, *Rs, *Rm;
- u64int res;
-
- Rm = up->R + (instr & 15);
- Rs = up->R + ((instr >> 8) & 15);
- RdL = up->R + ((instr >> 12) & 15);
- RdH = up->R + ((instr >> 16) & 15);
- if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == up->R + 15 || Rs == up->R + 15 || RdL == up->R + 15 || RdH == up->R + 15)
- invalid(instr);
- if(instr & (1<<22))
- res = ((vlong)*(int*)Rs) * *(int*)Rm;
- else {- res = *Rs;
- res *= *Rm;
- }
- if(instr & (1<<21)) {- res += *RdL;
- res += ((uvlong)*RdH) << 32;
- }
- *RdL = res;
- *RdH = res >> 32;
- if(instr & (1<<20)) {- up->CPSR &= ~FLAGS;
- if(res == 0)
- up->CPSR |= flN;
- if(res & (1LL<<63))
- up->CPSR |= flV;
- }
+ u32int *RdH, *RdL, *Rs, *Rm;
+ u64int res;
+print("multiplylong\n");+ Rm = up->R + (instr & 15);
+ Rs = up->R + ((instr >> 8) & 15);
+ RdL = up->R + ((instr >> 12) & 15);
+ RdH = up->R + ((instr >> 16) & 15);
+ if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == up->R + 15 || Rs == up->R + 15 || RdL == up->R + 15 || RdH == up->R + 15)
+ invalid(instr);
+ if(instr & (1<<22))
+ res = ((vlong)*(int*)Rs) * *(int*)Rm;
+ else {+ res = *Rs;
+ res *= *Rm;
+ }
+ if(instr & (1<<21)) {+ res += *RdL;
+ res += ((uvlong)*RdH) << 32;
+ }
+ *RdL = res;
+ *RdH = res >> 32;
+ if(instr & (1<<20)) {+ up->CPSR &= ~FLAGS;
+ if(res == 0)
+ up->CPSR |= flN;
+ if(res & (1LL<<63))
+ up->CPSR |= flV;
+ }
}
static void
singleex(u32int instr)
{- u32int *Rn, *Rd, *Rm, *targ, addr;
- Segment *seg;
-
- Rd = up->R + ((instr >> 12) & 15);
- Rn = up->R + ((instr >> 16) & 15);
- if(Rd == up->R + 15 || Rn == up->R + 15)
- invalid(instr);
- addr = evenaddr(*Rn, 3);
- if(instr & fS) {- targ = vaddr(addr, 4, &seg);
- *Rd = *targ;
- up->lladdr = addr;
- up->llval = *Rd;
- segunlock(seg);
- } else {- Rm = up->R + (instr & 15);
- if(Rm == up->R + 15)
- invalid(instr);
- targ = vaddr(addr, 4, &seg);
-
- /*
- * this is not quite correct as we will succeed even
- * if the value was modified and then restored to its
- * original value but good enough approximation for
- * libc's _tas(), _cas() and _xinc()/_xdec().
- */
- *Rd = addr != up->lladdr || !cas((int*)targ, up->llval, *Rm);
- segunlock(seg);
- clrex();
- }
+ u32int *Rn, *Rd, *Rm, *targ, addr;
+ Segment *seg;
+print("singleex\n");+ Rd = up->R + ((instr >> 12) & 15);
+ Rn = up->R + ((instr >> 16) & 15);
+ if(Rd == up->R + 15 || Rn == up->R + 15)
+ invalid(instr);
+ addr = evenaddr(*Rn, 3);
+ if(instr & fS) {+ targ = vaddr(addr, 4, &seg);
+ *Rd = *targ;
+ up->lladdr = addr;
+ up->llval = *Rd;
+ segunlock(seg);
+ } else {+ Rm = up->R + (instr & 15);
+ if(Rm == up->R + 15)
+ invalid(instr);
+ targ = vaddr(addr, 4, &seg);
+ *Rd = addr != up->lladdr || !cas((int*)targ, up->llval, *Rm);
+ segunlock(seg);
+ clrex();
+ }
}
void
clrex(void)
{- up->lladdr = 0;
- up->llval = 0;
+print("clrex\n");+ up->lladdr = 0;
+ up->llval = 0;
}
static void
barrier(void)
{- static Lock l;
-
- lock(&l);
- unlock(&l);
+print("barrier\n");+ static Lock l;
+ lock(&l);
+ unlock(&l);
}
-int
+void
step(void)
{- u32int instr;
- Segment *seg;
-print("Grabbing instruction\n");- instr = *(u32int*) vaddr(up->R[15], 4, &seg);
-print("Grabbed instruction\n");- segunlock(seg);
+ u32int instr;
+ Segment *seg;
- up->R[15] += 4;
+ if (!up->S[SEGTEXT] || up->R[15] < up->S[SEGTEXT]->start || up->R[15] >= up->S[SEGTEXT]->start + up->S[SEGTEXT]->size) {+ panic("step: invalid PC=%.8ux outside text segment [%.8ux, %.8ux)\n",+ up->R[15],
+ up->S[SEGTEXT] ? up->S[SEGTEXT]->start : 0,
+ up->S[SEGTEXT] ? up->S[SEGTEXT]->start + up->S[SEGTEXT]->size : 0);
+ return;
+ }
+
+ void *targ = vaddr(up->R[15], 4, &seg);
+ instr = *(u32int*)targ;
+ segunlock(seg);
+
+ up->R[15] += 4;
+
switch(instr >> 28) {- case 0x0: if(!(up->CPSR & flZ)) return 1; break;
- case 0x1: if(up->CPSR & flZ) return 1; break;
- case 0x2: if(!(up->CPSR & flC)) return 1; break;
- case 0x3: if(up->CPSR & flC) return 1; break;
- case 0x4: if(!(up->CPSR & flN)) return 1; break;
- case 0x5: if(up->CPSR & flN) return 1; break;
- case 0x6: if(!(up->CPSR & flV)) return 1; break;
- case 0x7: if(up->CPSR & flV) return 1; break;
- case 0x8: if(!(up->CPSR & flC) || (up->CPSR & flZ)) return 1; break;
- case 0x9: if((up->CPSR & flC) && !(up->CPSR & flZ)) return 1; break;
- case 0xA: if(!(up->CPSR & flN) != !(up->CPSR & flV)) return 1; break;
- case 0xB: if(!(up->CPSR & flN) == !(up->CPSR & flV)) return 1; break;
- case 0xC: if((up->CPSR & flZ) || !(up->CPSR & flN) != !(up->CPSR & flV)) return 1; break;
- case 0xD: if(!(up->CPSR & flZ) && !(up->CPSR & flN) == !(up->CPSR & flV)) return 1; break;
+ case 0x0: if(!(up->CPSR & flZ)) return; break;
+ case 0x1: if(up->CPSR & flZ) return; break;
+ case 0x2: if(!(up->CPSR & flC)) return; break;
+ case 0x3: if(up->CPSR & flC) return; break;
+ case 0x4: if(!(up->CPSR & flN)) return; break;
+ case 0x5: if(up->CPSR & flN) return; break;
+ case 0x6: if(!(up->CPSR & flV)) return; break;
+ case 0x7: if(up->CPSR & flV) return; break;
+ case 0x8: if(!(up->CPSR & flC) || (up->CPSR & flZ)) return; break;
+ case 0x9: if((up->CPSR & flC) && !(up->CPSR & flZ)) return; break;
+ case 0xA: if(!(up->CPSR & flN) != !(up->CPSR & flV)) return; break;
+ case 0xB: if(!(up->CPSR & flN) == !(up->CPSR & flV)) return; break;
+ case 0xC: if((up->CPSR & flZ) || !(up->CPSR & flN) != !(up->CPSR & flV)) return; break;
+ case 0xD: if(!(up->CPSR & flZ) && !(up->CPSR & flN) == !(up->CPSR & flV)) return; break;
case 0xE: break;
case 0xF:
switch(instr & 0xFFF000F0){case 0xF5700010: /* CLREX */
- print("clrex\n");- //clrex();
- return 1;
+ clrex();
+ return;
case 0xF5700040: /* DSB */
case 0xF5700050: /* DMB */
case 0xF5700060: /* ISB */
- print("barrier\n");- //barrier();
- return 1;
+ barrier();
+ return;
}
default:
- fprint(2, "condition code %x not implemented (instr %ux, ps %ux)", instr >> 28, instr, up->R[15]);
- return 0;
+ sysfatal("condition code %x not implemented (instr %ux, ps %ux)", instr >> 28, instr, up->R[15]);}
- if((instr & 0x0FB00FF0) == 0x01000090)
- print("Swap\n");- //swap(instr);
- else if((instr & 0x0FE000F0) == 0x01800090)
- print("Singleex\n");- //singleex(instr);
- else if((instr & 0x0FC000F0) == 0x90)
- print("Multiply\n");- //multiply(instr);
- else if((instr & 0x0F8000F0) == 0x800090)
- print("Multiplylong\n");- //multiplylong(instr);
- else if((instr & ((1<<26) | (1<<27))) == (1 << 26))
- print("Single\n");- //single(instr);
- else if((instr & 0x0E000090) == 0x90 && (instr & 0x60))
- print("Halfword\n");- //halfword(instr);
- else if((instr & ((1<<26) | (1<<27))) == 0)
- print("Alu\n");- //alu(instr);
- else if((instr & (7<<25)) == (5 << 25))
- print("Branch\n");- //branch(instr);
- else if((instr & (15<<24)) == (15 << 24))
- print("Syscall\n");- //_syscall();
- else if((instr & (7<<25)) == (4 << 25))
- print("Block\n");- //block(instr);
- else if((instr & 0x0E000F00) == 0x0C000100)
- print("Fpatransfer\n");- //fpatransfer(instr);
- else if((instr & 0x0E000F10) == 0x0E000100)
- print("Fpaoperation\n");- //fpaoperation(instr);
- else if((instr & 0x0E000F10) == 0x0E000110)
- print("Fparegtransfer\n");- //fparegtransfer(instr);
- else if((instr & 0x0F000A10) == 0x0E000A00)
- print("Vfpoperation\n");- //vfpoperation(instr);
- else if((instr & 0x0F000F10) == 0x0E000A10)
- print("Vfpregtransfer\n");- //vfpregtransfer(instr);
- else if((instr & 0x0F000A00) == 0x0D000A00)
- print("Vfprmtransfer\n");- //vfprmtransfer(instr);
- else {- print("Invalid\n");- invalid(instr);
- return 0;
- }
- return 1;
+
+ if ((instr & 0x0FB00FF0) == 0x01000090)
+ swap(instr);
+ else if ((instr & 0x0FE000F0) == 0x01800090)
+ singleex(instr);
+ else if ((instr & 0x0FC000F0) == 0x90)
+ multiply(instr);
+ else if ((instr & 0x0F8000F0) == 0x800090)
+ multiplylong(instr);
+ else if ((instr & ((1<<26) | (1<<27))) == (1 << 26))
+ single(instr);
+ else if ((instr & 0x0E000090) == 0x90 && (instr & 0x60))
+ halfword(instr);
+ else if ((instr & ((1<<26) | (1<<27))) == 0)
+ alu(instr);
+ else if ((instr & (7<<25)) == (5 << 25))
+ branch(instr);
+ else if ((instr & (15<<24)) == (15 << 24))
+ _syscall();
+ else if ((instr & (7<<25)) == (4 << 25))
+ block(instr);
+ else if ((instr & 0x0E000F00) == 0x0C000100)
+ fpatransfer(instr);
+ else if ((instr & 0x0E000F10) == 0x0E000100)
+ fpaoperation(instr);
+ else if ((instr & 0x0E000F10) == 0x0E000110)
+ fparegtransfer(instr);
+ else if ((instr & 0x0F000A10) == 0x0E000A00)
+ vfpoperation(instr);
+ else if ((instr & 0x0F000F10) == 0x0E000A10)
+ vfpregtransfer(instr);
+ else if ((instr & 0x0F000A00) == 0x0D000A00)
+ vfprmtransfer(instr);
+ else {+ invalid(instr);
+ }
}
\ No newline at end of file
--- a/kern/dat.h
+++ b/kern/dat.h
@@ -120,7 +120,6 @@
};
enum {- STACKSIZE = 0x100000,
NAMEMAX = 27,
NSMAX = 1000,
NNOTE = 5,
@@ -376,6 +375,7 @@
Pgrp *pgrp; /* Process group for namespace */
Fgrp *fgrp; /* File descriptor group */
Rgrp *rgrp;
+ Egrp *egrp;
Lock rlock; /* sync sleep/wakeup with postnote */
Rendez *r; /* rendezvous point slept on */
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -1,5 +1,6 @@
//#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
+void addnote(char*);
Block* adjustblock(Block*, int);
Block* allocb(int);
int blocklen(Block*);
@@ -125,6 +126,7 @@
Mount* newmount(Chan*, int, char*);
Path* newpath(char*);
Pgrp* newpgrp(void);
+Egrp* newegrp(void);
Rgrp* newrgrp(void);
Proc* newproc(void);
char* nextelem(char*, char*);
@@ -219,7 +221,6 @@
int splhi(void);
int spllo(void);
void splx(int);
-int step(void);
void _syscall(void);
Block* trimblock(Block*, int, int);
long unionread(Chan*, void*, long);
--- /dev/null
+++ b/kern/fpa.c
@@ -1,0 +1,145 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+resetfpa(void)
+{+ int i;
+
+ up->FPSR = 0x81000000;
+ for(i = 0; i < 8; i++)
+ up->F[i] = 0;
+}
+
+void
+fpatransfer(u32int instr)
+{+ enum {+ fP = 1<<24,
+ fU = 1<<23,
+ fT1 = 1<<22,
+ fW = 1<<21,
+ fL = 1<<20,
+ fT0 = 1<<15,
+ };
+
+ double *Fd;
+ u32int *Rn, addr;
+ int off;
+ void *targ;
+ Segment *seg;
+
+ Rn = up->R + ((instr >> 16) & 15);
+ Fd = up->F + ((instr >> 12) & 7);
+ if(Rn == up->R + 15)
+ invalid(instr);
+ off = (instr & 255) * 4;
+ if(!(instr & fU))
+ off = -off;
+ addr = *Rn;
+ if(instr & fP)
+ addr += off;
+ targ = vaddr(addr, 8, &seg);
+ switch(instr & (fT0 | fT1 | fL)) {+ case 0: *(float *) targ = *Fd; break;
+ case fL: *Fd = *(float *) targ; break;
+ case fT0: *(double *) targ = *Fd; break;
+ case fT0 | fL: *Fd = *(double *) targ; break;
+ default: invalid(instr);
+ }
+ segunlock(seg);
+ if(!(instr & fP))
+ addr += off;
+ if(instr & fW)
+ *Rn = addr;
+}
+
+static double
+fpasecop(u32int instr)
+{+ switch(instr & 15) {+ case 8: return 0.0; break;
+ case 9: return 1.0; break;
+ case 10: return 2.0; break;
+ case 11: return 3.0; break;
+ case 12: return 4.0; break;
+ case 13: return 5.0; break;
+ case 14: return 0.5; break;
+ case 15: return 10.0; break;
+ }
+ return up->F[instr & 7];
+}
+
+void
+fpaoperation(u32int instr)
+{+ double *Fn, *Fd, op, op2, res;
+ int prec, opc;
+
+ Fn = up->F + ((instr >> 16) & 7);
+ Fd = up->F + ((instr >> 12) & 7);
+ op2 = fpasecop(instr);
+ op = *Fn;
+ prec = ((instr >> 7) & 1) | ((instr >> 18) & 2);
+ opc = ((instr >> 20) & 15) | ((instr >> 11) & 16);
+ switch(opc) {+ case 0: res = op + op2; break;
+ case 1: res = op * op2; break;
+ case 2: res = op - op2; break;
+ case 3: res = op2 - op; break;
+ case 4: res = op / op2; break;
+ case 5: res = op2 / op; break;
+ case 16: res = op2; break;
+ case 17: res = - op2; break;
+ case 18: res = fabs(op2); break;
+ case 19: res = (vlong) op2; break;
+ case 20: res = sqrt(op2); break;
+ default: sysfatal("unimplemented FPA operation %#x @ %8ux", opc, up->R[15] - 4);+ }
+ switch(prec) {+ case 0: *Fd = (float) res; break;
+ case 1: *Fd = (double) res; break;
+ case 2: *Fd = res; break;
+ default: invalid(instr);
+ }
+}
+
+void
+fparegtransfer(u32int instr)
+{+ u32int *Rd;
+ long tmp;
+ double *Fn, op, op2;
+
+ Rd = up->R + ((instr >> 12) & 15);
+ Fn = up->F + ((instr >> 16) & 7);
+ op = fpasecop(instr);
+ if(Rd == up->R + 15) {+ op2 = *Fn;
+ switch((instr >> 21) & 7) {+ case 4: break;
+ case 5: op = - op; break;
+ default: invalid(instr);
+ }
+ if(op2 < op)
+ up->CPSR = (up->CPSR & ~FLAGS) | flN;
+ else if(op2 >= op) {+ up->CPSR = (up->CPSR & ~FLAGS) | flC;
+ if(op2 == op)
+ up->CPSR |= flZ;
+ } else
+ up->CPSR = (up->CPSR & ~FLAGS) | flV;
+ return;
+ }
+ if(instr & (1<<3))
+ invalid(instr);
+ switch((instr >> 20) & 15) {+ case 0: *Fn = *(long *) Rd; break;
+ case 1: tmp = op; *Rd = tmp; break;
+ case 2: up->FPSR = *Rd; break;
+ case 3: *Rd = up->FPSR; break;
+ default: invalid(instr);
+ }
+}
\ No newline at end of file
--- a/kern/notify.c
+++ b/kern/notify.c
@@ -21,7 +21,7 @@
#include <u.h>
#include <signal.h>
-#include <libc.h>
+#include <lib.h>
extern char *_p9sigstr(int, char*);
extern int _p9strsig(char*);
--- a/kern/pgrp.c
+++ b/kern/pgrp.c
@@ -16,6 +16,15 @@
return p;
}
+Egrp*
+newegrp(void)
+{+ Egrp *e;
+ e = smalloc(sizeof(Egrp));
+ e->ref.ref = 1;
+ return e;
+}
+
Rgrp*
newrgrp(void)
{--- a/kern/seg.c
+++ b/kern/seg.c
@@ -3,17 +3,21 @@
#include "dat.h"
#include "fns.h"
-// TODO: Update to 64 bit
Segment *
newseg(u32int start, u32int size, int idx)
{Segment *s;
- s = mallocz(sizeof *s, 1);
+ s = malloc(sizeof *s);
+ if(s == nil)
+ panic("%r");+ memset(s, 0, sizeof *s);
incref(&s->ref);
s->start = start;
s->size = size;
s->dref = malloc(size + sizeof(Ref));
+ if(s->dref == nil)
+ panic("%r");memset(s->dref, 0, sizeof(Ref));
incref(s->dref);
s->data = s->dref + 1;
@@ -43,31 +47,30 @@
void *
vaddr(u32int addr, u32int len, Segment **seg)
{- Segment **ss, *s;
- for(ss = up->S; ss < up->S + SEGNUM; ss++) {- if(*ss == nil)
- continue;
- s = *ss;
- if(addr >= s->start && addr < s->start + s->size) {- if(addr + len > s->start + s->size)
- break;
- if(s->flags & SEGFLLOCK)
- rlock(&s->rw);
- *seg = s;
- return (char *)s->data + (addr - s->start);
- }
- }
- fprint(2, "fault %.8ux (%d) @ %.8ux", addr, len, up->R[15]);
- return nil;
+ Segment **ss, *s;
+ for (ss = up->S; ss < up->S + SEGNUM; ss++) {+ if (*ss == nil)
+ continue;
+ s = *ss;
+ if (addr >= s->start && addr < s->start + s->size) {+ if (addr + len > s->start + s->size)
+ break;
+ if (s->flags & SEGFLLOCK)
+ rlock(&s->rw);
+ *seg = s;
+ return (char *)s->data + (addr - s->start);
+ }
+ }
+ panic("fault addr=%.8ux, (%d), PC=%.8ux\n", addr, len, up->R[15]);+ return nil;
}
-void *
+void*
vaddrnol(u32int addr, u32int len)
{- Segment *seg;
+ Segment *seg;
void *ret;
-
- ret = vaddr(addr, len, &seg);
+ ret = vaddr(addr, len, &seg);
segunlock(seg);
return ret;
}
@@ -94,6 +97,8 @@
if(len < 0)
len = strlen(targ) + 1;
ret = malloc(len);
+ if (ret == nil)
+ panic("%r");setmalloctag(ret, getcallerpc(&addr));
memcpy(ret, targ, len);
segunlock(seg);
@@ -115,6 +120,8 @@
segunlock(seg);
*buffered = 1;
v = malloc(len);
+ if (v == nil)
+ panic("%r");setmalloctag(v, getcallerpc(&addr));
return v;
}
--- a/kern/syscall.c
+++ b/kern/syscall.c
@@ -5,6 +5,7 @@
#include "error.h"
#include "user.h"
#include "sys.h"
+#include "proc.h"
static u32int
arg(int n)
@@ -161,21 +162,39 @@
static void
_sysstat(void)
{- u32int name, edir, nedir;
- char *namet;
- void *edirt;
- int copied, buffered;
-
- name = arg(0);
- namet = copyifnec(name, -1, &copied);
- edir = arg(1);
- nedir = arg(2);
- edirt = bufifnec(edir, nedir, &buffered);
- up->R[0] = noteerr(sysstat(namet, edirt, nedir), nedir);
- if(copied)
- free(namet);
- if(buffered)
- copyback(edir, up->R[0], edirt);
+ u32int name, edir, nedir;
+ char *namet;
+ void *edirt;
+ int copied, buffered;
+ Segment *seg;
+ print("sysstat\n");+
+ name = arg(0); // R0
+ print("sysstat: name=%.8ux, R13=%.8ux\n", name, up->R[13]);+ if (!vaddr(name, 1, &seg)) {+ print("sysstat: invalid name pointer %.8ux\n", name);+ cherrstr("invalid name pointer");+ up->R[0] = -1;
+ return;
+ }
+ namet = copyifnec(name, -1, &copied);
+ edir = arg(1); // R1
+ nedir = arg(2); // R2
+ print("sysstat: edir=%.8ux, nedir=%d\n", edir, nedir);+ if (nedir > 0 && !vaddr(edir, nedir, &seg)) {+ print("sysstat: invalid edir pointer %.8ux\n", edir);+ cherrstr("invalid edir pointer");+ if (copied)
+ free(namet);
+ up->R[0] = -1;
+ return;
+ }
+ edirt = bufifnec(edir, nedir, &buffered);
+ up->R[0] = noteerr(stat(namet, edirt, nedir), nedir);
+ if (copied)
+ free(namet);
+ if (buffered)
+ copyback(edir, up->R[0], edirt);
}
static void
@@ -184,7 +203,7 @@
u32int fd, edir, nedir;
void *edirt;
int buffered;
-
+ print("sysfstat\n");fd = arg(0);
edir = arg(1);
nedir = arg(2);
@@ -230,10 +249,10 @@
free(edirt);
}
-// TODO: This may be better done as a longjmp back
static void
_sysexits(void)
{+ print("Exiting\n");if(arg(0) == 0)
exits(nil);
else
@@ -271,7 +290,7 @@
char buf[ERRMAX], *srct;
u32int src, len;
int copied;
-
+ print("We're in syserrstr\n");src = arg(0);
len = arg(1);
srct = copyifnec(src, len, &copied);
@@ -319,7 +338,6 @@
up->R[0] = -1;
}
-
static void
_sysrfork(void)
{@@ -327,33 +345,37 @@
int rc, i;
Segment *s, *t;
Proc *p;
- int old;
flags = arg(0);
-
if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
(flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) ||
(flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) {+ werrstr("bad arg in rfork");up->R[0] = -1;
- cherrstr("bad arg in syscall");return;
}
if((flags & RFPROC) == 0) { if(flags & RFFDG) {- old = up->fd;
- up->fd = copyfd(up->fd);
- fddecref(old);
+ Fgrp *old = up->fgrp;
+ up->fgrp = dupfgrp(up->fgrp);
+ closefgrp(old);
}
if(flags & RFCFDG) {- old = up->fd;
- //up->fd = newfd();
- fddecref(old);
+ Fgrp *old = up->fgrp;
+ up->fgrp = dupfgrp(nil);
+ closefgrp(old);
}
- up->R[0] = noteerr(rfork(flags), 0);
+ up->R[0] = noteerr(sysrfork(flags), 0);
return;
}
- //incref(&nproc);
- p = emallocz(sizeof(Proc));
+ p = newproc();
+ if(p == nil) {+ fprint(2, "rfork: malloc failed for Proc");
+ werrstr("rfork: malloc failed");+ up->R[0] = -1;
+ return;
+ }
+ memset(p, 0, sizeof(Proc));
memcpy(p, up, sizeof(Proc));
for(i = 0; i < SEGNUM; i++) {s = p->S[i];
@@ -360,12 +382,20 @@
if(s == nil)
continue;
if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {- t = emallocz(sizeof(Segment));
- incref(t);
- t->size = s->size;
- t->start = s->start;
- t->dref = emalloc(sizeof(Ref) + s->size);
- memset(t->dref, 0, sizeof(Ref));
+ t = newseg(s->start, s->size, s->flags);
+ if(t == nil) {+ fprint(2, "rfork: newseg failed");
+ werrstr("rfork: newseg failed");+ up->R[0] = -1;
+ return;
+ }
+ t->dref = mallocz(sizeof(Ref) + s->size, 1);
+ if(t->dref == nil) {+ fprint(2, "rfork: malloc failed for Segment data");
+ werrstr("rfork: malloc failed");+ up->R[0] = -1;
+ return;
+ }
incref(t->dref);
t->data = t->dref + 1;
memcpy(t->data, s->data, s->size);
@@ -372,60 +402,76 @@
p->S[i] = t;
} else {incref(s->dref);
- incref(s);
+ incref(&s->ref);
}
}
-
if(flags & RFFDG)
- p->fd = copyfd(up->fd);
- //else if(flags & RFCFDG)
- // p->fd = newfd();
- //else
- // incref(up->fd);
-
- //incref(up->path);
- rc = rfork(RFMEM | flags);
- if(rc < 0) /* this should NEVER happen */
- sysfatal("rfork failed wtf: %r");+ p->fgrp = dupfgrp(up->fgrp);
+ else if(flags & RFCFDG)
+ p->fgrp = dupfgrp(nil);
+ else
+ incref(&up->fgrp->ref);
+ if(flags & RFNAMEG)
+ p->pgrp = newpgrp();
+ else
+ incref(&up->pgrp->ref);
+ if(flags & RFENVG)
+ p->egrp = newegrp();
+ else
+ incref(&up->egrp->ref);
+ rc = sysrfork(flags);
+ if(rc < 0) {+ fprint(2, "rfork: sysrfork failed: %r");
+ werrstr("rfork: %r");+ up->R[0] = -1;
+ return;
+ }
if(rc == 0) {- // up = p;
- //atexit(cleanup);
- up->pid = getpid();
+ _setproc(p);
+ atexit((void(*)(void))pexit);
+ p->pid = getpid();
inittos();
- // addproc(P);
+ osproc(p);
}
up->R[0] = rc;
}
-
static void
_sysexec(void)
{- u32int name, argv, *argvt;
- char *namet, **argvv;
+ u32int name, argv;
+ char *namet;
+ char **argvv;
int i, argc, rc;
Segment *seg1, *seg2;
+ u32int *argvt;
name = arg(0);
argv = arg(1);
- namet = strdup(vaddr(name, 0, &seg1));
- segunlock(seg1);
+ namet = estrdup((char*)vaddrnol(name, 0));
argvt = vaddr(argv, 0, &seg1);
for(argc = 0; argvt[argc]; argc++)
;
- argvv = emalloc(sizeof(char *) * argc);
+ argvv = mallocz(sizeof(char *) * (argc + 1), 1);
+ if(argvv == nil) {+ fprint(2, "exec: malloc failed for argv");
+ werrstr("exec: malloc failed");+ up->R[0] = -1;
+ free(namet);
+ return;
+ }
for(i = 0; i < argc; i++) {- argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
- segunlock(seg2);
+ argvv[i] = estrdup((char*)vaddrnol(argvt[i], 0));
}
+ argvv[argc] = nil;
segunlock(seg1);
rc = loadtext(namet, argc, argvv);
for(i = 0; i < argc; i++)
free(argvv[i]);
free(argvv);
+ free(namet);
if(rc < 0)
up->R[0] = noteerr(rc, 0);
- free(namet);
}
static void
@@ -589,7 +635,6 @@
addr = arg(0);
block = arg(1);
addrt = vaddrnol(addr, 4);
- // Still need semaphores
up->R[0] = noteerr(semacquire(addrt, block), 0);
}
@@ -603,7 +648,6 @@
addr = arg(0);
count = arg(1);
addrt = vaddr(addr, 4, &seg);
- // Still need semaphores
up->R[0] = noteerr(semrelease(addrt, count), 0);
segunlock(seg);
}
@@ -611,43 +655,44 @@
void
_syscall(void)
{- u32int n;
- static void (*calls[])(void) = {- [EXITS] = _sysexits,
- [CLOSE] = _sysclose,
- [OPEN] = _sysopen,
- [CREATE] = _syscreate,
- [PREAD] = _syspread,
- [PWRITE] = _syspwrite,
- [BRK_] = _sysbrk,
- [ERRSTR] = _syserrstr,
- [STAT] = _sysstat,
- [FSTAT] = _sysfstat,
- [WSTAT] = _syswstat,
- [FWSTAT] = _sysfwstat,
- [SEEK] = _sysseek,
- [CHDIR] = _syschdir,
- [FD2PATH] = _sysfd2path,
- [NOTIFY] = _sysnotify,
- [NOTED] = _sysnoted,
- [RFORK] = _sysrfork,
- [EXEC] = _sysexec,
- [AWAIT] = _sysawait,
- [PIPE] = _syspipe,
- [SLEEP] = _syssleep,
- [RENDEZVOUS] = _sysrendezvous,
- [BIND] = _sysbind,
- [UNMOUNT] = _sysunmount,
- [DUP] = _sysdup,
- [MOUNT] = _sysmount,
- [REMOVE] = _sysremove,
- [ALARM] = _sysalarm,
- [SEMACQUIRE] = _syssemacquire,
- [SEMRELEASE] = _syssemrelease,
- };
-
- n = up->R[0];
- if(n >= nelem(calls) || calls[n] == nil)
- fprint(2, "no such syscall %d @ %#ux", n, up->R[15] - 4);
- calls[n]();
+ u32int n;
+ static void (*calls[])(void) = {+ [EXITS] = _sysexits,
+ [CLOSE] = _sysclose,
+ [OPEN] = _sysopen,
+ [CREATE] = _syscreate,
+ [PREAD] = _syspread,
+ [PWRITE] = _syspwrite,
+ [BRK_] = _sysbrk,
+ [ERRSTR] = _syserrstr,
+ [STAT] = _sysstat,
+ [FSTAT] = _sysfstat,
+ [WSTAT] = _syswstat,
+ [FWSTAT] = _sysfwstat,
+ [SEEK] = _sysseek,
+ [CHDIR] = _syschdir,
+ [FD2PATH] = _sysfd2path,
+ [NOTIFY] = _sysnotify,
+ [NOTED] = _sysnoted,
+ [RFORK] = _sysrfork,
+ [EXEC] = _sysexec,
+ [AWAIT] = _sysawait,
+ [PIPE] = _syspipe,
+ [SLEEP] = _syssleep,
+ [RENDEZVOUS]= _sysrendezvous,
+ [BIND] = _sysbind,
+ [UNMOUNT] = _sysunmount,
+ [DUP] = _sysdup,
+ [MOUNT] = _sysmount,
+ [REMOVE] = _sysremove,
+ [ALARM] = _sysalarm,
+ [SEMACQUIRE]= _syssemacquire,
+ [SEMRELEASE]= _syssemrelease,
+ };
+
+ n = up->R[0];
+
+ print("syscall: calling handler for syscall %d\n", n);+ calls[n]();
+ print("syscall: handler for syscall %d completed\n", n);}
\ No newline at end of file
--- a/kern/sysproc.c
+++ b/kern/sysproc.c
@@ -3,6 +3,7 @@
#include "dat.h"
#include "fns.h"
#include "error.h"
+#include "proc.h"
#include "user.h"
#include "mem.h"
#include "sys.h"
@@ -12,7 +13,7 @@
#include <setjmp.h>
#undef rfork
-
+#undef read
jmp_buf exec_jmp;
static void
@@ -93,9 +94,9 @@
pid = fork();
if(pid){if(pid > 0)
- fprint(p[1], "%d", pid);
+ print("%d\n", pid);else
- fprint(p[1], "x %r");
+ print("x %r\n");close(p[1]);
_exit(0);
}else{@@ -193,197 +194,235 @@
return memchr((void*)a, c, i);
}
-#undef read
-/* Load text and data segments into memory */
+void
+addnote(char *msg)
+{+ int new;
+
+ new = up->notein + 1;
+ if((new - up->noteout) % NNOTE == 0)
+ return;
+ strncpy(up->notes[up->notein % NNOTE], msg, ERRMAX - 1);
+ up->notein = new;
+}
-/* the following code is not for the weak of heart */
void
donote(char *msg, ulong type)
{- int rc;
- u32int *ureg, *sp, uregp, msgp;
- char *msgb;
+ int rc;
+ u32int *ureg, *sp, uregp, msgp;
+ char *msgb;
- print("In donote\n");- if(up->notehandler == 0)
- exits(msg);
+ if(up->notehandler == 0)
+ exits(msg);
- clrex();
- uregp = up->R[13] - 18 * 4;
- ureg = vaddrnol(uregp, 18 * 4);
- memcpy(ureg, up->R, 15 * 4);
- ureg[15] = type;
- ureg[16] = up->CPSR;
- ureg[17] = up->R[15];
- up->R[13] = uregp;
- msgp = up->R[13] -= ERRMAX;
- msgb = vaddrnol(msgp, ERRMAX);
- strncpy(msgb, msg, ERRMAX);
- up->R[13] -= 3 * 4;
- sp = vaddrnol(up->R[13], 3 * 4);
- sp[0] = 0;
- sp[2] = msgp;
- up->R[0] = uregp;
- up->R[15] = up->notehandler;
- up->innote = 1;
- switch(rc = setjmp(up->notejmp) - 1) {- case -1:
- for(;;) {- step();
- }
- case NDFLT:
- exits(msg);
- case NCONT:
- break;
- default:
- sysfatal("unhandled noted argument %d", rc);- }
- up->innote = 0;
- ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
- memcpy(up->R, ureg, 15 * 4);
- up->CPSR = ureg[16];
- up->R[15] = ureg[17];
+ clrex();
+ uregp = up->R[13] - 18 * 4;
+ ureg = vaddrnol(uregp, 18 * 4);
+ memcpy(ureg, up->R, 15 * 4);
+ ureg[15] = type;
+ ureg[16] = up->CPSR;
+ ureg[17] = up->R[15];
+ up->R[13] = uregp;
+ msgp = up->R[13] -= ERRMAX;
+ msgb = vaddrnol(msgp, ERRMAX);
+ strncpy(msgb, msg, ERRMAX);
+ up->R[13] -= 3 * 4;
+ sp = vaddrnol(up->R[13], 3 * 4);
+ sp[0] = 0;
+ sp[2] = msgp;
+ up->R[0] = uregp;
+ up->R[15] = up->notehandler;
+ up->innote = 1;
+ switch(rc = setjmp(up->notejmp) - 1) {+ case -1:
+ for(;;) {+ step();
+ }
+ case NDFLT:
+ exits(msg);
+ case NCONT:
+ break;
+ default:
+ sysfatal("unhandled noted argument %d", rc);+ }
+ up->innote = 0;
+ ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
+ memcpy(up->R, ureg, 15 * 4);
+ up->CPSR = ureg[16];
+ up->R[15] = ureg[17];
}
-
static void
initstack(int argc, char **argv)
{- ulong tos, sp, ap, size, i, len;
-
- tos = USTKTOP - sizeof(Tos) * 2;
- sp = tos;
-
- size = 8;
- for(i = 0; i < argc; i++)
- size += strlen(argv[i]) + 5;
-
- sp -= size;
- sp &= ~7;
- up->R[0] = tos;
- up->R[1] = USTKTOP - 4;
- up->R[13] = sp;
-
+ ulong tos, sp, ap, size, i, len;
+
+ tos = (USTKTOP & ~7) - sizeof(Tos) * 2;
+ sp = tos;
+
+ size = 8;
+ for(i = 0; i < argc; i++)
+ size += strlen(argv[i]) + 5;
+
+ sp -= size;
+ sp &= ~7;
+ up->R[0] = tos;
+ up->R[1] = USTKTOP - 4;
+ up->R[13] = sp;
+
*(ulong *) vaddrnol(sp, 4) = argc;
- sp += 4;
- ap = sp + (argc + 1) * 4;
- for(i = 0; i < argc; i++) {- *(ulong *) vaddrnol(sp, 4) = ap;
- sp += 4;
- len = strlen(argv[i]) + 1;
- memcpy(vaddrnol(ap, len), argv[i], len);
- ap += len;
- }
- *(ulong *) vaddrnol(sp, 4) = 0;
- inittos();
+ sp += 4;
+ ap = sp + (argc + 1) * 4;
+ for(i = 0; i < argc; i++) {+ *(ulong *) vaddrnol(sp, 4) = ap;
+ sp += 4;
+ len = strlen(argv[i]) + 1;
+ memcpy(vaddrnol(ap, len), argv[i], len);
+ ap += len;
+ }
+ *(ulong *) vaddrnol(sp, 4) = 0;
+ inittos();
+
}
-
void
inittos(void)
{- ulong tos;
+ ulong tos;
- tos = USTKTOP - sizeof(Tos) * 2;
- ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = up->pid;
+ tos = (USTKTOP & ~7) - sizeof(Tos) * 2;
+ ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = up->pid;
}
-// TODO: fd has to go away here.
static int
-loadscript(int fd, char *file, int argc, char **argv)
+loadscript(Chan *tc, char *file, int argc, char **argv)
{- char buf[513], *p, **q, **nargv;
- int rc, nargc, i;
-
- seek(fd, 0, 0);
- rc = readn(fd, buf, 512);
- if(rc <= 0)
- goto invalid;
- close(fd);
- buf[rc] = 0;
- p = strchr(buf, '\n');
- if(p == nil)
- goto invalid;
- *p = 0;
- while(isspace(*--p))
- *p = 0;
- nargc = 0;
- p = buf + 2;
- while(*p) {- while(*p && isspace(*p))
- p++;
- nargc++;
- while(*p && !isspace(*p))
- p++;
- }
- if(nargc == 0)
- goto invalid;
- nargv = emallocz(sizeof(char *) * (nargc + argc));
- q = nargv;
- p = buf + 2;
- while(*p) {- while(*p && isspace(*p))
- p++;
- *(p-1) = 0;
- *q++ = p;
- while(*p && !isspace(*p))
- p++;
- }
- *q++ = file;
- for(i = 1; i < argc; i++)
- *q++ = argv[i];
- rc = loadtext(*nargv, argc + nargc, nargv);
- free(nargv);
- return rc;
+ char buf[513], *p, **q, **nargv;
+ int rc, nargc, i;
+
+ rc = devtab[tc->type]->read(tc, &buf, 512, 0);
+ if(rc <= 0)
+ goto invalid;
+ buf[rc] = 0;
+ p = strchr(buf, '\n');
+ if(p == nil)
+ goto invalid;
+ *p = 0;
+ while(isspace(*--p))
+ *p = 0;
+ nargc = 0;
+ p = buf + 2;
+ while(*p) {+ while(*p && isspace(*p))
+ p++;
+ nargc++;
+ while(*p && !isspace(*p))
+ p++;
+ }
+ if(nargc == 0)
+ goto invalid;
+ nargv = mallocz(sizeof(char *) * (nargc + argc), 1);
+ q = nargv;
+ p = buf + 2;
+ while(*p) {+ while(*p && isspace(*p))
+ p++;
+ *(p-1) = 0;
+ *q++ = p;
+ while(*p && !isspace(*p))
+ p++;
+ }
+ *q++ = file;
+ for(i = 1; i < argc; i++)
+ *q++ = argv[i];
+ rc = loadtext(*nargv, argc + nargc, nargv);
+ free(nargv);
+ return rc;
+
invalid:
- werrstr("exec header invalid");- return -1;
+ werrstr("exec header invalid");+ return -1;
}
int
loadtext(char *file, int argc, char **argv)
{- Segment *text, *data, *bss;
- char buf[2];
Chan *tc;
+ Segment *text, *data, *bss;
+ Exec hdr;
+ char buf[2];
+ vlong off;
int n;
- union {- struct {- Exec ex;
- uvlong hdr[1];
- } ehdr;
- char buf[256];
- } u;
-
+
+ /* Open the file using namespaced access */
tc = namec(file, Aopen, OEXEC, 0);
- n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
+ if(tc == nil) {+ print("cannot open %s: %r", file);+ return -1;
+ }
+
+ /* Peek the first two bytes */
+ devtab[tc->type]->read(tc, &buf, 2, 0);
+ if(buf[0] =='#' && buf[1] == '!') {+ return loadscript(tc, file, argc, argv);
+ }
- copyname(file);
- up->notehandler = up->innote = up->notein = up->noteout = 0;
- freesegs();
- memset(up->R, 0, sizeof(up->R));
- up->CPSR = 0;
- // Read instead with beswav(whatever)
- //text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
- //data = newseg(fp.dataddr, fp.datsz, SEGDATA);
- //bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
- //newseg(USTKTOP - STACKSIZE, STACKSIZE, SEGSTACK);
- // This also doesn't work, we want to read in the devtab way
- //seek(fd, fp.txtoff - fp.hdrsz, 0);
- //if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
- // sysfatal("%r");- //seek(fd, fp.datoff, 0);
- //if(readn(fd, data->data, fp.datsz) < fp.datsz)
- // sysfatal("%r");- //memset(bss->data, 0, bss->size);
- //up->R[15] = fp.entry;
- //if(havesymbols && syminit(fd, &fp) < 0)
- // fprint(2, "initializing symbol table: %r\n");
- //close(fd);
- fdclear(up->fd);
- initstack(argc, argv);
- resetfpa();
- return 0;
-}
+ n = devtab[tc->type]->read(tc, &hdr, sizeof(Exec), 0);
+ if(n != sizeof(Exec)) {+ print("short read on exec header");+ cclose(tc);
+ return -1;
+ }
+
+ if(beswal(hdr.magic) != E_MAGIC) {+ print("bad magic number in exec header: got 0x%lux, want 0x%lux", beswal(hdr.magic), E_MAGIC);+ cclose(tc);
+ return -1;
+ }
+
+ freesegs();
+ up->CPSR = 0;
+
+ /* Create segments: text, data, bss, stack */
+ text = newseg(beswal(hdr.entry), beswal(hdr.text) + sizeof(Exec), SEGTEXT);
+ data = newseg(beswal(hdr.entry) + beswal(hdr.text) + sizeof(Exec), beswal(hdr.data), SEGDATA);
+ bss = newseg(beswal(hdr.entry) + beswal(hdr.text) + sizeof(Exec) + beswal(hdr.data), beswal(hdr.bss), SEGBSS);
+ newseg((USTKTOP & ~7) - USTKSIZE, USTKSIZE, SEGSTACK);
+
+ /* Read text segment (including header) */
+ off = sizeof(Exec);
+ n = devtab[tc->type]->read(tc, text->data, beswal(hdr.text) + sizeof(Exec), off);
+ if(n != beswal(hdr.text) + sizeof(Exec)) {+ freesegs();
+ werrstr("short read on text segment: got %d, want %lud", n, beswal(hdr.text) + sizeof(Exec));+ cclose(tc);
+ return -1;
+ }
+
+ /* Read data segment */
+ off += beswal(hdr.text);
+ n = devtab[tc->type]->read(tc, data->data, beswal(hdr.data), off);
+ if(n != beswal(hdr.data)) {+ freesegs();
+ werrstr("short read on data segment: got %d, want %lud", n, beswal(hdr.data));+ cclose(tc);
+ return -1;
+ }
+
+ memset(bss->data, 0, bss->size);
+ up->R[15] = beswal(hdr.entry);
+
+ initstack(argc, argv);
+
+ //if(debug)
+ print("loadtext: PC=%.8ux, R1=%.8ux, R13=%.8ux\n", up->R[15], up->R[1], up->R[13]);+
+ /* Close the channel */
+ cclose(tc);
+ resetvfp();
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+++ b/kern/vfp.c
@@ -1,0 +1,158 @@
+#include <u.h>
+#include <lib.h>
+#include "dat.h"
+#include "fns.h"
+#include "proc.h"
+
+void
+resetvfp(void)
+{+ int i;
+
+ up->FPSR = 0x00000000;
+ for(i = 0; i < Nfpregs; i++)
+ up->F[i] = 0;
+}
+
+void
+vfpregtransfer(u32int instr)
+{+ u32int *Rt;
+ double *Fn;
+
+ Rt = up->R + ((instr>>12)&0xF);
+ Fn = up->F + ((instr>>16)&0xF);
+ switch((instr>>20)&0xF){+ case 0:
+ *((int*)Fn) = *Rt; break;
+ case 1:
+ *Rt = *((int*)Fn); break;
+ case 14:
+ up->FPSR = *Rt; break;
+ case 15:
+ if(Rt == (up->R + 15))
+ up->CPSR = up->FPSR;
+ else
+ *Rt = up->FPSR;
+ break;
+ default:
+ sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, up->R[15] - 4);+ }
+}
+
+void
+vfprmtransfer(u32int instr)
+{+ int n, d, off, sz;
+ void* ea;
+ Segment *seg;
+
+ n = (instr>>16) & 0xF;
+ d = (instr>>12) & 0xF;
+ off = (instr & 0xFF) << 2;
+ sz = instr & (1<<8);
+ if((instr & (1<<23)) == 0)
+ off = -off;
+ ea = vaddr(evenaddr(up->R[n] + off, 3), sz ? 8 : 4, &seg);
+ switch((instr>>20)&0x3){+ case 0:
+ if(sz)
+ *(double*)ea = up->F[d];
+ else
+ *(float*)ea = up->F[d];
+ break;
+ case 1:
+ if(sz)
+ up->F[d] = *(double*)ea;
+ else
+ up->F[d] = *(float*)ea;
+ break;
+ default:
+ sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, up->R[15] - 4);+ }
+ segunlock(seg);
+}
+
+void
+vfparithop(int opc, u32int instr)
+{+ int o;
+ double *Fd, *Fn, *Fm;
+
+ Fd = up->F + ((instr>>12)&0xF);
+ Fn = up->F + ((instr>>16)&0xF);
+ Fm = up->F + (instr&0xF);
+ o = ((opc&0x3)<<1) | (opc&0x8) | ((instr>>6)&0x1);
+
+ switch(o){+ case 4:
+ *Fd = *Fn * *Fm; break;
+ case 6:
+ *Fd = *Fn + *Fm; break;
+ case 7:
+ *Fd = *Fn - *Fm; break;
+ case 8:
+ *Fd = *Fn / *Fm; break;
+ default:
+ sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, up->R[15] - 4);+ }
+}
+
+void
+vfpotherop(u32int instr)
+{+ int o2, o3;
+ double *Fd, *Fm, F0;
+
+ Fd = up->F + ((instr>>12)&0xF);
+ Fm = up->F + (instr&0xF);
+ F0 = 0.0;
+ o2 = (instr>>16) & 0xF;
+ o3 = (instr>>6) & 0x3;
+
+ if((o3&1) == 0)
+ sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, up->R[15] - 4);+ switch(o2){+ case 0x5:
+ Fm = &F0;
+ case 0x4:
+ if(*Fd < *Fm)
+ up->FPSR = (up->FPSR & ~FLAGS) | flN;
+ else if(*Fd >= *Fm) {+ up->FPSR = (up->FPSR & ~FLAGS) | flC;
+ if(*Fd == *Fm)
+ up->FPSR |= flZ;
+ } else
+ up->FPSR = (up->FPSR & ~FLAGS) | flV | flC;
+ break;
+ case 0x8:
+ *Fd = *((int*)Fm); break;
+ case 0xD:
+ *((int*)Fd) = (int)*Fm; break;
+ default:
+ switch((o2<<1)|(o3>>1)){+ case 0:
+ case 15:
+ *Fd = *Fm; break;
+ case 1:
+ *Fd = fabs(*Fm); break;
+ case 2:
+ *Fd = -*Fm; break;
+ case 3:
+ *Fd = sqrt(*Fm); break;
+ default:
+ sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, up->R[15] - 4);+ }
+ }
+}
+
+void
+vfpoperation(u32int instr)
+{+ int o1;
+ o1 = (instr>>20) & 0xF;
+ if(o1 == 0xB)
+ vfpotherop(instr);
+ else
+ vfparithop(o1, instr);
+}
--- a/main.c
+++ b/main.c
@@ -48,17 +48,30 @@
exit(1);
}
-int
-notehandler(void *, char *note)
+void
+dump(void)
{+ int i;
+
+ for(i = 0; i < 16; i++) {+ print("R%2d %.8ux", i, up->R[i]);+ if((i % 4) == 3) print("\n");+ else print("\t");+ }
+}
+
+void
+notehandler(void *d, char *note)
+{+ USED(d);
if(strncmp(note, "sys:", 4) == 0)
- return 0;
+ return;
if(strncmp(note, "emu:", 4) == 0)
exits(note);
addnote(note);
- return 1;
+ return;
}
int
@@ -66,6 +79,7 @@
{extern ulong kerndate;
char *path, *file;
+ int debug = 0;
path = nil;
kerndate = seconds();
@@ -77,6 +91,9 @@
case 'p':
path = EARGF(usage());
break;
+ case 'd':
+ debug++;
+ break;
default:
usage();
} ARGEND;
@@ -111,24 +128,24 @@
bind(path, "/bin", MAFTER);
if(**argv == '/' || **argv == '.' || **argv == '#') {- // TODO: Export loadtext from the kernel
if(loadtext(*argv, argc, argv) < 0)
- sysfatal("loadtext: %r");- return;
+ panic("loadtext: %r");+ } else {+ file = smprint("/bin/%s", *argv);+ if(loadtext(file, argc, argv) < 0)
+ panic("loadtext: %r");+ free(file);
}
- file = smprint("/bin/%s", *argv);- if(loadtext(file, argc, argv) < 0)
- sysfatal("loadtext: %r");- free(file);
- // TODO: Export step() from the kernel
- atnotify(notehandler, 1);
+ notify(notehandler);
for(;;) {- // Kernel step, while this greys kernelspace/userspace this is the cleaner approach
+ if(debug)
+ dump();
step();
while((up->notein - up->noteout) % NNOTE) {donote(up->notes[up->noteout % NNOTE], 0);
- ainc(&up->noteout);
+ up->noteout++;
}
}
+ exits(0);
}
--
⑨