[openfirmware] [commit] r2183 - cpu/arm cpu/arm/Darwin cpu/arm/build cpu/x86 forth/lib
repository service
svn at openfirmware.info
Tue Apr 5 21:48:05 CEST 2011
Author: tooch
Date: Tue Apr 5 21:48:04 2011
New Revision: 2183
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2183
Log:
ARM Simulator - Fix the incredibly buggy shift logic.
ARM Assembler - Re-enhance (set) for ARMv6/v7...use movw/movt pairs.
ARM/Darwin - Use a make target that will compile the inflater under Xtools.
General - Add $case/$of/$endof/$endcase words yielding a case statement
that uses a string as a selector vice an integer.
Added:
cpu/arm/Darwin/
cpu/arm/Darwin/Makefile
forth/lib/strcase.fth
Modified:
cpu/arm/armsim.c
cpu/arm/assem.fth
cpu/arm/build/Makefile
cpu/arm/disassem.fth
cpu/arm/kerncode.fth
cpu/x86/kerncode.fth
forth/lib/build.sh
forth/lib/decomp.fth
forth/lib/loadcomm.fth
Added: cpu/arm/Darwin/Makefile
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ cpu/arm/Darwin/Makefile Tue Apr 5 21:48:04 2011 (r2183)
@@ -0,0 +1,25 @@
+# Darwin ARM tools
+
+BP = ../../..
+ZIPDIR = ${BP}/forth/wrapper/zip
+
+# Rationale for these flags:
+# -Oz optimizes for smallest possible size. (Apple-specific)
+# -fno-toplevel-reorder keeps inflate() as the first entry point.
+# -thumb gives 30%-50% improvement over ARM32.
+# -arch armv7 uses more powerful instructions for less space.
+# -static -nostartfiles allows us to link this as a static text image.
+# This set of flags generates an inflate.bin of 3546 bytes.
+
+CFLAGS = -Oz -arch armv7 -mthumb -static -nostartfiles -fno-toplevel-reorder
+
+INFLATEBIN = ../build/inflate.bin
+
+$(INFLATEBIN): inflate
+ segedit $< -extract __TEXT __text $@
+
+inflate: ${ZIPDIR}/inflate.c
+ ${CC} ${CFLAGS} -o $@ $<
+
+clean:
+ rm -f *.o inflate $(INFLATEBIN)
Modified: cpu/arm/armsim.c
==============================================================================
--- cpu/arm/armsim.c Tue Apr 5 17:13:03 2011 (r2182)
+++ cpu/arm/armsim.c Tue Apr 5 21:48:04 2011 (r2183)
@@ -82,19 +82,100 @@
struct { signed int imm24:24; } sext24;
#define BTGT { PC += sext24.imm24 = (IMM24 << 2); last_pc = 1; }
+int scout; // Hold the last bit shifted out
#define ROTATE(imm, rot) (((imm) >> (rot)) | ((imm) << (32-(rot))))
#define IMM32 ROTATE(IMM8, (ROT<<1))
-#define SHSRC (OP1 ? RS : IMM5)
-#define SHFT(res) \
-{ \
- switch (TYPE) { \
- case 0: res = RM << SHSRC; break; \
- case 1: res = RM >> SHSRC; break; \
- case 2: if (SHSRC == 0) { res = ((s32)(RM) < 0) ? -1 : 0; } else { res = (s32)(RM) >> SHSRC; } break; \
- case 3: res = ROTATE(RM, SHSRC); \
- } \
+#define TEST_SHIFT 0
+#if defined(TEST_SHIFT) && TEST_SHIFT
+#define EXIT(r) goto exit
+#else
+#define EXIT(r) return res
+#endif
+
+u32 shifter(u32 rm, u32 rs, u32 type, u32 imm, u32 imm5, u32 cin, u32 pc, u32 ir)
+{
+ u32 res, res2;
+ int cnt;
+
+#if defined(TEST_SHIFT) && TEST_SHIFT
+ u32 res2;
+ cnt = imm ? imm5 : rs;
+ switch (type) {
+ case 0: res = rm << cnt; break;
+ case 1: res = rm >> cnt; break;
+ case 2: if (cnt == 0) { res = ((s32)(rm) < 0) ? -1 : 0; } else { res = (s32)(rm) >> cnt; } break;
+ case 3: res = ROTATE(rm, cnt);
+ }
+ res2 = res;
+#endif
+
+ if (imm && (imm5 == 0)) {
+ if (type == 0) {
+ res = rm;
+ scout = cin;
+ EXIT(res);
+ return res;
+ }
+
+ if (type == 2) {
+ if ((s32)rm < 0) res = -1;
+ else res = 0;
+ scout = res & 1;
+ EXIT(res);
+ return res;
+ }
+
+ if (type == 3) {
+ res = (cin << 31) | (rm >> 1);
+ scout = rm & 1;
+ EXIT(res);
+ return res;
+ }
+ }
+
+ if (imm) {
+ if (imm5 == 0) cnt = 32;
+ else cnt = imm5;
+ } else cnt = rs & 31;
+
+ if (cnt == 0) {
+ res = rm;
+ scout = cin;
+ EXIT(res);
+ return res;
+ }
+
+ switch (type) {
+ case 0: res = rm << cnt; scout = rm >> (32 - cnt); break;
+ case 1: res = rm >> cnt; scout = rm >> (cnt - 1); break;
+ case 2: res = (s32)rm >> cnt; scout = rm >> (cnt - 1); break;
+ case 3: res = ROTATE(rm, cnt); scout = res >> 31;
+ } /* switch */
+
+ scout &= 1;
+
+ EXIT(res);
+
+#if defined(TEST_SHIFT) && TEST_SHIFT
+exit:
+ if (res != res2) {
+ char *shifts[] = {"lsl", "lsr", "asr", "ror"};
+ printf("PC: %x: %x ", pc, ir);
+ if (imm) {
+ printf("imm = #%d", imm5);
+ } else {
+ printf("RS = %d", rs & 31);
+ }
+ printf(", RM = %x, %s #%d; res = %x, res2 = %x\n", rm, shifts[type], cnt, res, res2);
+// while (1);
+ }
+ return res;
+#endif
}
+
+
+#define SHFT(res) res = shifter(RM, RS, TYPE, !OP1, IMM5, C, PC, instruction)
#define BF(sb, eb) ((u32)(((s32)0x80000000) >> (sb - eb))) >> (31 - sb);
@@ -122,7 +203,16 @@
if (S) { \
N = (res) >> 31; \
Z = (res == 0); \
-/* FIXME - possible problem with C bit - should be set to carry output from shifter */ \
+ } \
+}
+
+/* Factor in the shifted-out Carry. */
+#define SHFT_UPCC(res) \
+{ \
+ if (S) { \
+ N = (res) >> 31; \
+ Z = (res == 0); \
+ C = scout ? 1 : 0; \
} \
}
@@ -152,7 +242,7 @@
#define UNIMP(s) \
{ \
- printf("UNIMPLEMENTED '%s' op %02x s %d bxtype %02x\n", s, OP, S, BXTYPE); \
+ printf("UNIMPLEMENTED '%s' op %02x s %d bxtype %02x; Source line: %d\n", s, OP, S, BXTYPE, __LINE__); \
regdump(instruction, last_pc, 1); \
return; \
}
@@ -257,7 +347,7 @@
UNIMP("unconditional");
switch (OP) {
case 0x00: if (OP1 == 0 || OP2 == 0) {
- INSTR("and"); SHFT(res); RD = RN & res; UPCC(RD); break;
+ INSTR("and"); SHFT(res); RD = RN & res; SHFT_UPCC(RD); break;
}
switch (BXTYPE) {
case 0x9: INSTR("mul"); RN = RS * RM; UPCC(RN); break;
@@ -293,7 +383,7 @@
default: UNIMP("BXTYPE"); break;
} break;
case 0x01: if (OP1 == 0 || OP2 == 0) {
- INSTR("eor"); SHFT(res); RD = RN ^ res; UPCC(RD); break;
+ INSTR("eor"); SHFT(res); RD = RN ^ res; SHFT_UPCC(RD); break;
}
switch (BXTYPE) {
case 0x9: UNIMP("mla"); break;
@@ -628,13 +718,13 @@
default: UNIMP("BXTYPE"); break;
} break;
case 0x0c: if (OP1 == 0 || OP2 == 0) {
- INSTR("orr"); SHFT(res); RD = RN | res; UPCC(res); break;
+ INSTR("orr"); SHFT(res); RD = RN | res; SHFT_UPCC(RD);
} else {
switch (BXTYPE) {
case 0x1:
case 0x3:
case 0x5:
- case 0x7: INSTR("orr"); SHFT(res); RD = RN | res; UPCC(res);
+ case 0x7: INSTR("orr"); SHFT(res); RD = RN | res; SHFT_UPCC(RD);
break;
case 0x9: UNIMP("ldrex"); break;
// P=1, U=0, bit22=0, W=0 - offset/pre-index, subtract offset, register, no writeback
@@ -678,16 +768,16 @@
RD = RM; UPCC(RD); break;
} /* else fall through */
case 0x8:
- case 0x1: INSTR("lsl"); SHFT(RD); UPCC(RD); break;
+ case 0x1: INSTR("lsl"); SHFT(RD); SHFT_UPCC(RD); break;
case 0x2:
case 0xa:
- case 0x3: INSTR("lsr"); SHFT(RD); UPCC(RD); break;
+ case 0x3: INSTR("lsr"); SHFT(RD); SHFT_UPCC(RD); break;
case 0x4:
case 0xc:
- case 0x5: INSTR("asr"); SHFT(RD); UPCC(RD); break;
+ case 0x5: INSTR("asr"); SHFT(RD); SHFT_UPCC(RD); break;
case 0x6:
case 0xe:
- case 0x7: INSTR("ror"); SHFT(RD); UPCC(RD); break;
+ case 0x7: INSTR("ror"); SHFT(RD); SHFT_UPCC(RD); break;
case 0x9: UNIMP("ldrexd"); break;
// P=1, U=1, bit22=0, W=1 - offset/pre-index, add offset, register, writeback
case 0xb:
@@ -725,7 +815,7 @@
default: UNIMP("BXTYPE"); break;
}; break;
case 0x0e: if (OP1 == 0 || OP2 == 0) {
- INSTR("bic"); SHFT(res); RD = RN & ~res; UPCC(RD); break;
+ INSTR("bic"); SHFT(res); RD = RN & ~res; SHFT_UPCC(RD); break;
}
switch (BXTYPE) {
case 0x9: UNIMP("ldrexb"); break;
@@ -756,7 +846,7 @@
break;
} break;
case 0x0f: if (OP1 == 0 || OP2 == 0) {
- INSTR("mvn"); SHFT(res); RD = ~res; UPCC(RD); break;
+ INSTR("mvn"); SHFT(res); RD = ~res; SHFT_UPCC(RD); break;
} else {
switch (BXTYPE) {
case 0x9: UNIMP("ldrexh"); break;
Modified: cpu/arm/assem.fth
==============================================================================
--- cpu/arm/assem.fth Tue Apr 5 17:13:03 2011 (r2182)
+++ cpu/arm/assem.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -1076,6 +1076,7 @@
: mvn 01e0.0000 {cond/s} amode-rdop2 ;
: movw 0300.0000 {cond} amode-movw ;
+: movt 0340.0000 {cond} amode-movw ;
: mul 0000.0090 {cond/s} amode-mul ;
: mla 0020.0090 {cond/s} amode-mla ;
@@ -1140,6 +1141,20 @@
asm, \ const
051f.000c \ ldr rN,[pc,#-12]
;
+: movwt ( reg# imm -- )
+ \ newword contains conditional info we need to keep.
+ newword -rot ( newword reg# imm )
+ lwsplit swap ( newword reg# imm.hi imm.lo )
+ set-imm16 0300.0000 iop ( newword reg# imm.hi )
+ over rd-field !op \ movw rN,#<imm>
+ ?dup if ( newword reg# imm.hi )
+ rot is newword ( reg# imm.hi )
+ set-imm16 0340.0000 iop ( reg# )
+ rd-field !op \ movt rN,#<imm>
+ else
+ 2drop
+ then
+;
: (set) ( address? -- )
>r
0000.0000 {cond} init-operands
@@ -1165,11 +1180,7 @@
then
else ( reg# imm imm )
use-movw? if ( reg# imm imm )
- 1.0000 u< if ( reg# imm )
- set-imm16 0300.0000 ( reg# op ) \ movw rN,#<imm16>
- else ( reg# imm )
- false asm-const ( reg# op )
- then ( reg# op )
+ drop movwt exit
else ( reg# imm imm )
drop false asm-const ( reg# op )
then ( reg# op )
Modified: cpu/arm/build/Makefile
==============================================================================
--- cpu/arm/build/Makefile Tue Apr 5 17:13:03 2011 (r2182)
+++ cpu/arm/build/Makefile Tue Apr 5 21:48:04 2011 (r2183)
@@ -33,4 +33,4 @@
# Don't use *.dic so as not to remove builder.dic
clean:
rm -f tools.dic kernel.dic basefw.dic *.log headers *~ inflate.bin build *.tag
-
+ make -C ../${OS} clean
Modified: cpu/arm/disassem.fth
==============================================================================
--- cpu/arm/disassem.fth Tue Apr 5 17:13:03 2011 (r2182)
+++ cpu/arm/disassem.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -276,8 +276,9 @@
d#24 bit? 0= 5 2 bits 0= and if .alu-ext else .ld/st-ext then
;
-: .movw ( -- ) \ movw rN,#imm
- ." movw" {<cond>} op.rd, ." #"
+: .movtw ( -- ) \ movw rN,#imm
+ d#22 bit? if ." movt" else ." movw" then
+ {<cond>} op.rd, ." #"
d# 16 4bits d# 12 << 0 d# 12 bits or u.h
;
@@ -285,7 +286,7 @@
: ?pc-change ( -- ) d# 12 4bits d# 15 = end-found ! ;
: .alu-op ( -- ) \ d# 25 3 bits 0|1 =
- d#20 8bits h# 30 = if .movw exit then
+ d#20 8bits h# fb and h# 30 = if .movtw exit then
d#25 bit? 0= d# 4 bit? and d# 7 bit? and if .ext exit then
alu# h# d and h# d = if \ Moves
.alu {s} op.rd, .r/imm
Modified: cpu/arm/kerncode.fth
==============================================================================
--- cpu/arm/kerncode.fth Tue Apr 5 17:13:03 2011 (r2182)
+++ cpu/arm/kerncode.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -187,6 +187,20 @@
mov pc,r0
end-code
+\ execute-ip This word will call a block of Forth words given the address
+\ of the first word. It's used, for example, in try blocks where the
+\ a word calls 'try' and then the words that follow it are called repeatedly.
+\ This word, execute-ip, is used to transfer control back to the caller of
+\ try and execute the words that follow the call to try.
+
+\ see forth/lib/try.fth for more details.
+
+code execute-ip ( word-list-ip -- )
+ psh ip,rp
+ mov ip,tos
+ pop tos,sp
+c;
+
\ Run-time actions for compiling words
code branch ( -- )
@@ -331,7 +345,19 @@
code (endcase) ( n -- ) pop tos,sp c;
-code digit ( char base -- digit true | char false )
+\ ($endof) is the same as branch, and ($endcase) is a noop,
+\ but redefining them this way makes the decompiler much easier.
+\ code ($case) ( $ -- $ ) c;
+
+code ($endof) ( -- )
+\rel ldr r0,[ip]
+\rel add ip,ip,r0
+\abs ldr ip,[ip]
+c;
+
+code ($endcase) ( -- ) c;
+
+code digit ( char base -- digit true | char false )
mov r0,tos \ r0 base
ldr r1,[sp] \ r1 char
and r1,r1,#0xff
Modified: cpu/x86/kerncode.fth
==============================================================================
--- cpu/x86/kerncode.fth Tue Apr 5 17:13:03 2011 (r2182)
+++ cpu/x86/kerncode.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -222,6 +222,20 @@
\ Execute a Forth word given a code field address
code execute (s acf -- ) w pop 0 [w] jmp end-code
+\ execute-ip This word will call a block of Forth words given the address
+\ of the first word. It's used, for example, in try blocks where the
+\ a word calls 'try' and then the words that follow it are called repeatedly.
+\ This word, execute-ip, is used to transfer control back to the caller of
+\ try and execute the words that follow the call to try.
+
+\ see forth/lib/try.fth for more details.
+
+code execute-ip (s word-list-ip -- )
+ rp adec
+ ip 0 [rp] mov
+ ip pop
+c;
+
\ High level branch. The branch offset is compiled in-line.
code branch (s -- )
mloclabel bran1
@@ -318,6 +332,13 @@
code (endof) (s -- ) bran1 #) jmp end-code
code (endcase) (s n -- ) ax pop c;
+\ ($endof) is the same as branch, and ($endcase) is a noop,
+\ but redefining them this way makes the decompiler much easier.
+\ code ($case) ( $ -- $ ) c;
+
+code ($endof) (s -- ) bran1 #) jmp end-code
+code ($endcase) (s n -- ) c;
+
mloclabel yes assembler true # ax mov 1push c;
mloclabel no assembler false # ax mov 1push c;
Modified: forth/lib/build.sh
==============================================================================
--- forth/lib/build.sh Tue Apr 5 17:13:03 2011 (r2182)
+++ forth/lib/build.sh Tue Apr 5 21:48:04 2011 (r2183)
@@ -22,7 +22,7 @@
{
until [ -d ofw ]; do
if [ `pwd` = / ] ; then
- echo Can\'t find firmware root directory
+ echo "Can\'t find firmware root directory"
exit
fi
cd ..
Modified: forth/lib/decomp.fth
==============================================================================
--- forth/lib/decomp.fth Tue Apr 5 17:13:03 2011 (r2182)
+++ forth/lib/decomp.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -181,6 +181,8 @@
: +branch ( ip-of-branch -- next-ip ) ta1+ /branch + ;
: .endof ( ip -- ip' ) .." endof" indent +branch ;
: .endcase ( ip -- ip' ) indent .." endcase" indent ta1+ ;
+: .$endof ( ip -- ip' ) .." $endof" indent +branch ;
+: .$endcase ( ip -- ip' ) indent .." $endcase" indent ta1+ ;
: add-break ( break-address break-type -- )
end-breaks @ breaks 40 /n* + >= ( adr,type full? )
@@ -213,6 +215,13 @@
['] .endcase ?add-break
+branch
;
+: scan-$of ( ip-of-($of -- ip' )
+ dup >target dup +extent ( ip next-$of )
+ /branch - /token - ( ip $endof-addr )
+ dup ['] .$endof add-break ( ip $endof-addr )
+ ['] .$endcase ?add-break
+ +branch
+;
: scan-branch ( ip-of-?branch -- ip' )
dup dup forward-branch? if
>target dup +extent ( branch-target-address)
@@ -264,6 +273,7 @@
: .loop ( ip -- ip' ) -indent .." loop " +branch ;
: .+loop ( ip -- ip' ) -indent .." +loop " +branch ;
: .of ( ip -- ip' ) .." of " +branch ;
+: .$of ( ip -- ip' ) .." $of " +branch ;
\ first check for word being immediate so that it may be preceded
\ by [compile] if necessary
@@ -340,8 +350,8 @@
( 24 ) [compile] (n") ( 25 ) [compile] isdefer
( 26 ) [compile] isuser ( 27 ) [compile] isvalue
( 28 ) [compile] isconstant ( 29 ) [compile] isvariable
- ( 30 ) [compile] dummy ( 31 ) [compile] dummy
- ( 32 ) [compile] dummy ( 33 ) [compile] dummy
+ ( 30 ) [compile] ($of) ( 31 ) [compile] ($endof)
+ ( 32 ) [compile] ($endcase) ( 33 ) [compile] dummy
( 34 ) [compile] dummy ( 35 ) [compile] dummy
\ Print a word which has been classified by execution-class
@@ -361,8 +371,8 @@
( 24 ) .nstring ( 25 ) .is
( 26 ) .is ( 27 ) .is
( 28 ) .is ( 29 ) .is
- ( 30 ) dummy ( 31 ) dummy
- ( 32 ) dummy ( 32 ) dummy
+ ( 30 ) .$of ( 31 ) .$endof
+ ( 32 ) .$endcase ( 33 ) dummy
( 34 ) dummy ( 35 ) dummy
( default ) .word
;
@@ -385,8 +395,8 @@
( 24 ) skip-nstring ( 25 ) skip-word
( 26 ) skip-word ( 27 ) skip-word
( 28 ) skip-word ( 29 ) skip-word
- ( 30 ) dummy ( 31 ) dummy
- ( 32 ) dummy ( 32 ) dummy
+ ( 30 ) scan-$of ( 31 ) skip-branch
+ ( 32 ) skip-word ( 33 ) dummy
( 34 ) dummy ( 35 ) dummy
( default ) skip-word
;
Modified: forth/lib/loadcomm.fth
==============================================================================
--- forth/lib/loadcomm.fth Tue Apr 5 17:13:03 2011 (r2182)
+++ forth/lib/loadcomm.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -43,6 +43,7 @@
fload ${BP}/forth/lib/format.fth
fload ${BP}/forth/lib/stringar.fth
+fload ${BP}/forth/lib/strcase.fth
fload ${BP}/forth/lib/parses1.fth \ String parsing
Added: forth/lib/strcase.fth
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ forth/lib/strcase.fth Tue Apr 5 21:48:04 2011 (r2183)
@@ -0,0 +1,50 @@
+\ This section introduces a new set of words:
+\ $case $of $endof $endcase
+\ The semantics are very similar to the standard
+\ Forth case statement.
+
+\ Example of use:
+\ : foo ( $ -- )
+\ ( $ ) $case
+\ " abc" $of ." The string starts with abc" $endof
+\ " xyz" $of ." Oh, it's an xyz string" $endof
+\ ( $ ) ." **** It was " 2dup type
+\ $endcase
+
+\ The default clause is optional.
+\ When an $of clause is executed, the remaining selector string (past
+\ the matched string) remains on the string. It is the user's
+\ responsibility to dispose of the string.
+\ When a default clause is executed, the entire selector string is
+\ on the stack. The default clause must drop the selector, e.g., 2drop.
+
+\ At run time, ($of) tests the top of the stack against the selector.
+
+\ If the first N characters of the string supplied to $case are
+\ the same, the selector string is shortened and the following
+\ forth code is executed. If the first characters are not the
+\ same, execution continues at the point just following the
+\ the matching $endof
+
+\needs substring? fload ${BP}/forth/lib/substrin.fth
+
+: ($of) ( arg$ sel$ -- arg$' )
+ 4dup 2swap substring? if
+ nip /string
+ r> cell+ >r \ Return to next word in $of clause
+ else
+ 2drop
+ r> dup @ + >r \ Skip to matching $endof
+ then
+;
+
+: $case ( -- 0 ) +level 0 ; immediate
+: $of ( -- >m ) ['] ($of) +>mark ; immediate
+: $endof ( >m -- ) ['] ($endof) +>mark but ->resolve ; immediate
+
+: $endcase ( 0 [ >m ... ] -- )
+ compile ($endcase)
+ begin ?dup while ->resolve repeat
+ -level
+; immediate
+
More information about the openfirmware
mailing list